185 lines
4.4 KiB
JavaScript
Executable file
185 lines
4.4 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
/*
|
|
* Extracts translatable strings from manifest.json files.
|
|
*
|
|
*/
|
|
|
|
function fatal(message, code) {
|
|
console.log((filename || "manifest2po") + ": " + message);
|
|
process.exit(code || 1);
|
|
}
|
|
|
|
function usage() {
|
|
console.log("usage: manifest2po [-o output] input...");
|
|
process.exit(2);
|
|
}
|
|
|
|
var fs, path, stdio;
|
|
|
|
try {
|
|
fs = require('fs');
|
|
path = require('path');
|
|
stdio = require('stdio');
|
|
} catch (ex) {
|
|
fatal(ex.message, 127); /* missing looks for this */
|
|
}
|
|
|
|
var opts = stdio.getopt({
|
|
directory: { key: "d", args: 1, description: "Base directory for input files" },
|
|
output: { key: "o", args: 1, description: "Output file" },
|
|
from: { key: "f", args: 1, description: "File containing list of input files" },
|
|
});
|
|
|
|
if (!opts.from && opts.args.length < 1) {
|
|
usage();
|
|
}
|
|
|
|
var input = opts.args;
|
|
var entries = { };
|
|
|
|
/* Filename being parsed */
|
|
var filename = null;
|
|
|
|
prepare();
|
|
|
|
/* Decide what input files to process */
|
|
function prepare() {
|
|
if (opts.from) {
|
|
fs.readFile(opts.from, { encoding: "utf-8"}, function(err, data) {
|
|
if (err)
|
|
fatal(err.message);
|
|
input = data.split("\n").filter(function(value) {
|
|
return !!value;
|
|
}).concat(input);
|
|
step();
|
|
});
|
|
} else {
|
|
step();
|
|
}
|
|
}
|
|
|
|
/* Now process each file in turn */
|
|
function step() {
|
|
filename = input.shift();
|
|
if (filename === undefined) {
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
if (path.basename(filename) != "manifest.json")
|
|
return step();
|
|
|
|
fs.readFile(filename, { encoding: "utf-8"}, function(err, data) {
|
|
if (err)
|
|
fatal(err.message);
|
|
|
|
process_manifest(JSON.parse(data));
|
|
|
|
return step();
|
|
});
|
|
}
|
|
|
|
function process_manifest(manifest) {
|
|
if (manifest.menu)
|
|
process_menu(manifest.menu);
|
|
if (manifest.tools)
|
|
process_menu(manifest.tools);
|
|
}
|
|
|
|
function process_keywords(keywords) {
|
|
keywords.forEach(v => {
|
|
v.matches.forEach(keyword =>
|
|
push({
|
|
msgid: keyword,
|
|
locations: [ filename ]
|
|
})
|
|
);
|
|
});
|
|
}
|
|
|
|
function process_docs(docs) {
|
|
docs.forEach(doc => {
|
|
push({
|
|
msgid: doc.label,
|
|
locations: [ filename ]
|
|
})
|
|
});
|
|
}
|
|
|
|
function process_menu(menu) {
|
|
for (var m in menu) {
|
|
if (menu[m].label) {
|
|
push({
|
|
msgid: menu[m].label,
|
|
locations: [ filename ]
|
|
});
|
|
}
|
|
if (menu[m].keywords)
|
|
process_keywords(menu[m].keywords);
|
|
if (menu[m].docs)
|
|
process_docs(menu[m].docs);
|
|
}
|
|
}
|
|
|
|
/* Push an entry onto the list */
|
|
function push(entry) {
|
|
var key = entry.msgid + "\0" + entry.msgid_plural + "\0" + entry.msgctxt;
|
|
var prev = entries[key];
|
|
if (prev) {
|
|
prev.locations = prev.locations.concat(entry.locations);
|
|
} else {
|
|
entries[key] = entry;
|
|
}
|
|
}
|
|
|
|
/* Escape a string for inclusion in po file */
|
|
function escape(string) {
|
|
var bs = string.split('\\').join('\\\\').split('"').join('\\"');
|
|
return bs.split("\n").map(function(line) {
|
|
return '"' + line + '"';
|
|
}).join("\n");
|
|
}
|
|
|
|
/* Finish by writing out the strings */
|
|
function finish() {
|
|
var result = [
|
|
'msgid ""',
|
|
'msgstr ""',
|
|
'"Project-Id-Version: PACKAGE_VERSION\\n"',
|
|
'"MIME-Version: 1.0\\n"',
|
|
'"Content-Type: text/plain; charset=UTF-8\\n"',
|
|
'"Content-Transfer-Encoding: 8bit\\n"',
|
|
'"X-Generator: Cockpit manifest2po\\n"',
|
|
'',
|
|
];
|
|
|
|
var msgid, entry;
|
|
for (msgid in entries) {
|
|
entry = entries[msgid];
|
|
result.push('#: ' + entry.locations.join(" "));
|
|
if (entry.msgctxt)
|
|
result.push('msgctxt ' + escape(entry.msgctxt));
|
|
result.push('msgid ' + escape(entry.msgid));
|
|
if (entry.msgid_plural) {
|
|
result.push('msgid_plural ' + escape(entry.msgid_plural));
|
|
result.push('msgstr[0] ""');
|
|
result.push('msgstr[1] ""');
|
|
} else {
|
|
result.push('msgstr ""');
|
|
}
|
|
result.push('');
|
|
}
|
|
|
|
var data = result.join('\n');
|
|
if (!opts.output) {
|
|
process.stdout.write(data);
|
|
process.exit(0);
|
|
} else {
|
|
fs.writeFile(opts.output, data, function(err) {
|
|
if (err)
|
|
fatal(err.message);
|
|
process.exit(0);
|
|
});
|
|
}
|
|
}
|