@o3r/localization 9.4.0-alpha.8 → 9.5.0-alpha.1
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/builders/helpers/localization.generator.d.ts +3 -8
- package/builders/helpers/localization.generator.d.ts.map +1 -1
- package/builders/helpers/localization.generator.js +44 -42
- package/builders/localization-extractor/index.d.ts.map +1 -1
- package/builders/localization-extractor/index.js +1 -2
- package/package.json +7 -7
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { logging } from '@angular-devkit/core';
|
|
2
2
|
import type { JSONLocalization, LocalizationMetadata } from '@o3r/localization';
|
|
3
|
+
import type { LocalizationExtractorBuilderSchema } from '../localization-extractor/schema';
|
|
3
4
|
/** Map of Localization Metadata base on localization key */
|
|
4
5
|
export interface LocalizationMetadataAsMap {
|
|
5
6
|
[key: string]: JSONLocalization;
|
|
@@ -38,10 +39,11 @@ export interface LibraryMetadataMap {
|
|
|
38
39
|
* Localization extractor
|
|
39
40
|
*/
|
|
40
41
|
export declare class LocalizationExtractor {
|
|
42
|
+
private options?;
|
|
41
43
|
/** TsConfig of the file to base on */
|
|
42
44
|
private tsconfigPath;
|
|
43
45
|
private logger;
|
|
44
|
-
constructor(tsconfigPath: string, logger: logging.LoggerApi);
|
|
46
|
+
constructor(tsconfigPath: string, logger: logging.LoggerApi, options?: Partial<LocalizationExtractorBuilderSchema> | undefined);
|
|
45
47
|
/** Get the list of file from tsconfig.json */
|
|
46
48
|
private getFilesFromTsConfig;
|
|
47
49
|
/**
|
|
@@ -50,13 +52,6 @@ export declare class LocalizationExtractor {
|
|
|
50
52
|
* @param source Ts file source
|
|
51
53
|
*/
|
|
52
54
|
private getAngularClassNode;
|
|
53
|
-
/**
|
|
54
|
-
* Retrieve the localization json file from TS Code
|
|
55
|
-
*
|
|
56
|
-
* @param node TSNode of the angular component class
|
|
57
|
-
* @param source Ts file source
|
|
58
|
-
*/
|
|
59
|
-
private getLocalizationFileFromAngularElement;
|
|
60
55
|
/**
|
|
61
56
|
* Get the list of referenced translation files
|
|
62
57
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localization.generator.d.ts","sourceRoot":"","sources":["../../../builders/helpers/localization.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"localization.generator.d.ts","sourceRoot":"","sources":["../../../builders/helpers/localization.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAMhF,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,kCAAkC,CAAC;AAK3F,4DAA4D;AAC5D,MAAM,WAAW,yBAAyB;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,6BAA6B;AAC7B,MAAM,WAAW,qBAAqB;IACpC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAC;CACtC;AAED,gCAAgC;AAChC,MAAM,WAAW,mBAAmB;IAClC,CAAC,IAAI,EAAE,MAAM,GAAG;QACd,IAAI,EAAE,oBAAoB,CAAC;QAC3B,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC;CACH;AAED,4BAA4B;AAC5B,MAAM,WAAW,kBAAkB;IACjC,CAAC,mBAAmB,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACrD;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAO6B,OAAO,CAAC,OAAO,CAAC;IAL7E,sCAAsC;IACtC,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,MAAM,CAAoB;gBAEtB,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,EAAU,OAAO,CAAC,yDAA6C;IAK1H,8CAA8C;IAC9C,OAAO,CAAC,oBAAoB;IAK5B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,oCAAoC;IAiC5C;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAYnB,kDAAkD;IAC3C,uBAAuB;;;;;IAc9B;;;;;;OAMG;IACU,kBAAkB,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,kBAAkB,GAAE,MAAM,EAAO,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA2BnJ;;;;OAIG;IACU,+BAA+B,CAAC,sBAAsB,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA8BjH;;;;OAIG;IACU,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE;IAQzD;;;;OAIG;IACU,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE;IASzD;;;;;;;;;OASG;IACI,gBAAgB,CAAC,eAAe,EAAE,mBAAmB,EAAE,OAAO,EAAE;QACrE,mBAAmB,EAAE,OAAO,CAAC;QAC7B,eAAe,EAAE,kBAAkB,CAAC;QACpC,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,OAAO,CAAC;KACnB,GAAG,oBAAoB;CAsDzB"}
|
|
@@ -13,7 +13,8 @@ const ANGULAR_ANNOTATION = ['Component', 'Injectable', 'Pipe'];
|
|
|
13
13
|
* Localization extractor
|
|
14
14
|
*/
|
|
15
15
|
class LocalizationExtractor {
|
|
16
|
-
constructor(tsconfigPath, logger) {
|
|
16
|
+
constructor(tsconfigPath, logger, options) {
|
|
17
|
+
this.options = options;
|
|
17
18
|
this.tsconfigPath = tsconfigPath;
|
|
18
19
|
this.logger = logger;
|
|
19
20
|
}
|
|
@@ -51,32 +52,6 @@ class LocalizationExtractor {
|
|
|
51
52
|
});
|
|
52
53
|
return angularItems.length ? angularItems : undefined;
|
|
53
54
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Retrieve the localization json file from TS Code
|
|
56
|
-
*
|
|
57
|
-
* @param node TSNode of the angular component class
|
|
58
|
-
* @param source Ts file source
|
|
59
|
-
*/
|
|
60
|
-
getLocalizationFileFromAngularElement(node, source) {
|
|
61
|
-
const localizationPaths = [];
|
|
62
|
-
node.forEachChild((item) => {
|
|
63
|
-
if (!ts.isPropertyDeclaration(item)) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
item.forEachChild((decorator) => {
|
|
67
|
-
if (!ts.isDecorator(decorator)) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const text = decorator.getText(source);
|
|
71
|
-
const result = /^@Localization *\( *['"](.*)['"] *\)/.exec(text);
|
|
72
|
-
if (!result || !result[1]) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
localizationPaths.push(result[1]);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
return localizationPaths.length ? localizationPaths : undefined;
|
|
79
|
-
}
|
|
80
55
|
/**
|
|
81
56
|
* Get the list of referenced translation files
|
|
82
57
|
*
|
|
@@ -97,15 +72,19 @@ class LocalizationExtractor {
|
|
|
97
72
|
})
|
|
98
73
|
.map(({ ref }) => {
|
|
99
74
|
if (!ref.startsWith('.')) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
75
|
+
if (this.options?.libraries?.length && this.options.libraries.every((lib) => !ref.startsWith(lib))) {
|
|
76
|
+
try {
|
|
77
|
+
return require.resolve(ref);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Should be a local file
|
|
81
|
+
}
|
|
105
82
|
}
|
|
83
|
+
return undefined;
|
|
106
84
|
}
|
|
107
85
|
return folder ? path.resolve(folder, ref) : ref;
|
|
108
|
-
})
|
|
86
|
+
})
|
|
87
|
+
.filter((ref) => !!ref);
|
|
109
88
|
return referencedFiles.length ? referencedFiles : undefined;
|
|
110
89
|
}
|
|
111
90
|
/**
|
|
@@ -144,7 +123,13 @@ class LocalizationExtractor {
|
|
|
144
123
|
res.tags = loc.tags;
|
|
145
124
|
}
|
|
146
125
|
if (loc.$ref) {
|
|
147
|
-
|
|
126
|
+
const [refPath, refKey] = loc.$ref.split('#/', 2);
|
|
127
|
+
if (this.options?.libraries?.some((lib) => refPath.startsWith(lib))) {
|
|
128
|
+
res.ref = refKey;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
res.ref = loc.$ref;
|
|
132
|
+
}
|
|
148
133
|
}
|
|
149
134
|
if (typeof loc.defaultValue === 'undefined' && typeof loc.$ref === 'undefined' && !loc.dictionary) {
|
|
150
135
|
this.logger.error(`${key} has no default value or $ref defined`);
|
|
@@ -225,9 +210,9 @@ class LocalizationExtractor {
|
|
|
225
210
|
const localizationFiles = tsFiles
|
|
226
211
|
.map((file) => ({ file, source: program.getSourceFile(file) }))
|
|
227
212
|
.map(({ file, source }) => ({ file, classes: source && this.getAngularClassNode(source), source }))
|
|
228
|
-
.filter(({ classes
|
|
229
|
-
.map(({ file, classes
|
|
230
|
-
.map((classItem) =>
|
|
213
|
+
.filter(({ classes }) => !!classes)
|
|
214
|
+
.map(({ file, classes }) => classes
|
|
215
|
+
.map((classItem) => (0, extractors_1.getLocalizationFileFromAngularElement)(classItem))
|
|
231
216
|
.filter((locFiles) => !!locFiles)
|
|
232
217
|
.reduce((acc, locFiles) => {
|
|
233
218
|
acc.push(...locFiles.filter((f) => acc.indexOf(f) === -1));
|
|
@@ -276,24 +261,41 @@ class LocalizationExtractor {
|
|
|
276
261
|
*/
|
|
277
262
|
generateMetadata(localizationMap, options) {
|
|
278
263
|
const metadata = {};
|
|
279
|
-
|
|
264
|
+
let hasDuplicateKey = false;
|
|
265
|
+
const addMetadata = (data, origin, libraries = []) => {
|
|
280
266
|
if (metadata[data.key]) {
|
|
267
|
+
hasDuplicateKey = true;
|
|
281
268
|
if (options.ignoreDuplicateKeys) {
|
|
282
269
|
this.logger.warn(`The key ${data.key} from ${origin} will override the previous value (${metadata[data.key].value || 'ref ' + metadata[data.key].ref} -> ${data.value || 'ref ' + data.ref})`);
|
|
283
270
|
}
|
|
284
271
|
else {
|
|
285
272
|
this.logger.error(`The key ${data.key} from ${origin} try to override the previous value (${metadata[data.key].value || 'ref ' + metadata[data.key].ref} -> ${data.value || 'ref ' + data.ref})`);
|
|
286
|
-
throw new schematics_1.O3rCliError('Duplicate key');
|
|
287
273
|
}
|
|
288
274
|
}
|
|
289
|
-
metadata[data.key] = data
|
|
275
|
+
metadata[data.key] = data.ref && data.ref.includes('#/') && libraries.some((lib) => data.ref.startsWith(lib)) ? {
|
|
276
|
+
...data,
|
|
277
|
+
ref: data.ref.split('#/')[1]
|
|
278
|
+
} : data;
|
|
290
279
|
};
|
|
291
280
|
Object.keys(options.libraryMetadata)
|
|
292
|
-
.forEach((lib) => options.libraryMetadata[lib].forEach((dataLoc) => addMetadata(dataLoc, lib)));
|
|
281
|
+
.forEach((lib) => options.libraryMetadata[lib].forEach((dataLoc) => addMetadata(dataLoc, lib, this.options?.libraries)));
|
|
293
282
|
Object.keys(localizationMap)
|
|
294
283
|
.forEach((locFile) => Object.keys(localizationMap[locFile].data)
|
|
295
284
|
.forEach((locKey) => addMetadata(this.generateMetadataItemFromLocalization(localizationMap[locFile].data[locKey], locKey), locFile)));
|
|
296
|
-
|
|
285
|
+
if (hasDuplicateKey && !options.ignoreDuplicateKeys) {
|
|
286
|
+
throw new schematics_1.O3rCliError('Duplicate key');
|
|
287
|
+
}
|
|
288
|
+
const localizationMetadata = Object.values(metadata);
|
|
289
|
+
let hasUnknownRef = false;
|
|
290
|
+
localizationMetadata.forEach((data) => {
|
|
291
|
+
if (data.ref && !data.ref.includes('#/') && !metadata[data.ref]) {
|
|
292
|
+
hasUnknownRef = true;
|
|
293
|
+
this.logger.error(`The key ${data.ref} is unknown but referenced by ${data.key}.`);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
if (hasUnknownRef) {
|
|
297
|
+
throw new schematics_1.O3rCliError('Unknown referenced key');
|
|
298
|
+
}
|
|
297
299
|
return options.sortKeys ? localizationMetadata.sort((a, b) => this.compareKeys(a, b)) : localizationMetadata;
|
|
298
300
|
}
|
|
299
301
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../builders/localization-extractor/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kCAAkC,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../builders/localization-extractor/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kCAAkC,EAAE,MAAM,UAAU,CAAC;AAG9D,cAAc,UAAU,CAAC;;AAEzB,wBA2LG"}
|
|
@@ -12,7 +12,7 @@ const validations_1 = require("./validations");
|
|
|
12
12
|
tslib_1.__exportStar(require("./schema"), exports);
|
|
13
13
|
exports.default = (0, architect_1.createBuilder)(async (options, context) => {
|
|
14
14
|
context.reportRunning();
|
|
15
|
-
const localizationExtractor = new localization_generator_1.LocalizationExtractor(path.resolve(context.workspaceRoot, options.tsConfig), context.logger);
|
|
15
|
+
const localizationExtractor = new localization_generator_1.LocalizationExtractor(path.resolve(context.workspaceRoot, options.tsConfig), context.logger, options);
|
|
16
16
|
const cache = { libs: {}, locs: {} };
|
|
17
17
|
const execute = async (isFirstLoad = true, files) => {
|
|
18
18
|
/** Maximum number of steps */
|
|
@@ -95,7 +95,6 @@ exports.default = (0, architect_1.createBuilder)(async (options, context) => {
|
|
|
95
95
|
};
|
|
96
96
|
/**
|
|
97
97
|
* Run a translation generation and report the result
|
|
98
|
-
*
|
|
99
98
|
* @param execution Execution process
|
|
100
99
|
*/
|
|
101
100
|
const generateWithReport = async (execution) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@o3r/localization",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.0-alpha.1",
|
|
4
4
|
"description": "This module provides a runtime dynamic language/translation support and debug tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"localization",
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"@angular/core": "~16.2.0",
|
|
19
19
|
"@angular/platform-browser-dynamic": "~16.2.0",
|
|
20
20
|
"@formatjs/intl-numberformat": "^8.0.2",
|
|
21
|
-
"@ngrx/store": "~16.
|
|
21
|
+
"@ngrx/store": "~16.3.0",
|
|
22
22
|
"@ngx-translate/core": "~15.0.0",
|
|
23
|
-
"@o3r/core": "^9.
|
|
24
|
-
"@o3r/dynamic-content": "^9.
|
|
25
|
-
"@o3r/extractors": "^9.
|
|
26
|
-
"@o3r/logger": "^9.
|
|
27
|
-
"@o3r/schematics": "^9.
|
|
23
|
+
"@o3r/core": "^9.5.0-alpha.1",
|
|
24
|
+
"@o3r/dynamic-content": "^9.5.0-alpha.1",
|
|
25
|
+
"@o3r/extractors": "^9.5.0-alpha.1",
|
|
26
|
+
"@o3r/logger": "^9.5.0-alpha.1",
|
|
27
|
+
"@o3r/schematics": "^9.5.0-alpha.1",
|
|
28
28
|
"@schematics/angular": "~16.2.0",
|
|
29
29
|
"chokidar": "^3.5.2",
|
|
30
30
|
"intl-messageformat": "~10.5.0",
|