@ni/xliff-to-json-converter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/commonjs/cli.js +34 -0
- package/dist/commonjs/convert.js +79 -0
- package/dist/commonjs/json-file.js +14 -0
- package/dist/commonjs/util.js +2 -0
- package/dist/commonjs/xliff-file.js +14 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# XLIFF to JSON Converter for Angular
|
|
2
|
+
|
|
3
|
+
The `@ni/xliff-to-json-converter` library converts XLIFF translation files to Angular's JSON format so that they can be loaded at runtime in Angular apps.
|
|
4
|
+
|
|
5
|
+
# Usage
|
|
6
|
+
|
|
7
|
+
1. Install in your Angular app's `devDependencies`:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm install -D @ni/xliff-to-json-converter
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Add scripts to your app's `package.json` to convert translated XLIFF files to JSON.
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
"scripts": {
|
|
17
|
+
"i18n:convert": "npm run i18n:convert:de && npm run i18n:convert:ja && npm run i18n:convert:zh",
|
|
18
|
+
"i18n:convert:de": "xliff-to-json-converter --source src/locales/messages.de.xlf --destination src/locales/messages.de.json",
|
|
19
|
+
"i18n:convert:ja": "xliff-to-json-converter --source src/locales/messages.ja.xlf --destination src/locales/messages.ja.json",
|
|
20
|
+
"i18n:convert:zh": "xliff-to-json-converter --source src/locales/messages.zh.xlf --destination src/locales/messages.zh.json",
|
|
21
|
+
},
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
3. Ensure those converted files are generated at build time and not checked in to source.
|
|
25
|
+
|
|
26
|
+
# Context
|
|
27
|
+
|
|
28
|
+
NI employees can see more info about our [recommended Angular localization toolchain in the NI internal wiki](https://dev.azure.com/ni/DevCentral/_wiki/wikis/AppCentral.wiki/6636/Internationalization-(Angular)).
|
|
29
|
+
|
|
30
|
+
# Contributing
|
|
31
|
+
|
|
32
|
+
See [CONTRIBUTING.md](/packages/xliff-to-json-converter/CONTRIBUTING.md) for instructions to make changes to the library.
|
|
33
|
+
|
|
34
|
+
# Acknowledgements
|
|
35
|
+
|
|
36
|
+
This library is forked from [talque/xliff-to-angular-json](https://github.com/talque/xliff-to-angular-json) with additions including auto-testing, linting, and some small functionality changes. Thanks to its main contributor [vbraun](https://github.com/vbraun) for the starting point!
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
8
|
+
const helpers_1 = require("yargs/helpers");
|
|
9
|
+
const convert_1 = require("./convert");
|
|
10
|
+
// This is how yargs expects to be run at the entry point of a cli application
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, @typescript-eslint/no-floating-promises
|
|
12
|
+
yargs_1.default(helpers_1.hideBin(process.argv))
|
|
13
|
+
.strict()
|
|
14
|
+
.scriptName('xliff-to-json-converter')
|
|
15
|
+
.usage('$0 --source <src.xlf> --destination <dst.json>')
|
|
16
|
+
.command('$0', 'Convert source xliff file to angular simple json format', yargsObj => yargsObj
|
|
17
|
+
.option('source', {
|
|
18
|
+
alias: 's',
|
|
19
|
+
type: 'string',
|
|
20
|
+
describe: 'Source xliff file',
|
|
21
|
+
demandOption: true
|
|
22
|
+
})
|
|
23
|
+
.option('destination', {
|
|
24
|
+
alias: 'd',
|
|
25
|
+
type: 'string',
|
|
26
|
+
describe: 'Destination json file',
|
|
27
|
+
demandOption: true
|
|
28
|
+
}), async (argv) => {
|
|
29
|
+
const { source, destination } = argv;
|
|
30
|
+
console.log(`Converting ${source} -> ${destination}`);
|
|
31
|
+
await convert_1.convertXliff2Json(source, destination);
|
|
32
|
+
})
|
|
33
|
+
.help()
|
|
34
|
+
.argv;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeParsedTranslation = exports.xliff2Json = exports.convertXliff2Json = void 0;
|
|
4
|
+
const json_file_1 = require("./json-file");
|
|
5
|
+
const xliff_file_1 = require("./xliff-file");
|
|
6
|
+
async function convertXliff2Json(src, dst) {
|
|
7
|
+
const xliff = await xliff_file_1.loadXliff(src);
|
|
8
|
+
const json = xliff2Json(xliff);
|
|
9
|
+
json_file_1.saveJson(json, dst);
|
|
10
|
+
}
|
|
11
|
+
exports.convertXliff2Json = convertXliff2Json;
|
|
12
|
+
function xliff2Json(xliff) {
|
|
13
|
+
const translations = {};
|
|
14
|
+
const template = xliff.resources['ng2.template'];
|
|
15
|
+
Object.keys(template).forEach(key => {
|
|
16
|
+
const target = template[key].target;
|
|
17
|
+
const translation = xliffTranslation2jsonString(target);
|
|
18
|
+
if (translation !== '') {
|
|
19
|
+
translations[key] = translation;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const json = {
|
|
23
|
+
locale: xliff.targetLanguage,
|
|
24
|
+
translations
|
|
25
|
+
};
|
|
26
|
+
return json;
|
|
27
|
+
}
|
|
28
|
+
exports.xliff2Json = xliff2Json;
|
|
29
|
+
function xliffTranslation2jsonString(xliff) {
|
|
30
|
+
if (xliff === undefined) {
|
|
31
|
+
// translating the empty string (empty source is technically allowed, makes no sense)
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
if (typeof xliff === 'string') {
|
|
35
|
+
// translation is plain string without interpolation
|
|
36
|
+
return xliff;
|
|
37
|
+
}
|
|
38
|
+
if (!(xliff instanceof Array)) {
|
|
39
|
+
// translation just interpolation (makes no linguistical sense, but technically possible)
|
|
40
|
+
return makeParsedTranslation(['', ''], [xliff.Standalone.id]);
|
|
41
|
+
}
|
|
42
|
+
// makeParsedTranslation expects messagePart0, placeholderName0,
|
|
43
|
+
// messagePart1, placeholderName1, ..., messagePartN. May have to
|
|
44
|
+
// add empty messagePart at front or back.
|
|
45
|
+
const messageParts = [];
|
|
46
|
+
const placeholderNames = [];
|
|
47
|
+
for (const part of xliff) {
|
|
48
|
+
if (typeof part === 'string') {
|
|
49
|
+
messageParts.push(part);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// part is placeholder object
|
|
53
|
+
if (messageParts.length === placeholderNames.length) {
|
|
54
|
+
messageParts.push('');
|
|
55
|
+
}
|
|
56
|
+
placeholderNames.push(part.Standalone.id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (messageParts.length === placeholderNames.length) {
|
|
60
|
+
messageParts.push('');
|
|
61
|
+
}
|
|
62
|
+
return makeParsedTranslation(messageParts, placeholderNames);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a `ParsedTranslation` from a set of `messageParts` and `placeholderNames`.
|
|
66
|
+
*
|
|
67
|
+
* Adapted from the function in @angular/localize of the same name
|
|
68
|
+
*/
|
|
69
|
+
function makeParsedTranslation(messageParts, placeholderNames) {
|
|
70
|
+
if (messageParts.length !== placeholderNames.length + 1) {
|
|
71
|
+
throw new Error('translation part length mismatch');
|
|
72
|
+
}
|
|
73
|
+
let messageString = messageParts[0];
|
|
74
|
+
for (let i = 0; i < placeholderNames.length; i++) {
|
|
75
|
+
messageString += `{$${placeholderNames[i]}}${messageParts[i + 1]}`;
|
|
76
|
+
}
|
|
77
|
+
return messageString;
|
|
78
|
+
}
|
|
79
|
+
exports.makeParsedTranslation = makeParsedTranslation;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.saveJson = exports.stringify = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
function stringify(json) {
|
|
6
|
+
const content = JSON.stringify(json, undefined, 4);
|
|
7
|
+
return content;
|
|
8
|
+
}
|
|
9
|
+
exports.stringify = stringify;
|
|
10
|
+
function saveJson(json, dst) {
|
|
11
|
+
const content = stringify(json);
|
|
12
|
+
fs_1.writeFileSync(dst, content);
|
|
13
|
+
}
|
|
14
|
+
exports.saveJson = saveJson;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseXliff = exports.loadXliff = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const xliff_1 = require("xliff");
|
|
6
|
+
async function loadXliff(path) {
|
|
7
|
+
const xliff = fs_1.readFileSync(path);
|
|
8
|
+
return parseXliff(xliff.toString());
|
|
9
|
+
}
|
|
10
|
+
exports.loadXliff = loadXliff;
|
|
11
|
+
async function parseXliff(contents) {
|
|
12
|
+
return xliff_1.xliff12ToJs(contents);
|
|
13
|
+
}
|
|
14
|
+
exports.parseXliff = parseXliff;
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ni/xliff-to-json-converter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A utility to convert translation files from XLIFF to JSON for Angular localization",
|
|
5
|
+
"main": "dist/commonjs/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"xliff-to-json-converter": "./dist/commonjs/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "npm run compile",
|
|
11
|
+
"compile": "tsc -p tsconfig.json",
|
|
12
|
+
"compile-watch": "tsc -p tsconfig.json -w",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"format": "eslint . --fix",
|
|
15
|
+
"pack": "npm pack",
|
|
16
|
+
"invoke-publish": "npm publish",
|
|
17
|
+
"tdd": "npm run build && npm run test",
|
|
18
|
+
"test": "jasmine"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/ni/nimble.git",
|
|
23
|
+
"directory": "packages/xliff-to-json-converter"
|
|
24
|
+
},
|
|
25
|
+
"author": "National Instruments",
|
|
26
|
+
"license": "UNLICENSED",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@ni/eslint-config-javascript": "^3.1.0",
|
|
29
|
+
"@ni/eslint-config-typescript": "^3.0.5",
|
|
30
|
+
"@types/jasmine": "^4.0.2",
|
|
31
|
+
"@types/yargs": "^17.0.10",
|
|
32
|
+
"jasmine": "^4.2.0",
|
|
33
|
+
"jasmine-core": "^4.1.0",
|
|
34
|
+
"typescript": "^4.3.2"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"xliff": "^6.0.3",
|
|
38
|
+
"yargs": "^17.5.1"
|
|
39
|
+
}
|
|
40
|
+
}
|