diff --git a/sample/messages.no-target.xlf b/sample/messages.no-target.xlf new file mode 100644 index 0000000..e0a4355 --- /dev/null +++ b/sample/messages.no-target.xlf @@ -0,0 +1,26 @@ + + + + + + Hello i18n! + An introduction header for this sample + User welcome + + + Hello! + A hello world message for the localized component + localized.component.hello + + + Good bye! + A goodbye message for the localized component + localized.component.goodbye + + + Créé par le + Info création par qui / quand + + + + diff --git a/spec/translate.spec.js b/spec/translate.spec.js index 0a448a9..c0ab1bc 100644 --- a/spec/translate.spec.js +++ b/spec/translate.spec.js @@ -66,5 +66,21 @@ describe("translate", function() { expect(units.eq(3).find('source').html()).toBe('Créé par le '); }); + + describe("with no target", function() { + beforeEach(() => { + const messageData = fs.readFileSync('./sample/messages.no-target.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(target(1)).toBe(lang.localized.component.hello); + expect(target(2)).toBe(lang.localized.component.goodbye); + }); + }); + }); diff --git a/translate.js b/translate.js index b3d408d..1a6356d 100644 --- a/translate.js +++ b/translate.js @@ -2,6 +2,11 @@ const jp = require('jsonpath'); +const indent = node => { + const indent = node.parent().html().match(/^\s+/); + return indent !== null ? indent[0] : ''; +}; + /** * Fills in translations in XLIFF files based on 'meaning' metadata as a key. * @@ -14,11 +19,21 @@ const translate = (doc, lang, force) => { let stats = { count: 0, skip: 0 }; units - .filter(unit => doc(unit).find('note').length > 0) - .map(unit => ({ - target: doc(unit).find('target'), - id: doc(unit).find('note[from=meaning]').text() - })) + .map(unit => doc(unit)) + .filter(unit => unit.find('note').length > 0) + .map(unit => { + const source = unit.find('source'); + let target = unit.find('target'); + if (target.length === 0 && source.length === 1) { + target = doc(''); + source.after(indent(source), target); + } + + return { + target: target, + id: doc(unit).find('note[from=meaning]').text() + }; + }) .filter(d => d.id && isKey(d.id)) .forEach(d => { const query = '$.' + d.id;