To extract message, run following command:
yarn extract-i18n
{ | |
"projects": { | |
"my-app": { | |
"architech": { | |
... | |
... | |
"xliffmerge": { | |
"builder": "@ngx-i18nsupport/tooling:xliffmerge", | |
"options": { | |
"xliffmergeOptions": { | |
"i18nFormat": "xlf", | |
"srcDir": "src/i18n", | |
"genDir": "src/i18n", | |
"defaultLanguage": "en", | |
"languages": [ | |
"en", | |
"fr" | |
"ru" | |
"vi" | |
] | |
} | |
} | |
}, | |
... | |
} | |
} | |
} | |
} |
// path: tools/xlf-merge/index.js | |
#!/usr/bin/env node | |
const program = require('commander'); | |
const fs = require('fs'); | |
const convert = require('xml-js'); | |
const shell = require('shelljs'); | |
const mergeXlf = require('./merge-xlf'); | |
function runMerge(inputPaths, outputPath) { | |
const inputFiles = (function*() { yield* shell.ls(inputPaths); })(); | |
const sourceFile = inputFiles.next().value; | |
console.log('Initial file', sourceFile); | |
let fileContent = fs.readFileSync(sourceFile).toString(); | |
let output = convert.xml2js(fileContent); | |
for (let fileIter = inputFiles.next(); !fileIter.done; fileIter = inputFiles.next()) { | |
fileContent = fs.readFileSync(fileIter.value).toString(); | |
output = mergeXlf(output, convert.xml2js(fileContent), fileIter.value); | |
} | |
const outXml = convert.js2xml(output); | |
fs.writeFileSync(outputPath, outXml); | |
console.log('Generated output file', outputPath); | |
} | |
//runMerge(['data/test3/generic.xlf', 'data/test3/home-page.xlf', 'data/test3/lesson.xlf'], 'data/test3/out.xlf'); | |
//return; | |
program | |
.version('1.0.3') | |
.usage('[options] <input files or pattern such as *.xlf ...>') | |
.option('-o, --output <output>', 'Output file name') | |
.parse(process.argv); | |
if (program.args === 0 || !program.output) { | |
program.help(); | |
} | |
try { | |
runMerge(program.args, program.output); | |
} | |
catch (err) { | |
console.error(err); | |
} |
# Angular 9 come with new Ivy engine, xi18n tool do not support for new engine so we can't extract translate messages. | |
# This script tool support extract i18n from templates and ts file | |
# Install require package | |
yarn add shx @locl/cli xml-js @ngx-i18nsupport/ngx-i18nsupport @ngx-i18nsupport/tooling |
// path: tools/xlf-merge/merge-xlf.js | |
module.exports = function(first, second, fileName) { | |
function fail(message) { | |
throw new Error(message + ' File name: ' + fileName + '.'); | |
} | |
function getElement(src, path, isOptional) { | |
let result = src; | |
let breadcrumbs = ''; | |
for (const pnode of path) { | |
breadcrumbs += '/' + pnode; | |
if (!result.elements) { | |
if (!isOptional) { | |
fail(breadcrumbs + ' - expected element ' + pnode + ' not found. Make sure that the XLF file schema is correct.'); | |
} else { | |
return null; | |
} | |
} | |
result = result.elements.find(e => e.name === pnode); | |
if (!result) { | |
if (!isOptional) { | |
fail('Element ' + breadcrumbs + ' not found. Make sure that the XLF file schema is correct.'); | |
} else { | |
return null; | |
} | |
} | |
} | |
return result; | |
} | |
function getContent(src) { | |
const result = ((src && src.elements) || []).find(e => e.type === 'text'); | |
return result ? result.text : ''; | |
} | |
function* getTransUnits(root) { | |
if (!root.elements) { | |
console.log('Skipping ', fileName, '- no trans-units found.'); | |
return; | |
} | |
for (const el of root.elements) { | |
if (el.name === 'trans-unit') { | |
yield el; | |
} | |
} | |
} | |
const transPath = ['xliff', 'file', 'body']; | |
const srcRoot = getElement(first, transPath); | |
const tgtRoot = getElement(second, transPath); | |
const tgtTransUnits = [...getTransUnits(tgtRoot)]; | |
let numMergedTransUnits = 0; | |
function findTgtById(id) { | |
return tgtTransUnits.find(t => t.attributes && t.attributes.id === id); | |
} | |
for (const srcTransUnit of getTransUnits(srcRoot)) { | |
const id = srcTransUnit.attributes.id; | |
const content = getContent(getElement(srcTransUnit, ['target'], true)); | |
const matchingTgt = findTgtById(id); | |
if (matchingTgt) { | |
const tgtContent = getContent(getElement(matchingTgt, ['target'], true)); | |
if (content !== tgtContent) { | |
console.log(`"${content}"`, ' <- ', id, ' -> ', `"${tgtContent}"`); | |
} | |
} else { | |
tgtRoot.elements.push(srcTransUnit); | |
numMergedTransUnits++; | |
} | |
} | |
console.log(fileName, ' -> ', numMergedTransUnits, 'translations merged'); | |
return second; | |
} |
// Add following scripts to package.json file | |
// Asume | |
{ | |
"merge-i18n": "node ./tools/xlf-merge/ src/i18n/tool/*.en.xlf -o src/i18n/messages.xlf", | |
"gen-i18n": "yarn shx rm -rf src/i18n/tool && yarn locl extract -s=dist/web/*.js -f=xlf -o=src/i18n/tool/ && yarn merge-i18n", | |
"extract-i18n": "ng build --prod && yarn gen-i18n && ng run my-app:xliffmerge && yarn shx rm -rf src/i18n/tool", | |
} |