arb-convert
Version:
Convert Application Resource Bundle (ARB) translation files to other translation formats and back
262 lines (261 loc) • 10.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.gettextToJs = exports.gettextString = exports.gettextComment = exports.timezoneOffset = exports.formatDate = exports.parse = exports.convert = void 0;
var zeroPad_1 = __importDefault(require("../util/zeroPad"));
var MAX_CHAR_WIDTH = 80;
function convert(_a) {
var source = _a.source, target = _a.target, original = _a.original, sourceLanguage = _a.sourceLanguage, targetLanguage = _a.targetLanguage;
var sourceJs = JSON.parse(source);
var targetJs = target ? JSON.parse(target) : '';
var content = '';
// Header
content += ("\n# Translation converted from ARB\n# original: " + (original || '') + "\n# srcLang: " + (sourceLanguage || '') + "\n# trgLang: " + (targetLanguage || '') + "\nmsgid \"\"\nmsgstr \"\"\n\"PO-Revision-Date: " + formatDate(new Date(Date.now())) + "\"\n\"MIME-Version: 1.0\"\n\"Content-Type: text/plain; charset=UTF-8\"\n\"Content-Transfer-Encoding: 8bit\"\n ").trim();
// white-space
// # translator-comments
// #. extracted-comments
// #: reference…
// #, flag…
// #| msgid previous-untranslated-string
// msgctxt context
// msgid untranslated-string
// msgstr translated-string
Object.keys(sourceJs)
.filter(function (key) { return key[0] !== '@'; })
.forEach(function (key) {
var sourceString = sourceJs[key];
var targetString = (targetJs && targetJs[key]) || '';
var _a = sourceJs["@" + key], description = _a.description, placeholders = _a.placeholders;
content += '\n';
if (description) {
content += "\n" + gettextComment('#.', description, MAX_CHAR_WIDTH);
}
Object.keys(placeholders).forEach(function (paramName) {
Object.keys(placeholders[paramName]).forEach(function (property) {
var example = "{" + paramName + "} " + property + ": " + placeholders[paramName][property];
content += "\n" + gettextComment('#.', example, MAX_CHAR_WIDTH);
});
});
content += "\n" + gettextString('msgctxt', key, MAX_CHAR_WIDTH);
content += "\n" + gettextString('msgid', sourceString, MAX_CHAR_WIDTH);
content += "\n" + gettextString('msgstr', targetString, MAX_CHAR_WIDTH);
});
content += '\n';
return { content: content };
}
exports.convert = convert;
function parse(_a) {
var content = _a.content;
var gettext = gettextToJs(content);
var srcArb = {};
var trgArb = {};
var original = '';
var sourceLanguage = 'en-US';
var targetLanguage = '';
srcArb['@@locale'] = '';
srcArb['@@last_modified'] = '';
trgArb['@@locale'] = '';
trgArb['@@last_modified'] = '';
gettext.forEach(function (entry) {
// Header
if (entry.msgctxt === '' && entry.msgid === '') {
entry.translatorCommentLines.forEach(function (comment) {
if (comment.startsWith('original: ')) {
original = comment.substr(10);
}
else if (comment.startsWith('srcLang: ')) {
sourceLanguage = comment.substr(9);
}
else if (comment.startsWith('trgLang: ')) {
targetLanguage = comment.substr(9);
}
});
}
else {
var key = entry.msgctxt.replace('\\n', '\n');
var srcString = entry.msgid.replace('\\n', '\n');
var trgString = entry.msgstr.replace('\\n', '\n');
var placeholders_1 = {};
var description_1 = '';
entry.extractedCommentLines.forEach(function (comment) {
var match = comment.match(/^\{([\w-]+)\} (.*): (.*)$/);
if (match) {
var field = match[1], name_1 = match[2], value = match[3];
placeholders_1[field] = placeholders_1[field] || {};
placeholders_1[field][name_1] = value;
}
else {
description_1 += comment;
}
});
srcArb[key] = srcString;
srcArb["@" + key] = {
description: description_1,
type: 'text',
placeholders: placeholders_1,
};
if (targetLanguage) {
trgArb[key] = trgString;
trgArb["@" + key] = {
description: description_1,
type: 'text',
placeholders: placeholders_1,
};
}
}
});
srcArb['@@locale'] = sourceLanguage.replace('-', '_');
srcArb['@@last_modified'] = new Date(Date.now()).toISOString();
if (targetLanguage) {
trgArb['@@locale'] = targetLanguage.replace('-', '_');
trgArb['@@last_modified'] = new Date(Date.now()).toISOString();
}
var source = JSON.stringify(srcArb, null, 2);
var target = targetLanguage ? JSON.stringify(trgArb, null, 2) : '';
return {
source: source,
target: target,
original: original,
sourceLanguage: sourceLanguage,
targetLanguage: targetLanguage,
};
}
exports.parse = parse;
// YEAR-MO-DA HO:MI+ZONE, e.g. 2008-07-22 18:13+0200
function formatDate(date) {
return date.getFullYear() + "-" + zeroPad_1.default(date.getMonth() + 1) + "-" + zeroPad_1.default(date.getDate()) + " " + zeroPad_1.default(date.getHours()) + ":" + zeroPad_1.default(date.getMinutes()) + timezoneOffset(date);
}
exports.formatDate = formatDate;
function timezoneOffset(date) {
var offset = date.getTimezoneOffset();
var sign = offset <= 0 ? '+' : '-';
var hours = Math.floor(Math.abs(offset) / 60);
var minutes = Math.abs(offset) % 60;
return sign + zeroPad_1.default(hours) + zeroPad_1.default(minutes);
}
exports.timezoneOffset = timezoneOffset;
function gettextComment(prefix, value, maxCharWidth) {
var splitValue = [];
var val = value;
while (val.length > maxCharWidth - prefix.length - 1) {
splitValue.push(prefix + " " + val.substr(0, maxCharWidth - prefix.length - 1));
val = val.substr(maxCharWidth - prefix.length - 1);
}
splitValue.push(prefix + " " + val);
return splitValue.join('\n');
}
exports.gettextComment = gettextComment;
function gettextString(prefix, value, maxCharWidth) {
var val = value.replace(/\n/, '\\n');
if (val.length <= maxCharWidth - prefix.length - 3) {
return prefix + " \"" + val + "\"";
}
var splitValue = [prefix + " \"\""];
while (val.length > maxCharWidth - prefix.length - 2) {
splitValue.push("\"" + val.substr(0, maxCharWidth - 2) + "\"");
val = val.substr(maxCharWidth - 2);
}
splitValue.push("\"" + val + "\"");
return splitValue.join('\n');
}
exports.gettextString = gettextString;
function gettextToJs(content) {
var result = [];
var multilineScope = '';
var translatorCommentLines = [];
var extractedCommentLines = [];
var references = [];
var flags = [];
var msgctxt = '';
var msgid = '';
var msgstr = '';
content.split('\n').forEach(function (line) {
if (line.trim() === '') {
// End of block
result.push({
translatorCommentLines: translatorCommentLines,
extractedCommentLines: extractedCommentLines,
references: references,
flags: flags,
msgctxt: msgctxt,
msgid: msgid,
msgstr: msgstr,
});
// Reset
multilineScope = '';
translatorCommentLines = [];
extractedCommentLines = [];
references = [];
flags = [];
msgctxt = '';
msgid = '';
msgstr = '';
return;
}
if (multilineScope !== '') {
if (line.startsWith('"')) {
var continuedText = line.substr(1, line.length - 2);
// eslint-disable-next-line default-case
switch (multilineScope) {
case 'msgctxt':
msgctxt += continuedText;
break;
case 'msgid':
msgid += continuedText;
break;
case 'msgstr':
msgstr += continuedText;
break;
}
}
else {
multilineScope = '';
}
}
var prefix = line.substr(0, line.indexOf(' '));
var text = line.substr(line.indexOf(' ') + 1);
// eslint-disable-next-line default-case
switch (prefix) {
case '#':
translatorCommentLines.push(text);
break;
case '#.':
extractedCommentLines.push(text);
break;
case '#:':
references = references.concat(text.split(',').map(function (part) { return part.trim(); }));
break;
case '#,':
flags = flags.concat(text.split(',').map(function (part) { return part.trim(); }));
break;
case 'msgctxt':
if (text === '""') {
multilineScope = prefix;
}
else {
msgctxt = text.substr(1, text.length - 2);
}
break;
case 'msgid':
if (text === '""') {
multilineScope = prefix;
}
else {
msgid = text.substr(1, text.length - 2);
}
break;
case 'msgstr':
if (text === '""') {
multilineScope = prefix;
}
else {
msgstr = text.substr(1, text.length - 2);
}
break;
}
});
return result;
}
exports.gettextToJs = gettextToJs;