Skip to content

Commit

Permalink
New: Added xliff translations (fixes #3624) (#3625)
Browse files Browse the repository at this point in the history
* New: Added xliff translations (fixes #3624)

* Remove console log

* HTML escaping

* Remove imports

* Switch to xliff 1.2

* Update grunt/helpers/Translate.js

Co-authored-by: Cahir O'Doherty <[email protected]>

---------

Co-authored-by: Cahir O'Doherty <[email protected]>
  • Loading branch information
1 parent 5f5f53a commit 94dbd41
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 14 deletions.
101 changes: 99 additions & 2 deletions grunt/helpers/Translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const _ = require('lodash');
const fs = require('fs-extra');
const csv = require('csv');
const { XMLParser } = require('fast-xml-parser');
const async = require('async');
const globs = require('globs');
const jschardet = require('jschardet');
Expand Down Expand Up @@ -177,7 +178,60 @@ class Translate {
const filePath = path.join(outputFolder, 'export.json');
this.log(`Exporting json to ${filePath}`);
fs.writeJSONSync(filePath, exportTextData, { spaces: 2 });
return;
return this;
}

if (['xliff', 'xlf'].includes(this.format)) {
// create csv for each file
const outputGroupedByFile = exportTextData.reduce((prev, current) => {
if (!prev.hasOwnProperty(current.file)) {
prev[current.file] = [];
}
prev[current.file].push(current);
return prev;
}, {});

// xliff 2.0
// const output = `<?xml version="1.0" encoding="UTF-8"?>
// <xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="${this.masterLang}" trgLang="${this.masterLang}">
// ${Object.entries(outputGroupedByFile).map(([fileName, entries]) => {
// return ` <file id="${fileName}">
// ${entries.map(item => {
// const value = /[<>&"'/]/.test(item.value)
// ? `<![CDATA[${item.value}]]>`
// : item.value;
// return ` <unit id="${item.id}${item.path}">
// <segment>
// <source xml:space="preserve">${value}</source>
// <target xml:space="preserve">${value}</target>
// </segment>
// </unit>
// `;
// }).filter(Boolean).join('')} </file>
// `;
// }).join('')}</xliff>`;

// xliff 1.2
const output = `<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2">
${Object.entries(outputGroupedByFile).map(([fileName, entries]) => {
return ` <file original="${fileName}" source-language="${this.masterLang}" target-language="${this.masterLang}"><body>
${entries.map(item => {
const value = /[<>&"'/]/.test(item.value)
? `<![CDATA[${item.value}]]>`
: item.value;
return ` <trans-unit id="${item.id}${item.path}">
<source>${value}</source>
<target>${value}</target>
</trans-unit>
`;
}).filter(Boolean).join('')} </body></file>
`;
}).join('')}</xliff>`;
const filePath = path.join(outputFolder, 'source.xlf');
this.log(`Exporting xliff to ${filePath}`);
fs.writeFileSync(filePath, `${output}`);
return this;
}

// create csv for each file
Expand Down Expand Up @@ -246,6 +300,8 @@ class Translate {
}
format = uniqueFileExtensions[0];
switch (format) {
case 'xlf':
case 'xliff':
case 'csv':
case 'json':
this.log(`Format autodetected as ${format}`);
Expand All @@ -255,6 +311,8 @@ class Translate {
}
}

if (format === 'xliff') format = 'xlf';

// discover import files
const langFiles = globs.sync([`${inputFolder}/*.${format}`]);
if (langFiles.length === 0) {
Expand All @@ -281,8 +339,46 @@ class Translate {
case 'json':
importData = fs.readJSONSync(langFiles[0]);
break;
case 'xliff':
case 'xlf': {
importData = [];
await async.each(langFiles, (filename, done) => {
const XMLData = fs.readFileSync(filename);
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: ''
});
const xml = parser.parse(XMLData);
// xliff 2.0
// for (const file of xml.xliff.file) {
// for (const unit of file.unit) {
// const [ id, ...path ] = unit.id.split('/');
// importData.push({
// file: file.id,
// id,
// path: path.filter(Boolean).join('/'),
// value: unit.segment.target['#text']
// });
// }
// }
// xliff 1.2
for (const file of xml.xliff.file) {
for (const unit of file.body['trans-unit']) {
const [ id, ...path ] = unit.id.split('/');
importData.push({
file: file.original,
id,
path: path.filter(Boolean).join('/'),
value: unit.source
});
}
}
done();
});
break;
}
case 'csv':
default:
default: {
importData = [];
const lines = [];
await async.each(langFiles, (filename, done) => {
Expand Down Expand Up @@ -349,6 +445,7 @@ class Translate {
throw new Error(`Error processing CSV files: ${err}`);
});
break;
}
}

// check import validity
Expand Down
22 changes: 10 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"chalk": "^2.4.1",
"columnify": "^1.5.4",
"csv": "^5.5.3",
"fast-xml-parser": "^4.5.0",
"fs-extra": "^8.1.0",
"globs": "^0.1.4",
"grunt": "^1.6.1",
Expand Down

0 comments on commit 94dbd41

Please sign in to comment.