@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.
@@ -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;AAUhF,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;IAEhC,sCAAsC;IACtC,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,MAAM,CAAoB;gBAEtB,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS;IAK3D,8CAA8C;IAC9C,OAAO,CAAC,oBAAoB;IAK5B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;;;;OAKG;IACH,OAAO,CAAC,qCAAqC;IAyB7C;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA0B1B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,oCAAoC;IA4B5C;;;;;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;CAkCzB"}
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
- try {
101
- return require.resolve(ref);
102
- }
103
- catch {
104
- // Should be a local file
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
- res.ref = loc.$ref.split('#/')[1];
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, source }) => !!classes && !!source)
229
- .map(({ file, classes, source }) => classes
230
- .map((classItem) => this.getLocalizationFileFromAngularElement(classItem, source))
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
- const addMetadata = (data, origin) => {
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
- const localizationMetadata = Object.keys(metadata).map((k) => metadata[k]);
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;AAI9D,cAAc,UAAU,CAAC;;AAEzB,wBA4LG"}
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.4.0-alpha.8",
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.2.0",
21
+ "@ngrx/store": "~16.3.0",
22
22
  "@ngx-translate/core": "~15.0.0",
23
- "@o3r/core": "^9.4.0-alpha.8",
24
- "@o3r/dynamic-content": "^9.4.0-alpha.8",
25
- "@o3r/extractors": "^9.4.0-alpha.8",
26
- "@o3r/logger": "^9.4.0-alpha.8",
27
- "@o3r/schematics": "^9.4.0-alpha.8",
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",