Skip to content

Commit

Permalink
fix: ignore interpolations in source data
Browse files Browse the repository at this point in the history
  • Loading branch information
tsvetomir committed May 3, 2017
1 parent b9d6c8a commit 640cda0
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 148 deletions.
28 changes: 12 additions & 16 deletions bin/xlf-translate
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

const yaml = require('js-yaml');
const fs = require('fs');
const xml = require('xml2js');
const cheerio = require('cheerio');
const translate = require('../translate');

const args = (() => {
Expand All @@ -28,26 +28,22 @@ const args = (() => {
action: 'storeTrue'
});

parser.addArgument([ '-e', '--encoding' ], {
help: 'Specifies the XLIFF file encoding. Default is "utf-8".',
defaultValue: 'utf-8'
});

return parser.parseArgs();
})();

const langData = fs.readFileSync(args.lang_file);
const lang = yaml.safeLoad(langData);

const messageData = fs.readFileSync(args.file);
const parser = new xml.Parser();
parser.parseString(messageData, (err, result) => {
if (err) {
console.log('Oops, error occurred');
throw err;
}

const stats = translate(result, lang, args.force);

const builder = new xml.Builder();
const out = builder.buildObject(result);
const messageData = fs.readFileSync(args.file, { encoding: args.encoding });
const messages = cheerio.load(messageData, { xmlMode: true, decodeEntities: false });
const stats = translate(messages, lang, args.force);
const out = messages.html();

fs.writeFileSync(args.file, out);
console.log(`Done. Replaced ${stats.count} units, skipped ${stats.skip}.`);
});
fs.writeFileSync(args.file, out);
console.log(`Done. Replaced ${stats.count} units, skipped ${stats.skip}.`);

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"author": "Tsvetomir Tsonev",
"license": "BSD-3-Clause",
"dependencies": {
"cheerio": "0.22.0",
"js-yaml": "^3.7.0",
"jsonpath": "^0.2.9",
"xml2js": "^0.4.17"
"jsonpath": "^0.2.9"
},
"repository": {
"type": "git",
Expand Down
7 changes: 6 additions & 1 deletion sample/messages.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
<note priority="1" from="description">A goodbye message for the localized component</note>
<note priority="1" from="meaning">localized.component.goodbye</note>
</trans-unit>
<trans-unit id="225c24c98a62f1f8974e1c1206f6eac06d7e5b62" datatype="html">
<source>Créé par <x id="INTERPOLATION"/> le <x id="INTERPOLATION_1"/></source>
<target/>
<note priority="1" from="description">Info création par qui / quand</note>
</trans-unit>
</body>
</file>
</xliff>
</xliff>
5 changes: 5 additions & 0 deletions sample/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
<note priority="1" from="description">A goodbye message for the localized component</note>
<note priority="1" from="meaning">localized.component.goodbye</note>
</trans-unit>
<trans-unit id="225c24c98a62f1f8974e1c1206f6eac06d7e5b62" datatype="html">
<source>Créé par <x id="INTERPOLATION"/> le <x id="INTERPOLATION_1"/></source>
<target/>
<note priority="1" from="description">Info création par qui / quand</note>
</trans-unit>
</body>
</file>
</xliff>
108 changes: 0 additions & 108 deletions spec/message-data.js

This file was deleted.

35 changes: 25 additions & 10 deletions spec/translate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const yaml = require('js-yaml');
const fs = require('fs');
const xml = require('xml2js');
const cheerio = require('cheerio');
const translate = require('../translate');

const lang = {
Expand All @@ -18,38 +18,53 @@ describe("translate", function() {
let messages;
let units;

const target = (index, text) => units.eq(index).find('target').text(text);

beforeEach(() => {
messages = require('./message-data');
units = messages.xliff.file[0].body[0]['trans-unit'];
const messageData = fs.readFileSync('./sample/messages.xlf', { encoding: 'utf-8' });
messages = cheerio.load(messageData, { xmlMode: true, decodeEntities: false });
units = messages('trans-unit');
});

it("fills tagged units", function() {
translate(messages, lang);

expect(units[1].target[0]).toBe(lang.localized.component.hello);
expect(units[2].target[0]).toBe(lang.localized.component.goodbye);
expect(target(1)).toBe(lang.localized.component.hello);
expect(target(2)).toBe(lang.localized.component.goodbye);
});

it("skips translated tagged units", function() {
units[1].target[0] = 'Foo';
target(1, 'Foo');

translate(messages, lang);

expect(units[1].target[0]).toBe('Foo');
expect(target(1)).toBe('Foo');
});

it("overwrites translated tagged units with force", function() {
units[1].target[0] = 'Foo';
target(1, 'Foo');

translate(messages, lang, true);

expect(units[1].target[0]).toBe(lang.localized.component.hello);
expect(target(1)).toBe(lang.localized.component.hello);
});

it("skips regular units", function() {
translate(messages, lang);

expect(units[0].target[0]).toBe('');
expect(target(0)).toBe('');
});

it("skips units with interpolations", function() {
translate(messages, lang);

expect(target(3)).toBe('');
});

it("outputs interpolations", function() {
translate(messages, lang);

expect(units.eq(3).find('source').html()).toBe('Créé par <x id="INTERPOLATION"/> le <x id="INTERPOLATION_1"/>');
});
});

21 changes: 10 additions & 11 deletions translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@ const jp = require('jsonpath');
/**
* Fills in translations in XLIFF files based on 'meaning' metadata as a key.
*
* @param messages an XLIFF document parsed with xml2js
* @param doc an XLIFF document parsed with cheerio
* @param lang a tree of keys and their corresponding translations
* @return statistics the messages will be filled in-place
*/
const translate = (messages, lang, force) => {
const units = jp.query(messages, '$..["trans-unit"]')[0];
const translate = (doc, lang, force) => {
const units = doc('trans-unit').toArray();
let stats = { count: 0, skip: 0 };

units
.filter(hasNotes)
.filter(unit => doc(unit).find('note').length > 0)
.map(unit => ({
target: unit.target,
id: meaning(unit)
target: doc(unit).find('target'),
id: doc(unit).find('note[from=meaning]').text()
}))
.filter(d => isKey(d.id))
.filter(d => d.id && isKey(d.id))
.forEach(d => {
const query = '$.' + d.id;
const match = jp.query(lang, query);

if (match.length === 1) {
if (d.target[0] === '' || force) {
d.target[0] = match[0];
if (d.target.text() === '' || force) {
d.target.text(match[0]);
stats.count++;
} else if (!force) {
stats.skip++;
Expand All @@ -37,9 +37,8 @@ const translate = (messages, lang, force) => {
return stats;
};


const isKey = val => !!val.match(/^[a-zA-Z0-9.]*$/);
const hasNotes = u => !!u.note;
const meaning = unit => unit.note.find(note => note['$'].from === 'meaning')['_'];

module.exports = translate;

0 comments on commit 640cda0

Please sign in to comment.