@twin.org/validate-locales 0.0.3-next.3 → 0.0.3-next.31

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 CHANGED
@@ -1,16 +1,16 @@
1
1
  # TWIN Validate Locales
2
2
 
3
- This tool will read the source files and validate the usage of the locales.
3
+ This application is part of the framework workspace and provides validate source files against the locales to support consistent development workflows across the ecosystem.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```shell
8
- npm install @twin.org/validate-locales
8
+ npm install -D @twin.org/validate-locales
9
9
  ```
10
10
 
11
- ## Examples
11
+ ## Usage
12
12
 
13
- Usage of the tool is shown in the examples [docs/examples.md](docs/examples.md)
13
+ Usage of the tool is shown in the examples [docs/usage.md](docs/usage.md)
14
14
 
15
15
  ## Reference
16
16
 
package/dist/es/cli.js CHANGED
@@ -20,7 +20,7 @@ export class CLI extends CLIBase {
20
20
  return this.execute({
21
21
  title: "TWIN Validate Locales",
22
22
  appName: "validate-locales",
23
- version: "0.0.3-next.3", // x-release-please-version
23
+ version: "0.0.3-next.31", // x-release-please-version
24
24
  icon: "⚙️ ",
25
25
  supportsEnvFiles: false,
26
26
  overrideOutputWidth: options?.overrideOutputWidth
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E;;GAEG;AACH,MAAM,OAAO,GAAI,SAAQ,OAAO;IAC/B;;;;;;;OAOG;IACI,KAAK,CAAC,GAAG,CACf,IAAc,EACd,gBAAyB,EACzB,OAA0C;QAE1C,OAAO,IAAI,CAAC,OAAO,CAClB;YACC,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,cAAc,EAAE,2BAA2B;YACpD,IAAI,EAAE,KAAK;YACX,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;SACjD,EACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EACzF,IAAI,CACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,OAAgB;QACvC,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { CLIBase } from \"@twin.org/cli-core\";\nimport type { Command } from \"commander\";\nimport { buildCommandValidateLocales } from \"./commands/validateLocales.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport class CLI extends CLIBase {\n\t/**\n\t * Run the app.\n\t * @param argv The process arguments.\n\t * @param localesDirectory The directory for the locales, default to relative to the script.\n\t * @param options Additional options.\n\t * @param options.overrideOutputWidth Override the output width.\n\t * @returns The exit code.\n\t */\n\tpublic async run(\n\t\targv: string[],\n\t\tlocalesDirectory?: string,\n\t\toptions?: { overrideOutputWidth?: number }\n\t): Promise<number> {\n\t\treturn this.execute(\n\t\t\t{\n\t\t\t\ttitle: \"TWIN Validate Locales\",\n\t\t\t\tappName: \"validate-locales\",\n\t\t\t\tversion: \"0.0.3-next.3\", // x-release-please-version\n\t\t\t\ticon: \"⚙️ \",\n\t\t\t\tsupportsEnvFiles: false,\n\t\t\t\toverrideOutputWidth: options?.overrideOutputWidth\n\t\t\t},\n\t\t\tlocalesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), \"../locales\"),\n\t\t\targv\n\t\t);\n\t}\n\n\t/**\n\t * Configure any options or actions at the root program level.\n\t * @param program The root program command.\n\t */\n\tprotected configureRoot(program: Command): void {\n\t\tbuildCommandValidateLocales(program);\n\t}\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E;;GAEG;AACH,MAAM,OAAO,GAAI,SAAQ,OAAO;IAC/B;;;;;;;OAOG;IACI,KAAK,CAAC,GAAG,CACf,IAAc,EACd,gBAAyB,EACzB,OAA0C;QAE1C,OAAO,IAAI,CAAC,OAAO,CAClB;YACC,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,eAAe,EAAE,2BAA2B;YACrD,IAAI,EAAE,KAAK;YACX,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;SACjD,EACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EACzF,IAAI,CACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,OAAgB;QACvC,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { CLIBase } from \"@twin.org/cli-core\";\nimport type { Command } from \"commander\";\nimport { buildCommandValidateLocales } from \"./commands/validateLocales.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport class CLI extends CLIBase {\n\t/**\n\t * Run the app.\n\t * @param argv The process arguments.\n\t * @param localesDirectory The directory for the locales, default to relative to the script.\n\t * @param options Additional options.\n\t * @param options.overrideOutputWidth Override the output width.\n\t * @returns The exit code.\n\t */\n\tpublic async run(\n\t\targv: string[],\n\t\tlocalesDirectory?: string,\n\t\toptions?: { overrideOutputWidth?: number }\n\t): Promise<number> {\n\t\treturn this.execute(\n\t\t\t{\n\t\t\t\ttitle: \"TWIN Validate Locales\",\n\t\t\t\tappName: \"validate-locales\",\n\t\t\t\tversion: \"0.0.3-next.31\", // x-release-please-version\n\t\t\t\ticon: \"⚙️ \",\n\t\t\t\tsupportsEnvFiles: false,\n\t\t\t\toverrideOutputWidth: options?.overrideOutputWidth\n\t\t\t},\n\t\t\tlocalesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), \"../locales\"),\n\t\t\targv\n\t\t);\n\t}\n\n\t/**\n\t * Configure any options or actions at the root program level.\n\t * @param program The root program command.\n\t */\n\tprotected configureRoot(program: Command): void {\n\t\tbuildCommandValidateLocales(program);\n\t}\n}\n"]}
@@ -17,7 +17,17 @@ const ERROR_TYPES = [
17
17
  { name: "UnauthorizedError", dynamicPropertyIndex: 2 },
18
18
  { name: "NotSupportedError", dynamicPropertyIndex: 3, inbuiltProperties: ["methodName"] },
19
19
  { name: "UnprocessableError", dynamicPropertyIndex: 2 },
20
- { name: "ConflictError", dynamicPropertyIndex: 4, inbuiltProperties: ["conflictId", "conflicts"] }
20
+ {
21
+ name: "ConflictError",
22
+ dynamicPropertyIndex: 4,
23
+ inbuiltProperties: ["conflictId", "conflicts"]
24
+ },
25
+ {
26
+ name: "TooManyRequestsError",
27
+ dynamicPropertyIndex: 4,
28
+ inbuiltProperties: ["requestCount", "nextRequestTime"]
29
+ },
30
+ { name: "ForbiddenError", dynamicPropertyIndex: 2 }
21
31
  ];
22
32
  const SKIP_FILES = ["**/models/**/*.ts"];
23
33
  const SKIP_LITERALS = [
@@ -475,21 +485,27 @@ function processVariableDeclaration(sourceFile, node, localeEntries, failures, c
475
485
  * @returns True if processed, false otherwise.
476
486
  */
477
487
  function processPropertyAssignment(sourceFile, node, localeEntries, failures) {
478
- if (Is.object(node.name) && ts.isIdentifier(node.name) && node.name.getText() === "message") {
479
- const localeKey = getExpandedText(node.initializer);
480
- if (Is.stringValue(localeKey)) {
481
- let localeEntry = findAndReferenceLocale(localeEntries, localeKey);
482
- if (!Is.object(localeEntry)) {
483
- localeEntry = findAndReferenceLocale(localeEntries, `error.${localeKey}`);
484
- }
485
- if (!Is.object(localeEntry)) {
486
- failures.push({
487
- type: "key",
488
- key: localeKey,
489
- source: path.resolve(sourceFile.fileName),
490
- ...getSourcePosition(sourceFile, node)
491
- });
488
+ if (Is.object(node.name) && ts.isIdentifier(node.name)) {
489
+ if (node.name.getText() === "message") {
490
+ const localeKey = getExpandedText(node.initializer);
491
+ if (Is.stringValue(localeKey)) {
492
+ let localeEntry = findAndReferenceLocale(localeEntries, localeKey);
493
+ if (!Is.object(localeEntry)) {
494
+ localeEntry = findAndReferenceLocale(localeEntries, `error.${localeKey}`);
495
+ }
496
+ if (!Is.object(localeEntry)) {
497
+ failures.push({
498
+ type: "key",
499
+ key: localeKey,
500
+ source: path.resolve(sourceFile.fileName),
501
+ ...getSourcePosition(sourceFile, node)
502
+ });
503
+ }
504
+ return true;
492
505
  }
506
+ }
507
+ else if (node.name.getText() === "property") {
508
+ // This handles cases such as { property: 'someProperty.foo' } like we have in entity conditions
493
509
  return true;
494
510
  }
495
511
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validateLocales.js","sourceRoot":"","sources":["../../../src/commands/validateLocales.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { GeneralError, I18n, Is, StringHelper, type ILocaleDictionary } from \"@twin.org/core\";\nimport { manual } from \"@twin.org/nameof-transformer\";\nimport type { Command } from \"commander\";\nimport * as glob from \"glob\";\nimport * as ts from \"typescript\";\nimport type { ILocaleDictionaryEntry } from \"../models/ILocaleDictionaryEntry.js\";\nimport type { ILocaleFailure } from \"../models/ILocaleFailure.js\";\n\nconst ERROR_TYPES = [\n\t{ name: \"GeneralError\", dynamicPropertyIndex: 2 },\n\t{ name: \"GuardError\", dynamicPropertyIndex: -1 },\n\t{ name: \"ValidationError\", dynamicPropertyIndex: -1 },\n\t{ name: \"FetchError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"httpStatus\"] },\n\t{ name: \"NotFoundError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"notFoundId\"] },\n\t{ name: \"AlreadyExistsError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"existingId\"] },\n\t{ name: \"UnauthorizedError\", dynamicPropertyIndex: 2 },\n\t{ name: \"NotSupportedError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"methodName\"] },\n\t{ name: \"UnprocessableError\", dynamicPropertyIndex: 2 },\n\t{ name: \"ConflictError\", dynamicPropertyIndex: 4, inbuiltProperties: [\"conflictId\", \"conflicts\"] }\n];\n\nconst SKIP_FILES = [\"**/models/**/*.ts\"];\n\nconst SKIP_LITERALS = [\n\t/^\\d+\\.\\d+\\.\\d+(-\\w+(\\.\\w+)*)?(-\\d)?$/, // Version string\n\t/^[^@]+@[^@]+\\.[^@]+$/, // Email string\n\t/\\.json$/i, // ending in .json\n\t/\\.js$/i, // ending in .js\n\t/\\.ts$/i, // ending in .ts\n\t/\\.env$/i, // ending in .env\n\t/\\.png$/i, // ending in .png\n\t/\\.lock$/i, // ending in .lock\n\t/\\.toml$/i, // ending in .toml\n\t/\\.{3}/i, // ...\n\t/@twin\\.org/, // starting with @twin.org\n\t/^console.log/i // console.log\n];\n\nconst SKIP_METHODS = [/^generateRest/, /^generateSocket/];\n\nconst CAPTURE_VARIABLES = [/ROUTES_SOURCE/];\n\n/**\n * Build the root command to be consumed by the CLI.\n * @param program The command to build on.\n */\nexport function buildCommandValidateLocales(program: Command): void {\n\tprogram\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.source.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.source.description\"),\n\t\t\t\"src/**/*.ts\"\n\t\t)\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.locales.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.locales.description\"),\n\t\t\t\"locales/**/*.json\"\n\t\t)\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.ignoreFile.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.ignoreFile.description\"),\n\t\t\t\"locales/.validate-ignore\"\n\t\t)\n\t\t.action(async opts => {\n\t\t\tawait actionCommandValidateLocales(opts);\n\t\t});\n}\n\n/**\n * Action the root command.\n * @param opts The options for the command.\n * @param opts.source The source glob.\n * @param opts.locales The locales glob.\n * @param opts.ignoreFile The ignore file path.\n */\nexport async function actionCommandValidateLocales(opts: {\n\tsource: string;\n\tlocales: string;\n\tignoreFile: string;\n}): Promise<void> {\n\topts.source = path.resolve(opts.source);\n\topts.locales = path.resolve(opts.locales);\n\topts.ignoreFile = path.resolve(opts.ignoreFile);\n\n\tCLIDisplay.value(I18n.formatMessage(\"commands.validate-locales.labels.source\"), opts.source);\n\tCLIDisplay.value(I18n.formatMessage(\"commands.validate-locales.labels.locales\"), opts.locales);\n\tlet ignore: string[] = [];\n\n\tif (await CLIUtils.fileExists(opts.ignoreFile)) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.ignoreFile\"),\n\t\t\topts.ignoreFile\n\t\t);\n\t\tignore = (await CLIUtils.readLinesFile(opts.ignoreFile)) ?? [];\n\t}\n\n\tCLIDisplay.break();\n\n\tconst sources = glob.sync(opts.source.replace(/\\\\/g, \"/\"), { ignore: SKIP_FILES });\n\tconst locales = glob.sync(opts.locales.replace(/\\\\/g, \"/\"));\n\n\tif (sources.length === 0) {\n\t\tCLIDisplay.warning(I18n.formatMessage(\"commands.validate-locales.warnings.noSourceFiles\"));\n\t} else if (locales.length === 0) {\n\t\tCLIDisplay.warning(I18n.formatMessage(\"commands.validate-locales.warnings.noLocaleFiles\"));\n\t} else {\n\t\tawait validateLocales(\n\t\t\tsources,\n\t\t\tlocales,\n\t\t\tignore.filter(i => Is.stringValue(i) && !i.startsWith(\"#\")).map(i => new RegExp(i))\n\t\t);\n\t}\n\n\tCLIDisplay.break();\n\tCLIDisplay.done();\n}\n\n/**\n * Validate the locales.\n * @param sourceFiles The source files.\n * @param localeFiles The locale files.\n * @param ignore The ignore list.\n */\nasync function validateLocales(\n\tsourceFiles: string[],\n\tlocaleFiles: string[],\n\tignore: RegExp[]\n): Promise<void> {\n\tconst localeEntries: ILocaleDictionaryEntry[] = [];\n\n\tlet hasQuoteError = false;\n\tlet hasUnused = false;\n\tlet hasFailures = false;\n\n\tfor (const localeFile of localeFiles) {\n\t\tconst dictionary = await CLIUtils.readJsonFile<ILocaleDictionary>(localeFile);\n\t\tconst locale = path.basename(localeFile, path.extname(localeFile));\n\n\t\tCLIDisplay.task(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.progress.validatingLocale\", { localeFile })\n\t\t);\n\t\tCLIDisplay.break();\n\n\t\tif (Is.object<ILocaleDictionary>(dictionary)) {\n\t\t\tconst mergedKeys: { [key: string]: string } = {};\n\t\t\tI18n.flattenTranslationKeys(dictionary, \"\", mergedKeys);\n\n\t\t\tfor (const flatKey of Object.keys(mergedKeys)) {\n\t\t\t\tif (/'{.*?}'/.test(mergedKeys[flatKey])) {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.usesSingleQuotes\", {\n\t\t\t\t\t\t\tkey: flatKey\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\thasQuoteError = true;\n\t\t\t\t}\n\n\t\t\t\tlocaleEntries.push({\n\t\t\t\t\tlocale,\n\t\t\t\t\tkey: flatKey,\n\t\t\t\t\tvalue: mergedKeys[flatKey],\n\t\t\t\t\tpropertyNames: I18n.getPropertyNames(mergedKeys[flatKey]),\n\t\t\t\t\treferenced: false\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tlet failures: ILocaleFailure[] = [];\n\t\tconst captureVariables: { [name: string]: ts.Node } = {};\n\n\t\tfor (const sourceFile of sourceFiles) {\n\t\t\tconst source = await readFile(sourceFile, \"utf8\");\n\n\t\t\tconst sourceTs = ts.createSourceFile(\n\t\t\t\tsourceFile,\n\t\t\t\tsource,\n\t\t\t\tts.ScriptTarget.ESNext,\n\t\t\t\ttrue,\n\t\t\t\tts.ScriptKind.TS\n\t\t\t);\n\n\t\t\tvisit(sourceTs, sourceTs, localeEntries, failures, captureVariables);\n\t\t}\n\n\t\tfailures = failures.filter(mr => !ignore.some(pattern => pattern.test(mr.key)));\n\n\t\tif (failures.length === 0) {\n\t\t\tCLIDisplay.write(\n\t\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.noMissingLocaleEntries\")\n\t\t\t);\n\t\t\tCLIDisplay.break();\n\t\t} else {\n\t\t\thasFailures = true;\n\t\t\tfor (const failureRef of failures) {\n\t\t\t\tif (failureRef.type === \"key\") {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.missingLocaleEntry\", {\n\t\t\t\t\t\t\tkey: failureRef.key,\n\t\t\t\t\t\t\tsource: failureRef.source,\n\t\t\t\t\t\t\tline: failureRef.line,\n\t\t\t\t\t\t\tcolumn: failureRef.column\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCLIDisplay.break();\n\n\t\tfor (const localeEntry of localeEntries) {\n\t\t\tif (ignore.some(pattern => pattern.test(localeEntry.key))) {\n\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t}\n\t\t}\n\n\t\tif (localeEntries.filter(le => !le.referenced).length === 0) {\n\t\t\tCLIDisplay.write(\n\t\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.noUnusedLocaleEntries\")\n\t\t\t);\n\t\t\tCLIDisplay.break();\n\t\t} else {\n\t\t\thasUnused = true;\n\t\t\tfor (const localeEntry of localeEntries) {\n\t\t\t\tif (!localeEntry.referenced) {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.unusedLocaleEntry\", {\n\t\t\t\t\t\t\tkey: localeEntry.key\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasFailures || hasUnused || hasQuoteError) {\n\t\tthrow new GeneralError(\"validateLocales\", \"validationFailed\");\n\t}\n}\n\n/**\n * Visit the node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to visit.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n */\nfunction visit(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.Node,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): void {\n\tlet handled = false;\n\tif (\n\t\tts.isNewExpression(node) &&\n\t\tts.isIdentifier(node.expression) &&\n\t\tERROR_TYPES.some(errorType => errorType.name === node.expression.getText())\n\t) {\n\t\tprocessErrorType(sourceFile, node, node.expression.text, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isStringLiteral(node)) {\n\t\tprocessStringLiteral(sourceFile, node, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isTemplateExpression(node)) {\n\t\tprocessTemplateExpression(sourceFile, node, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isCallExpression(node)) {\n\t\thandled = processCallExpression(sourceFile, node, localeEntries, failures, captureVariables);\n\t} else if (ts.isFunctionDeclaration(node)) {\n\t\thandled = processFunctionDeclaration(sourceFile, node, localeEntries, failures);\n\t} else if (ts.isVariableDeclaration(node)) {\n\t\thandled = processVariableDeclaration(\n\t\t\tsourceFile,\n\t\t\tnode,\n\t\t\tlocaleEntries,\n\t\t\tfailures,\n\t\t\tcaptureVariables\n\t\t);\n\t} else if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n\t\t// Don't care about string in imports/exports\n\t\thandled = true;\n\t} else if (ts.isPropertyAssignment(node)) {\n\t\thandled = processPropertyAssignment(sourceFile, node, localeEntries, failures);\n\t}\n\n\tif (!handled) {\n\t\tts.forEachChild(node, child =>\n\t\t\tvisit(sourceFile, child, localeEntries, failures, captureVariables)\n\t\t);\n\t}\n}\n\n/**\n * Process an error type node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param errorType The error type.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processErrorType(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.NewExpression,\n\terrorType: string,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\tconst errType = ERROR_TYPES.find(e => e.name === errorType);\n\n\tif (Is.object(errType)) {\n\t\tconst localeKey = localeFromClassAndMessage(\n\t\t\tsourceFile,\n\t\t\tnode.arguments?.[0],\n\t\t\tnode.arguments?.[1],\n\t\t\t\"error\",\n\t\t\tfailures\n\t\t);\n\n\t\tif (Is.stringValue(localeKey)) {\n\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\tif (errType.dynamicPropertyIndex !== -1 || Is.arrayValue(errType.inbuiltProperties)) {\n\t\t\t\t\tconst usedProperties = errType.inbuiltProperties?.slice() ?? [];\n\n\t\t\t\t\tif (errType.dynamicPropertyIndex !== -1) {\n\t\t\t\t\t\tusedProperties.push(\n\t\t\t\t\t\t\t...getPropertiesFromNode(node.arguments?.[errType.dynamicPropertyIndex])\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, usedProperties, failures);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"key\",\n\t\t\t\t\tkey: localeKey,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tCLIDisplay.errorMessage(\n\t\tI18n.formatMessage(\"error.validateLocales.unableToProcessContent\", { content: node.getText() })\n\t);\n}\n\n/**\n * Find the locale entry if it exists.\n * @param localeEntries The locale entries.\n * @param entryToMatch The full key to check.\n * @returns The item if found, undefined otherwise.\n */\nfunction findAndReferenceLocale(\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tentryToMatch: string\n): ILocaleDictionaryEntry | undefined {\n\tif (Is.stringValue(entryToMatch)) {\n\t\tconst found = localeEntries.find(le => le.key === entryToMatch);\n\t\tif (found) {\n\t\t\tfound.referenced = true;\n\t\t\treturn found;\n\t\t}\n\t}\n}\n\n/**\n * Process a string literal node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processStringLiteral(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.StringLiteral,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\tif (\n\t\tnode.text.length > 3 &&\n\t\tnode.text.includes(\".\") &&\n\t\t!/[ ()/]/.test(node.text) &&\n\t\t!/^\\.|\\.$/.test(node.text) &&\n\t\t!isSkipLiteral(node.text)\n\t) {\n\t\tconst parts = node.text.split(\".\");\n\t\tif (parts.length > 1) {\n\t\t\t// First try and match the string as-is\n\t\t\tlet localeEntry = findAndReferenceLocale(localeEntries, node.text);\n\t\t\tif (localeEntry) {\n\t\t\t\tlocaleEntry.referenced = true;\n\n\t\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, node.text, usedProperties, failures);\n\t\t\t}\n\n\t\t\tif (!localeEntry && [\"validation.\", \"common.\"].some(t => node.text.startsWith(t))) {\n\t\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${node.text}`);\n\t\t\t\tif (localeEntry) {\n\t\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\t\t\tcheckPropertyUsage(\n\t\t\t\t\t\tsourceFile,\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tlocaleEntry,\n\t\t\t\t\t\t`error.${node.text}`,\n\t\t\t\t\t\tusedProperties,\n\t\t\t\t\t\tfailures\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!localeEntry) {\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"key\",\n\t\t\t\t\tkey: node.text,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Process a template expression node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processTemplateExpression(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.TemplateExpression,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\t// This case handles templates like `error.${nameof(Class)}.message`\n\tconst templateParts = extractTemplatePartsWithExpressions(node);\n\n\t// Join all literal text parts to form a potential locale key\n\tif (hasValidTemplateContent(templateParts)) {\n\t\tconst key = expandTemplateParts(templateParts);\n\n\t\tlet localeEntry = findAndReferenceLocale(localeEntries, key);\n\t\tif (localeEntry) {\n\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeEntry.key, usedProperties, failures);\n\t\t} else if ([\"validation.\", \"common.\"].some(t => key.startsWith(t))) {\n\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${key}`);\n\n\t\t\tif (localeEntry) {\n\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t\tconst usedProperties = getPropertiesFromNode(node.parent.parent);\n\n\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, `error.${key}`, usedProperties, failures);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Process a call expression node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n * @returns True if processed, false otherwise.\n */\nfunction processCallExpression(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.CallExpression,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): boolean {\n\tif (ts.isPropertyAccessExpression(node.expression)) {\n\t\tconst functionName = node.expression.name.getText();\n\t\tif (node.expression.getText() === \"console.log\") {\n\t\t\treturn true;\n\t\t} else if (\n\t\t\tfunctionName === \"log\" &&\n\t\t\tnode.arguments.length === 1 &&\n\t\t\tts.isObjectLiteralExpression(node.arguments[0])\n\t\t) {\n\t\t\tlet level;\n\t\t\tlet source;\n\t\t\tlet message;\n\t\t\tlet dataNames;\n\t\t\tfor (const prop of node.arguments[0].properties) {\n\t\t\t\tif (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {\n\t\t\t\t\tif (prop.name.text === \"source\") {\n\t\t\t\t\t\tif (ts.isIdentifier(prop.initializer) && captureVariables[prop.initializer.text]) {\n\t\t\t\t\t\t\tsource = captureVariables[prop.initializer.text];\n\t\t\t\t\t\t} else if (ts.isStringLiteral(prop.initializer)) {\n\t\t\t\t\t\t\tsource = prop.initializer;\n\t\t\t\t\t\t} else if (ts.isPropertyAccessExpression(prop.initializer)) {\n\t\t\t\t\t\t\tsource = prop.initializer;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (prop.name.text === \"message\") {\n\t\t\t\t\t\tmessage = prop.initializer;\n\t\t\t\t\t} else if (prop.name.text === \"data\") {\n\t\t\t\t\t\tdataNames = getPropertiesFromNode(prop.initializer);\n\t\t\t\t\t} else if (prop.name.text === \"level\") {\n\t\t\t\t\t\tlevel = getExpandedText(prop.initializer);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst localeKey = localeFromClassAndMessage(sourceFile, source, message, level, failures);\n\n\t\t\tif (Is.stringValue(localeKey)) {\n\t\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, dataNames ?? [], failures);\n\t\t\t\t} else {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: localeKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst messageText = message?.getText();\n\t\t\t\tif (Is.stringValue(messageText)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: messageText,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else if (\n\t\t\tfunctionName === \"formatMessage\" &&\n\t\t\tnode.arguments.length === 2 &&\n\t\t\tts.isTemplateExpression(node.arguments[0]) &&\n\t\t\tts.isObjectLiteralExpression(node.arguments[1])\n\t\t) {\n\t\t\tconst localeKey = getExpandedText(node.arguments[0]);\n\n\t\t\tif (Is.stringValue(localeKey)) {\n\t\t\t\tconst dataNames = getPropertiesFromNode(node.arguments[1]);\n\t\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, dataNames ?? [], failures);\n\t\t\t\t} else {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: localeKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Process a function declaration node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @returns True if processed, false otherwise.\n */\nfunction processFunctionDeclaration(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.FunctionDeclaration,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): boolean {\n\tif (\n\t\tIs.object(node.name) &&\n\t\tts.isIdentifier(node.name) &&\n\t\tSKIP_METHODS.some(re => re.test(node.name?.text ?? \"\"))\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Process a variable statement declaration node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n * @returns True if processed, false otherwise.\n */\nfunction processVariableDeclaration(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.VariableDeclaration,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): boolean {\n\tif (\n\t\tIs.object(node.name) &&\n\t\tIs.object(node.initializer) &&\n\t\tts.isIdentifier(node.name) &&\n\t\tts.isStringLiteral(node.initializer) &&\n\t\tCAPTURE_VARIABLES.some(re => re.test(node.name.getText()))\n\t) {\n\t\tcaptureVariables[node.name.getText()] = node.initializer;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Process a property assignment node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @returns True if processed, false otherwise.\n */\nfunction processPropertyAssignment(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.PropertyAssignment,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): boolean {\n\tif (Is.object(node.name) && ts.isIdentifier(node.name) && node.name.getText() === \"message\") {\n\t\tconst localeKey = getExpandedText(node.initializer);\n\n\t\tif (Is.stringValue(localeKey)) {\n\t\t\tlet localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\tif (!Is.object(localeEntry)) {\n\t\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${localeKey}`);\n\t\t\t}\n\n\t\t\tif (!Is.object(localeEntry)) {\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"key\",\n\t\t\t\t\tkey: localeKey,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Get the expanded text from a node.\n * @param node The node to get the text from.\n * @returns The expanded text.\n */\nfunction getExpandedText(node: ts.Node): string {\n\tif (ts.isTemplateExpression(node)) {\n\t\tconst templateParts = extractTemplatePartsWithExpressions(node);\n\t\tif (hasValidTemplateContent(templateParts)) {\n\t\t\treturn expandTemplateParts(templateParts);\n\t\t}\n\t} else if (ts.isStringLiteral(node)) {\n\t\tif (hasValidTemplateContent([node.text])) {\n\t\t\treturn node.text;\n\t\t}\n\t}\n\n\treturn \"\";\n}\n\n/**\n * Extract parts from a template literal, splitting by ${} expressions.\n * @param node The template expression node.\n * @returns Array of parts including expressions and literal text.\n */\nfunction extractTemplatePartsWithExpressions(node: ts.TemplateExpression): string[] {\n\tconst parts: string[] = [];\n\n\t// Start with the head (text before first ${})\n\tif (node.head.text) {\n\t\tparts.push(node.head.text);\n\t}\n\n\t// Process each template span (${expression}text)\n\tfor (const span of node.templateSpans) {\n\t\t// Add the expression part as text\n\t\tparts.push(span.expression.getText());\n\n\t\t// Add the literal text after the expression\n\t\tif (span.literal.text) {\n\t\t\tparts.push(span.literal.text);\n\t\t}\n\t}\n\n\treturn parts.filter(part => part.length > 0);\n}\n\n/**\n * Check if the content has any parts which contain elements which determine is is not an locale key.\n * @param templateParts The template parts to check.\n * @returns True if the template parts are valid, false otherwise.\n */\nfunction hasValidTemplateContent(templateParts: string[]): boolean {\n\treturn !templateParts.some(part => /[#,/:=?|]/.test(part));\n}\n\n/**\n * Expand template parts into a single string, processing nameof expressions.\n * @param templateParts The template parts to expand.\n * @returns The expanded template string.\n */\nfunction expandTemplateParts(templateParts: string[]): string {\n\tfor (let i = 0; i < templateParts.length; i++) {\n\t\ttemplateParts[i] = expandTemplatePart(templateParts[i]);\n\t}\n\n\treturn templateParts.join(\"\");\n}\n\n/**\n * Expand template part into a single string, processing nameof expressions.\n * @param templatePart The template part to expand.\n * @returns The expanded template string.\n */\nfunction expandTemplatePart(templatePart: string): string {\n\tif (templatePart.startsWith(\"nameof\")) {\n\t\tconst stripped = manual(templatePart).replace(/[\"']/g, \"\");\n\t\ttemplatePart = StringHelper.camelCase(stripped, true);\n\t} else if (templatePart.startsWith(\"StringHelper.\")) {\n\t\ttemplatePart = templatePart.replace(/\\.CLASS_NAME/g, \"\");\n\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.camelCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.camelCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.titleCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.titleCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.pascalCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.pascalCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.kebabCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.kebabCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.snakeCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.snakeCase(i)\n\t\t);\n\t} else if (templatePart.includes(\".CLASS_NAME\")) {\n\t\ttemplatePart = StringHelper.camelCase(templatePart.replace(/\\.CLASS_NAME/g, \"\"));\n\t}\n\ttemplatePart = templatePart.replace(/[\"'`]/g, \"\"); // Remove quotes\n\n\treturn templatePart;\n}\n\n/**\n * Check the property usage in a locale entry against the used properties.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to check.\n * @param localeEntry The locale entry to check against.\n * @param key The key in the locale entry.\n * @param usedProperties The properties used in the code.\n * @param failures The failure entries.\n */\nfunction checkPropertyUsage(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.Node,\n\tlocaleEntry: ILocaleDictionaryEntry,\n\tkey: string,\n\tusedProperties: string[],\n\tfailures: ILocaleFailure[]\n): void {\n\tfor (const propName of localeEntry.propertyNames) {\n\t\tconst propIndex = usedProperties.indexOf(propName);\n\t\tif (propIndex === -1) {\n\t\t\tconst position = getSourcePosition(sourceFile, node);\n\t\t\tCLIDisplay.errorMessage(\n\t\t\t\tI18n.formatMessage(\"error.validateLocales.missingPropertyInLocale\", {\n\t\t\t\t\tkey,\n\t\t\t\t\tproperty: propName,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\tline: position.line,\n\t\t\t\t\tcolumn: position.column\n\t\t\t\t})\n\t\t\t);\n\t\t\tfailures.push({\n\t\t\t\ttype: \"property\",\n\t\t\t\tkey: localeEntry.key,\n\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t...position\n\t\t\t});\n\t\t}\n\t}\n\n\t// We often pass additional properties in the error details to better inform the logging\n\t// so we don't want to perform the opposite check for parameters in the call but not in the locale entry\n}\n\n/**\n * Helper to get line and column position from a node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param n The node to get position for.\n * @returns Line and column (1-based).\n */\nfunction getSourcePosition(\n\tsourceFile: ts.SourceFile,\n\tn: ts.Node\n): { line: number; column: number } {\n\tconst { line, character } = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));\n\treturn { line: line + 1, column: character + 1 };\n}\n\n/**\n * Get property names from a node.\n * @param node The node to get property names from.\n * @returns The property names.\n */\nfunction getPropertiesFromNode(node?: ts.Node): string[] {\n\tif (!node) {\n\t\treturn [];\n\t}\n\n\tconst props: string[] = [];\n\n\t// If this is an object literal then we can get the property names\n\tif (ts.isObjectLiteralExpression(node)) {\n\t\t// Get the properties of the object literal\n\t\tconst properties = node.properties;\n\t\tfor (const prop of properties) {\n\t\t\tif (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {\n\t\t\t\t// { property: value }\n\t\t\t\tprops.push(prop.name.text);\n\n\t\t\t\t// { property: { nestedProperty: value } }\n\t\t\t\tif (ts.isObjectLiteralExpression(prop.initializer)) {\n\t\t\t\t\t// Recursively get properties from nested object literals\n\t\t\t\t\tconst nestedProps = getPropertiesFromNode(prop.initializer);\n\t\t\t\t\tprops.push(...nestedProps);\n\t\t\t\t}\n\t\t\t} else if (ts.isShorthandPropertyAssignment(prop)) {\n\t\t\t\t// { property }\n\t\t\t\tprops.push(prop.getText());\n\t\t\t}\n\t\t}\n\t} else if (ts.isStringLiteral(node)) {\n\t\t// If this is a string literal then there are no properties\n\t\t// so we need to look in the surrounding context\n\t\tconst parent = node.parent;\n\t\tif (ts.isCallExpression(parent) || ts.isNewExpression(parent)) {\n\t\t\t// Let's see if they are the next argument in the call\n\t\t\tconst args = parent.arguments;\n\t\t\tif (args && args.length > 0) {\n\t\t\t\tconst index = args.findIndex(a => a === node);\n\t\t\t\tif (index !== -1 && index + 1 < args.length) {\n\t\t\t\t\treturn getPropertiesFromNode(args[index + 1]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (ts.isPropertyAssignment(parent)) {\n\t\t\t// This is part of a property assignment in an object\n\t\t\t// so we can check the parent object for other properties\n\t\t\tif (ts.isObjectLiteralExpression(parent.parent)) {\n\t\t\t\treturn getPropertiesFromNode(parent.parent);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn props;\n}\n\n/**\n * Check if a value is a file operation.\n * @param value The value to check.\n * @returns True if the value is a file operation.\n */\nfunction isSkipLiteral(value: string): boolean {\n\treturn SKIP_LITERALS.some(regex => regex.test(value));\n}\n\n/**\n * Get the locale from the class and message nodes.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param classNode The class node.\n * @param messageNode The message node.\n * @param prefix The prefix for the locale key.\n * @param failures The failure entries.\n * @returns The locale entry or undefined.\n */\nfunction localeFromClassAndMessage(\n\tsourceFile: ts.SourceFile,\n\tclassNode: ts.Node | undefined,\n\tmessageNode: ts.Node | undefined,\n\tprefix: string | undefined,\n\tfailures: ILocaleFailure[]\n): string | undefined {\n\tif (!classNode || !messageNode) {\n\t\treturn undefined;\n\t}\n\n\tconst classNameParam = classNode.getText();\n\tconst classNameParamParts = classNameParam?.split(\".\");\n\n\tif (Is.array(classNameParamParts)) {\n\t\tconst messageKey = getExpandedText(messageNode);\n\n\t\tif (Is.stringValue(messageKey)) {\n\t\t\tif (messageKey.includes(\" \")) {\n\t\t\t\t// If the message contains spaces then it is not a key\n\t\t\t\t// but should be replaced by one\n\t\t\t\tconst position = getSourcePosition(sourceFile, messageNode);\n\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.shouldBeKey\", {\n\t\t\t\t\t\tvalue: messageKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\tline: position.line,\n\t\t\t\t\t\tcolumn: position.column\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"noKey\",\n\t\t\t\t\tkey: messageKey,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...position\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst finalKeyParts = [];\n\n\t\t\t\tconst classNameExpanded = expandTemplatePart(classNameParam);\n\t\t\t\tconst messageKeyParts = messageKey.split(\".\");\n\n\t\t\t\tif (messageKeyParts.length === 2 && classNameExpanded === messageKeyParts[0]) {\n\t\t\t\t\t// But if it is fully qualified with exactly two segments and starts with the class name\n\t\t\t\t\t// then the class name is redundant and should be removed in the source\n\t\t\t\t\tconst position = getSourcePosition(sourceFile, messageNode);\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.noNeedToQualify\", {\n\t\t\t\t\t\t\tkey: messageKey,\n\t\t\t\t\t\t\tproperty: classNameParam,\n\t\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t\tline: position.line,\n\t\t\t\t\t\t\tcolumn: position.column\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"qualify\",\n\t\t\t\t\t\tkey: messageKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...position\n\t\t\t\t\t});\n\t\t\t\t} else if (!messageKey.includes(\".\")) {\n\t\t\t\t\t// If the key is not fully qualified then add the class name\n\t\t\t\t\t// to the final key\n\t\t\t\t\tfinalKeyParts.push(classNameExpanded);\n\t\t\t\t}\n\n\t\t\t\tfinalKeyParts.push(messageKey);\n\n\t\t\t\tif (Is.stringValue(prefix)) {\n\t\t\t\t\tfinalKeyParts.unshift(prefix);\n\t\t\t\t}\n\n\t\t\t\treturn finalKeyParts.join(\".\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"validateLocales.js","sourceRoot":"","sources":["../../../src/commands/validateLocales.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { GeneralError, I18n, Is, StringHelper, type ILocaleDictionary } from \"@twin.org/core\";\nimport { manual } from \"@twin.org/nameof-transformer\";\nimport type { Command } from \"commander\";\nimport * as glob from \"glob\";\nimport * as ts from \"typescript\";\nimport type { ILocaleDictionaryEntry } from \"../models/ILocaleDictionaryEntry.js\";\nimport type { ILocaleFailure } from \"../models/ILocaleFailure.js\";\n\nconst ERROR_TYPES = [\n\t{ name: \"GeneralError\", dynamicPropertyIndex: 2 },\n\t{ name: \"GuardError\", dynamicPropertyIndex: -1 },\n\t{ name: \"ValidationError\", dynamicPropertyIndex: -1 },\n\t{ name: \"FetchError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"httpStatus\"] },\n\t{ name: \"NotFoundError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"notFoundId\"] },\n\t{ name: \"AlreadyExistsError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"existingId\"] },\n\t{ name: \"UnauthorizedError\", dynamicPropertyIndex: 2 },\n\t{ name: \"NotSupportedError\", dynamicPropertyIndex: 3, inbuiltProperties: [\"methodName\"] },\n\t{ name: \"UnprocessableError\", dynamicPropertyIndex: 2 },\n\t{\n\t\tname: \"ConflictError\",\n\t\tdynamicPropertyIndex: 4,\n\t\tinbuiltProperties: [\"conflictId\", \"conflicts\"]\n\t},\n\t{\n\t\tname: \"TooManyRequestsError\",\n\t\tdynamicPropertyIndex: 4,\n\t\tinbuiltProperties: [\"requestCount\", \"nextRequestTime\"]\n\t},\n\t{ name: \"ForbiddenError\", dynamicPropertyIndex: 2 }\n];\n\nconst SKIP_FILES = [\"**/models/**/*.ts\"];\n\nconst SKIP_LITERALS = [\n\t/^\\d+\\.\\d+\\.\\d+(-\\w+(\\.\\w+)*)?(-\\d)?$/, // Version string\n\t/^[^@]+@[^@]+\\.[^@]+$/, // Email string\n\t/\\.json$/i, // ending in .json\n\t/\\.js$/i, // ending in .js\n\t/\\.ts$/i, // ending in .ts\n\t/\\.env$/i, // ending in .env\n\t/\\.png$/i, // ending in .png\n\t/\\.lock$/i, // ending in .lock\n\t/\\.toml$/i, // ending in .toml\n\t/\\.{3}/i, // ...\n\t/@twin\\.org/, // starting with @twin.org\n\t/^console.log/i // console.log\n];\n\nconst SKIP_METHODS = [/^generateRest/, /^generateSocket/];\n\nconst CAPTURE_VARIABLES = [/ROUTES_SOURCE/];\n\n/**\n * Build the root command to be consumed by the CLI.\n * @param program The command to build on.\n */\nexport function buildCommandValidateLocales(program: Command): void {\n\tprogram\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.source.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.source.description\"),\n\t\t\t\"src/**/*.ts\"\n\t\t)\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.locales.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.locales.description\"),\n\t\t\t\"locales/**/*.json\"\n\t\t)\n\t\t.option(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.ignoreFile.param\"),\n\t\t\tI18n.formatMessage(\"commands.validate-locales.options.ignoreFile.description\"),\n\t\t\t\"locales/.validate-ignore\"\n\t\t)\n\t\t.action(async opts => {\n\t\t\tawait actionCommandValidateLocales(opts);\n\t\t});\n}\n\n/**\n * Action the root command.\n * @param opts The options for the command.\n * @param opts.source The source glob.\n * @param opts.locales The locales glob.\n * @param opts.ignoreFile The ignore file path.\n */\nexport async function actionCommandValidateLocales(opts: {\n\tsource: string;\n\tlocales: string;\n\tignoreFile: string;\n}): Promise<void> {\n\topts.source = path.resolve(opts.source);\n\topts.locales = path.resolve(opts.locales);\n\topts.ignoreFile = path.resolve(opts.ignoreFile);\n\n\tCLIDisplay.value(I18n.formatMessage(\"commands.validate-locales.labels.source\"), opts.source);\n\tCLIDisplay.value(I18n.formatMessage(\"commands.validate-locales.labels.locales\"), opts.locales);\n\tlet ignore: string[] = [];\n\n\tif (await CLIUtils.fileExists(opts.ignoreFile)) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.ignoreFile\"),\n\t\t\topts.ignoreFile\n\t\t);\n\t\tignore = (await CLIUtils.readLinesFile(opts.ignoreFile)) ?? [];\n\t}\n\n\tCLIDisplay.break();\n\n\tconst sources = glob.sync(opts.source.replace(/\\\\/g, \"/\"), { ignore: SKIP_FILES });\n\tconst locales = glob.sync(opts.locales.replace(/\\\\/g, \"/\"));\n\n\tif (sources.length === 0) {\n\t\tCLIDisplay.warning(I18n.formatMessage(\"commands.validate-locales.warnings.noSourceFiles\"));\n\t} else if (locales.length === 0) {\n\t\tCLIDisplay.warning(I18n.formatMessage(\"commands.validate-locales.warnings.noLocaleFiles\"));\n\t} else {\n\t\tawait validateLocales(\n\t\t\tsources,\n\t\t\tlocales,\n\t\t\tignore.filter(i => Is.stringValue(i) && !i.startsWith(\"#\")).map(i => new RegExp(i))\n\t\t);\n\t}\n\n\tCLIDisplay.break();\n\tCLIDisplay.done();\n}\n\n/**\n * Validate the locales.\n * @param sourceFiles The source files.\n * @param localeFiles The locale files.\n * @param ignore The ignore list.\n */\nasync function validateLocales(\n\tsourceFiles: string[],\n\tlocaleFiles: string[],\n\tignore: RegExp[]\n): Promise<void> {\n\tconst localeEntries: ILocaleDictionaryEntry[] = [];\n\n\tlet hasQuoteError = false;\n\tlet hasUnused = false;\n\tlet hasFailures = false;\n\n\tfor (const localeFile of localeFiles) {\n\t\tconst dictionary = await CLIUtils.readJsonFile<ILocaleDictionary>(localeFile);\n\t\tconst locale = path.basename(localeFile, path.extname(localeFile));\n\n\t\tCLIDisplay.task(\n\t\t\tI18n.formatMessage(\"commands.validate-locales.progress.validatingLocale\", { localeFile })\n\t\t);\n\t\tCLIDisplay.break();\n\n\t\tif (Is.object<ILocaleDictionary>(dictionary)) {\n\t\t\tconst mergedKeys: { [key: string]: string } = {};\n\t\t\tI18n.flattenTranslationKeys(dictionary, \"\", mergedKeys);\n\n\t\t\tfor (const flatKey of Object.keys(mergedKeys)) {\n\t\t\t\tif (/'{.*?}'/.test(mergedKeys[flatKey])) {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.usesSingleQuotes\", {\n\t\t\t\t\t\t\tkey: flatKey\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\thasQuoteError = true;\n\t\t\t\t}\n\n\t\t\t\tlocaleEntries.push({\n\t\t\t\t\tlocale,\n\t\t\t\t\tkey: flatKey,\n\t\t\t\t\tvalue: mergedKeys[flatKey],\n\t\t\t\t\tpropertyNames: I18n.getPropertyNames(mergedKeys[flatKey]),\n\t\t\t\t\treferenced: false\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tlet failures: ILocaleFailure[] = [];\n\t\tconst captureVariables: { [name: string]: ts.Node } = {};\n\n\t\tfor (const sourceFile of sourceFiles) {\n\t\t\tconst source = await readFile(sourceFile, \"utf8\");\n\n\t\t\tconst sourceTs = ts.createSourceFile(\n\t\t\t\tsourceFile,\n\t\t\t\tsource,\n\t\t\t\tts.ScriptTarget.ESNext,\n\t\t\t\ttrue,\n\t\t\t\tts.ScriptKind.TS\n\t\t\t);\n\n\t\t\tvisit(sourceTs, sourceTs, localeEntries, failures, captureVariables);\n\t\t}\n\n\t\tfailures = failures.filter(mr => !ignore.some(pattern => pattern.test(mr.key)));\n\n\t\tif (failures.length === 0) {\n\t\t\tCLIDisplay.write(\n\t\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.noMissingLocaleEntries\")\n\t\t\t);\n\t\t\tCLIDisplay.break();\n\t\t} else {\n\t\t\thasFailures = true;\n\t\t\tfor (const failureRef of failures) {\n\t\t\t\tif (failureRef.type === \"key\") {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.missingLocaleEntry\", {\n\t\t\t\t\t\t\tkey: failureRef.key,\n\t\t\t\t\t\t\tsource: failureRef.source,\n\t\t\t\t\t\t\tline: failureRef.line,\n\t\t\t\t\t\t\tcolumn: failureRef.column\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCLIDisplay.break();\n\n\t\tfor (const localeEntry of localeEntries) {\n\t\t\tif (ignore.some(pattern => pattern.test(localeEntry.key))) {\n\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t}\n\t\t}\n\n\t\tif (localeEntries.filter(le => !le.referenced).length === 0) {\n\t\t\tCLIDisplay.write(\n\t\t\t\tI18n.formatMessage(\"commands.validate-locales.labels.noUnusedLocaleEntries\")\n\t\t\t);\n\t\t\tCLIDisplay.break();\n\t\t} else {\n\t\t\thasUnused = true;\n\t\t\tfor (const localeEntry of localeEntries) {\n\t\t\t\tif (!localeEntry.referenced) {\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.unusedLocaleEntry\", {\n\t\t\t\t\t\t\tkey: localeEntry.key\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (hasFailures || hasUnused || hasQuoteError) {\n\t\tthrow new GeneralError(\"validateLocales\", \"validationFailed\");\n\t}\n}\n\n/**\n * Visit the node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to visit.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n */\nfunction visit(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.Node,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): void {\n\tlet handled = false;\n\tif (\n\t\tts.isNewExpression(node) &&\n\t\tts.isIdentifier(node.expression) &&\n\t\tERROR_TYPES.some(errorType => errorType.name === node.expression.getText())\n\t) {\n\t\tprocessErrorType(sourceFile, node, node.expression.text, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isStringLiteral(node)) {\n\t\tprocessStringLiteral(sourceFile, node, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isTemplateExpression(node)) {\n\t\tprocessTemplateExpression(sourceFile, node, localeEntries, failures);\n\t\thandled = true;\n\t} else if (ts.isCallExpression(node)) {\n\t\thandled = processCallExpression(sourceFile, node, localeEntries, failures, captureVariables);\n\t} else if (ts.isFunctionDeclaration(node)) {\n\t\thandled = processFunctionDeclaration(sourceFile, node, localeEntries, failures);\n\t} else if (ts.isVariableDeclaration(node)) {\n\t\thandled = processVariableDeclaration(\n\t\t\tsourceFile,\n\t\t\tnode,\n\t\t\tlocaleEntries,\n\t\t\tfailures,\n\t\t\tcaptureVariables\n\t\t);\n\t} else if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n\t\t// Don't care about string in imports/exports\n\t\thandled = true;\n\t} else if (ts.isPropertyAssignment(node)) {\n\t\thandled = processPropertyAssignment(sourceFile, node, localeEntries, failures);\n\t}\n\n\tif (!handled) {\n\t\tts.forEachChild(node, child =>\n\t\t\tvisit(sourceFile, child, localeEntries, failures, captureVariables)\n\t\t);\n\t}\n}\n\n/**\n * Process an error type node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param errorType The error type.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processErrorType(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.NewExpression,\n\terrorType: string,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\tconst errType = ERROR_TYPES.find(e => e.name === errorType);\n\n\tif (Is.object(errType)) {\n\t\tconst localeKey = localeFromClassAndMessage(\n\t\t\tsourceFile,\n\t\t\tnode.arguments?.[0],\n\t\t\tnode.arguments?.[1],\n\t\t\t\"error\",\n\t\t\tfailures\n\t\t);\n\n\t\tif (Is.stringValue(localeKey)) {\n\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\tif (errType.dynamicPropertyIndex !== -1 || Is.arrayValue(errType.inbuiltProperties)) {\n\t\t\t\t\tconst usedProperties = errType.inbuiltProperties?.slice() ?? [];\n\n\t\t\t\t\tif (errType.dynamicPropertyIndex !== -1) {\n\t\t\t\t\t\tusedProperties.push(\n\t\t\t\t\t\t\t...getPropertiesFromNode(node.arguments?.[errType.dynamicPropertyIndex])\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, usedProperties, failures);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"key\",\n\t\t\t\t\tkey: localeKey,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tCLIDisplay.errorMessage(\n\t\tI18n.formatMessage(\"error.validateLocales.unableToProcessContent\", { content: node.getText() })\n\t);\n}\n\n/**\n * Find the locale entry if it exists.\n * @param localeEntries The locale entries.\n * @param entryToMatch The full key to check.\n * @returns The item if found, undefined otherwise.\n */\nfunction findAndReferenceLocale(\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tentryToMatch: string\n): ILocaleDictionaryEntry | undefined {\n\tif (Is.stringValue(entryToMatch)) {\n\t\tconst found = localeEntries.find(le => le.key === entryToMatch);\n\t\tif (found) {\n\t\t\tfound.referenced = true;\n\t\t\treturn found;\n\t\t}\n\t}\n}\n\n/**\n * Process a string literal node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processStringLiteral(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.StringLiteral,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\tif (\n\t\tnode.text.length > 3 &&\n\t\tnode.text.includes(\".\") &&\n\t\t!/[ ()/]/.test(node.text) &&\n\t\t!/^\\.|\\.$/.test(node.text) &&\n\t\t!isSkipLiteral(node.text)\n\t) {\n\t\tconst parts = node.text.split(\".\");\n\t\tif (parts.length > 1) {\n\t\t\t// First try and match the string as-is\n\t\t\tlet localeEntry = findAndReferenceLocale(localeEntries, node.text);\n\t\t\tif (localeEntry) {\n\t\t\t\tlocaleEntry.referenced = true;\n\n\t\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, node.text, usedProperties, failures);\n\t\t\t}\n\n\t\t\tif (!localeEntry && [\"validation.\", \"common.\"].some(t => node.text.startsWith(t))) {\n\t\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${node.text}`);\n\t\t\t\tif (localeEntry) {\n\t\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\t\t\tcheckPropertyUsage(\n\t\t\t\t\t\tsourceFile,\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tlocaleEntry,\n\t\t\t\t\t\t`error.${node.text}`,\n\t\t\t\t\t\tusedProperties,\n\t\t\t\t\t\tfailures\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!localeEntry) {\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"key\",\n\t\t\t\t\tkey: node.text,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Process a template expression node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n */\nfunction processTemplateExpression(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.TemplateExpression,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): void {\n\t// This case handles templates like `error.${nameof(Class)}.message`\n\tconst templateParts = extractTemplatePartsWithExpressions(node);\n\n\t// Join all literal text parts to form a potential locale key\n\tif (hasValidTemplateContent(templateParts)) {\n\t\tconst key = expandTemplateParts(templateParts);\n\n\t\tlet localeEntry = findAndReferenceLocale(localeEntries, key);\n\t\tif (localeEntry) {\n\t\t\tconst usedProperties = getPropertiesFromNode(node);\n\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeEntry.key, usedProperties, failures);\n\t\t} else if ([\"validation.\", \"common.\"].some(t => key.startsWith(t))) {\n\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${key}`);\n\n\t\t\tif (localeEntry) {\n\t\t\t\tlocaleEntry.referenced = true;\n\t\t\t\tconst usedProperties = getPropertiesFromNode(node.parent.parent);\n\n\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, `error.${key}`, usedProperties, failures);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Process a call expression node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n * @returns True if processed, false otherwise.\n */\nfunction processCallExpression(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.CallExpression,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): boolean {\n\tif (ts.isPropertyAccessExpression(node.expression)) {\n\t\tconst functionName = node.expression.name.getText();\n\t\tif (node.expression.getText() === \"console.log\") {\n\t\t\treturn true;\n\t\t} else if (\n\t\t\tfunctionName === \"log\" &&\n\t\t\tnode.arguments.length === 1 &&\n\t\t\tts.isObjectLiteralExpression(node.arguments[0])\n\t\t) {\n\t\t\tlet level;\n\t\t\tlet source;\n\t\t\tlet message;\n\t\t\tlet dataNames;\n\t\t\tfor (const prop of node.arguments[0].properties) {\n\t\t\t\tif (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {\n\t\t\t\t\tif (prop.name.text === \"source\") {\n\t\t\t\t\t\tif (ts.isIdentifier(prop.initializer) && captureVariables[prop.initializer.text]) {\n\t\t\t\t\t\t\tsource = captureVariables[prop.initializer.text];\n\t\t\t\t\t\t} else if (ts.isStringLiteral(prop.initializer)) {\n\t\t\t\t\t\t\tsource = prop.initializer;\n\t\t\t\t\t\t} else if (ts.isPropertyAccessExpression(prop.initializer)) {\n\t\t\t\t\t\t\tsource = prop.initializer;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (prop.name.text === \"message\") {\n\t\t\t\t\t\tmessage = prop.initializer;\n\t\t\t\t\t} else if (prop.name.text === \"data\") {\n\t\t\t\t\t\tdataNames = getPropertiesFromNode(prop.initializer);\n\t\t\t\t\t} else if (prop.name.text === \"level\") {\n\t\t\t\t\t\tlevel = getExpandedText(prop.initializer);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst localeKey = localeFromClassAndMessage(sourceFile, source, message, level, failures);\n\n\t\t\tif (Is.stringValue(localeKey)) {\n\t\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, dataNames ?? [], failures);\n\t\t\t\t} else {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: localeKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst messageText = message?.getText();\n\t\t\t\tif (Is.stringValue(messageText)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: messageText,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else if (\n\t\t\tfunctionName === \"formatMessage\" &&\n\t\t\tnode.arguments.length === 2 &&\n\t\t\tts.isTemplateExpression(node.arguments[0]) &&\n\t\t\tts.isObjectLiteralExpression(node.arguments[1])\n\t\t) {\n\t\t\tconst localeKey = getExpandedText(node.arguments[0]);\n\n\t\t\tif (Is.stringValue(localeKey)) {\n\t\t\t\tconst dataNames = getPropertiesFromNode(node.arguments[1]);\n\t\t\t\tconst localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\t\tif (Is.object(localeEntry)) {\n\t\t\t\t\tcheckPropertyUsage(sourceFile, node, localeEntry, localeKey, dataNames ?? [], failures);\n\t\t\t\t} else {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: localeKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Process a function declaration node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @returns True if processed, false otherwise.\n */\nfunction processFunctionDeclaration(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.FunctionDeclaration,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): boolean {\n\tif (\n\t\tIs.object(node.name) &&\n\t\tts.isIdentifier(node.name) &&\n\t\tSKIP_METHODS.some(re => re.test(node.name?.text ?? \"\"))\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Process a variable statement declaration node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @param captureVariables The capture variables.\n * @returns True if processed, false otherwise.\n */\nfunction processVariableDeclaration(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.VariableDeclaration,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[],\n\tcaptureVariables: { [name: string]: ts.Node }\n): boolean {\n\tif (\n\t\tIs.object(node.name) &&\n\t\tIs.object(node.initializer) &&\n\t\tts.isIdentifier(node.name) &&\n\t\tts.isStringLiteral(node.initializer) &&\n\t\tCAPTURE_VARIABLES.some(re => re.test(node.name.getText()))\n\t) {\n\t\tcaptureVariables[node.name.getText()] = node.initializer;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Process a property assignment node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to process.\n * @param localeEntries The locale entries.\n * @param failures The failure entries.\n * @returns True if processed, false otherwise.\n */\nfunction processPropertyAssignment(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.PropertyAssignment,\n\tlocaleEntries: ILocaleDictionaryEntry[],\n\tfailures: ILocaleFailure[]\n): boolean {\n\tif (Is.object(node.name) && ts.isIdentifier(node.name)) {\n\t\tif (node.name.getText() === \"message\") {\n\t\t\tconst localeKey = getExpandedText(node.initializer);\n\n\t\t\tif (Is.stringValue(localeKey)) {\n\t\t\t\tlet localeEntry = findAndReferenceLocale(localeEntries, localeKey);\n\n\t\t\t\tif (!Is.object(localeEntry)) {\n\t\t\t\t\tlocaleEntry = findAndReferenceLocale(localeEntries, `error.${localeKey}`);\n\t\t\t\t}\n\n\t\t\t\tif (!Is.object(localeEntry)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"key\",\n\t\t\t\t\t\tkey: localeKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...getSourcePosition(sourceFile, node)\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (node.name.getText() === \"property\") {\n\t\t\t// This handles cases such as { property: 'someProperty.foo' } like we have in entity conditions\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Get the expanded text from a node.\n * @param node The node to get the text from.\n * @returns The expanded text.\n */\nfunction getExpandedText(node: ts.Node): string {\n\tif (ts.isTemplateExpression(node)) {\n\t\tconst templateParts = extractTemplatePartsWithExpressions(node);\n\t\tif (hasValidTemplateContent(templateParts)) {\n\t\t\treturn expandTemplateParts(templateParts);\n\t\t}\n\t} else if (ts.isStringLiteral(node)) {\n\t\tif (hasValidTemplateContent([node.text])) {\n\t\t\treturn node.text;\n\t\t}\n\t}\n\n\treturn \"\";\n}\n\n/**\n * Extract parts from a template literal, splitting by ${} expressions.\n * @param node The template expression node.\n * @returns Array of parts including expressions and literal text.\n */\nfunction extractTemplatePartsWithExpressions(node: ts.TemplateExpression): string[] {\n\tconst parts: string[] = [];\n\n\t// Start with the head (text before first ${})\n\tif (node.head.text) {\n\t\tparts.push(node.head.text);\n\t}\n\n\t// Process each template span (${expression}text)\n\tfor (const span of node.templateSpans) {\n\t\t// Add the expression part as text\n\t\tparts.push(span.expression.getText());\n\n\t\t// Add the literal text after the expression\n\t\tif (span.literal.text) {\n\t\t\tparts.push(span.literal.text);\n\t\t}\n\t}\n\n\treturn parts.filter(part => part.length > 0);\n}\n\n/**\n * Check if the content has any parts which contain elements which determine is is not an locale key.\n * @param templateParts The template parts to check.\n * @returns True if the template parts are valid, false otherwise.\n */\nfunction hasValidTemplateContent(templateParts: string[]): boolean {\n\treturn !templateParts.some(part => /[#,/:=?|]/.test(part));\n}\n\n/**\n * Expand template parts into a single string, processing nameof expressions.\n * @param templateParts The template parts to expand.\n * @returns The expanded template string.\n */\nfunction expandTemplateParts(templateParts: string[]): string {\n\tfor (let i = 0; i < templateParts.length; i++) {\n\t\ttemplateParts[i] = expandTemplatePart(templateParts[i]);\n\t}\n\n\treturn templateParts.join(\"\");\n}\n\n/**\n * Expand template part into a single string, processing nameof expressions.\n * @param templatePart The template part to expand.\n * @returns The expanded template string.\n */\nfunction expandTemplatePart(templatePart: string): string {\n\tif (templatePart.startsWith(\"nameof\")) {\n\t\tconst stripped = manual(templatePart).replace(/[\"']/g, \"\");\n\t\ttemplatePart = StringHelper.camelCase(stripped, true);\n\t} else if (templatePart.startsWith(\"StringHelper.\")) {\n\t\ttemplatePart = templatePart.replace(/\\.CLASS_NAME/g, \"\");\n\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.camelCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.camelCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.titleCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.titleCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.pascalCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.pascalCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.kebabCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.kebabCase(i)\n\t\t);\n\t\ttemplatePart = templatePart.replace(/StringHelper\\.snakeCase\\((.*?)\\)/, (_, i) =>\n\t\t\tStringHelper.snakeCase(i)\n\t\t);\n\t} else if (templatePart.includes(\".CLASS_NAME\")) {\n\t\ttemplatePart = StringHelper.camelCase(templatePart.replace(/\\.CLASS_NAME/g, \"\"));\n\t}\n\ttemplatePart = templatePart.replace(/[\"'`]/g, \"\"); // Remove quotes\n\n\treturn templatePart;\n}\n\n/**\n * Check the property usage in a locale entry against the used properties.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param node The node to check.\n * @param localeEntry The locale entry to check against.\n * @param key The key in the locale entry.\n * @param usedProperties The properties used in the code.\n * @param failures The failure entries.\n */\nfunction checkPropertyUsage(\n\tsourceFile: ts.SourceFile,\n\tnode: ts.Node,\n\tlocaleEntry: ILocaleDictionaryEntry,\n\tkey: string,\n\tusedProperties: string[],\n\tfailures: ILocaleFailure[]\n): void {\n\tfor (const propName of localeEntry.propertyNames) {\n\t\tconst propIndex = usedProperties.indexOf(propName);\n\t\tif (propIndex === -1) {\n\t\t\tconst position = getSourcePosition(sourceFile, node);\n\t\t\tCLIDisplay.errorMessage(\n\t\t\t\tI18n.formatMessage(\"error.validateLocales.missingPropertyInLocale\", {\n\t\t\t\t\tkey,\n\t\t\t\t\tproperty: propName,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\tline: position.line,\n\t\t\t\t\tcolumn: position.column\n\t\t\t\t})\n\t\t\t);\n\t\t\tfailures.push({\n\t\t\t\ttype: \"property\",\n\t\t\t\tkey: localeEntry.key,\n\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t...position\n\t\t\t});\n\t\t}\n\t}\n\n\t// We often pass additional properties in the error details to better inform the logging\n\t// so we don't want to perform the opposite check for parameters in the call but not in the locale entry\n}\n\n/**\n * Helper to get line and column position from a node.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param n The node to get position for.\n * @returns Line and column (1-based).\n */\nfunction getSourcePosition(\n\tsourceFile: ts.SourceFile,\n\tn: ts.Node\n): { line: number; column: number } {\n\tconst { line, character } = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));\n\treturn { line: line + 1, column: character + 1 };\n}\n\n/**\n * Get property names from a node.\n * @param node The node to get property names from.\n * @returns The property names.\n */\nfunction getPropertiesFromNode(node?: ts.Node): string[] {\n\tif (!node) {\n\t\treturn [];\n\t}\n\n\tconst props: string[] = [];\n\n\t// If this is an object literal then we can get the property names\n\tif (ts.isObjectLiteralExpression(node)) {\n\t\t// Get the properties of the object literal\n\t\tconst properties = node.properties;\n\t\tfor (const prop of properties) {\n\t\t\tif (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {\n\t\t\t\t// { property: value }\n\t\t\t\tprops.push(prop.name.text);\n\n\t\t\t\t// { property: { nestedProperty: value } }\n\t\t\t\tif (ts.isObjectLiteralExpression(prop.initializer)) {\n\t\t\t\t\t// Recursively get properties from nested object literals\n\t\t\t\t\tconst nestedProps = getPropertiesFromNode(prop.initializer);\n\t\t\t\t\tprops.push(...nestedProps);\n\t\t\t\t}\n\t\t\t} else if (ts.isShorthandPropertyAssignment(prop)) {\n\t\t\t\t// { property }\n\t\t\t\tprops.push(prop.getText());\n\t\t\t}\n\t\t}\n\t} else if (ts.isStringLiteral(node)) {\n\t\t// If this is a string literal then there are no properties\n\t\t// so we need to look in the surrounding context\n\t\tconst parent = node.parent;\n\t\tif (ts.isCallExpression(parent) || ts.isNewExpression(parent)) {\n\t\t\t// Let's see if they are the next argument in the call\n\t\t\tconst args = parent.arguments;\n\t\t\tif (args && args.length > 0) {\n\t\t\t\tconst index = args.findIndex(a => a === node);\n\t\t\t\tif (index !== -1 && index + 1 < args.length) {\n\t\t\t\t\treturn getPropertiesFromNode(args[index + 1]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (ts.isPropertyAssignment(parent)) {\n\t\t\t// This is part of a property assignment in an object\n\t\t\t// so we can check the parent object for other properties\n\t\t\tif (ts.isObjectLiteralExpression(parent.parent)) {\n\t\t\t\treturn getPropertiesFromNode(parent.parent);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn props;\n}\n\n/**\n * Check if a value is a file operation.\n * @param value The value to check.\n * @returns True if the value is a file operation.\n */\nfunction isSkipLiteral(value: string): boolean {\n\treturn SKIP_LITERALS.some(regex => regex.test(value));\n}\n\n/**\n * Get the locale from the class and message nodes.\n * @param sourceFile The TypeScript source file for position calculations.\n * @param classNode The class node.\n * @param messageNode The message node.\n * @param prefix The prefix for the locale key.\n * @param failures The failure entries.\n * @returns The locale entry or undefined.\n */\nfunction localeFromClassAndMessage(\n\tsourceFile: ts.SourceFile,\n\tclassNode: ts.Node | undefined,\n\tmessageNode: ts.Node | undefined,\n\tprefix: string | undefined,\n\tfailures: ILocaleFailure[]\n): string | undefined {\n\tif (!classNode || !messageNode) {\n\t\treturn undefined;\n\t}\n\n\tconst classNameParam = classNode.getText();\n\tconst classNameParamParts = classNameParam?.split(\".\");\n\n\tif (Is.array(classNameParamParts)) {\n\t\tconst messageKey = getExpandedText(messageNode);\n\n\t\tif (Is.stringValue(messageKey)) {\n\t\t\tif (messageKey.includes(\" \")) {\n\t\t\t\t// If the message contains spaces then it is not a key\n\t\t\t\t// but should be replaced by one\n\t\t\t\tconst position = getSourcePosition(sourceFile, messageNode);\n\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.shouldBeKey\", {\n\t\t\t\t\t\tvalue: messageKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\tline: position.line,\n\t\t\t\t\t\tcolumn: position.column\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tfailures.push({\n\t\t\t\t\ttype: \"noKey\",\n\t\t\t\t\tkey: messageKey,\n\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t...position\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst finalKeyParts = [];\n\n\t\t\t\tconst classNameExpanded = expandTemplatePart(classNameParam);\n\t\t\t\tconst messageKeyParts = messageKey.split(\".\");\n\n\t\t\t\tif (messageKeyParts.length === 2 && classNameExpanded === messageKeyParts[0]) {\n\t\t\t\t\t// But if it is fully qualified with exactly two segments and starts with the class name\n\t\t\t\t\t// then the class name is redundant and should be removed in the source\n\t\t\t\t\tconst position = getSourcePosition(sourceFile, messageNode);\n\t\t\t\t\tCLIDisplay.errorMessage(\n\t\t\t\t\t\tI18n.formatMessage(\"error.validateLocales.noNeedToQualify\", {\n\t\t\t\t\t\t\tkey: messageKey,\n\t\t\t\t\t\t\tproperty: classNameParam,\n\t\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t\tline: position.line,\n\t\t\t\t\t\t\tcolumn: position.column\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\ttype: \"qualify\",\n\t\t\t\t\t\tkey: messageKey,\n\t\t\t\t\t\tsource: path.resolve(sourceFile.fileName),\n\t\t\t\t\t\t...position\n\t\t\t\t\t});\n\t\t\t\t} else if (!messageKey.includes(\".\")) {\n\t\t\t\t\t// If the key is not fully qualified then add the class name\n\t\t\t\t\t// to the final key\n\t\t\t\t\tfinalKeyParts.push(classNameExpanded);\n\t\t\t\t}\n\n\t\t\t\tfinalKeyParts.push(messageKey);\n\n\t\t\t\tif (Is.stringValue(prefix)) {\n\t\t\t\t\tfinalKeyParts.unshift(prefix);\n\t\t\t\t}\n\n\t\t\t\treturn finalKeyParts.join(\".\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
@@ -79,7 +79,9 @@
79
79
  "function": "Property \"{property}\" must be a function, it is \"{value}\"",
80
80
  "urn": "Property \"{property}\" must be a Urn formatted string, it is \"{value}\"",
81
81
  "url": "Property \"{property}\" must be a Url formatted string, it is \"{value}\"",
82
- "email": "Property \"{property}\" must be string in e-mail format, it is \"{value}\""
82
+ "email": "Property \"{property}\" must be string in e-mail format, it is \"{value}\"",
83
+ "uuidV7": "Property \"{property}\" must be a UUIDv7 formatted string, it is \"{value}\"",
84
+ "uuidV7Compact": "Property \"{property}\" must be a UUIDv7 formatted string in compact mode, it is \"{value}\""
83
85
  },
84
86
  "objectHelper": {
85
87
  "failedBytesToJSON": "Failed converting bytes to JSON",
@@ -92,7 +94,8 @@
92
94
  },
93
95
  "factory": {
94
96
  "noUnregister": "There is no {typeName} registered with the name \"{name}\"",
95
- "noGet": "The requested {typeName} \"{name}\" does not exist in the factory"
97
+ "noGet": "The requested {typeName} \"{name}\" does not exist in the factory",
98
+ "noCreate": "The requested {typeName} \"{name}\" cannot be created by the factory, with params \"{params}\""
96
99
  },
97
100
  "bitString": {
98
101
  "outOfRange": "The index should be >= 0 and less than the length of the bit string, the index is \"{index}\" and the number of bit is \"{numberBits}\""
package/docs/changelog.md CHANGED
@@ -1,5 +1,582 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.31](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.30...validate-locales-v0.0.3-next.31) (2026-04-14)
4
+
5
+
6
+ ### Miscellaneous Chores
7
+
8
+ * **validate-locales:** Synchronize repo versions
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/cli-core bumped from 0.0.3-next.30 to 0.0.3-next.31
16
+ * @twin.org/core bumped from 0.0.3-next.30 to 0.0.3-next.31
17
+ * @twin.org/nameof bumped from 0.0.3-next.30 to 0.0.3-next.31
18
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.30 to 0.0.3-next.31
19
+ * devDependencies
20
+ * @twin.org/merge-locales bumped from 0.0.3-next.30 to 0.0.3-next.31
21
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.30 to 0.0.3-next.31
22
+
23
+ ## [0.0.3-next.30](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.29...validate-locales-v0.0.3-next.30) (2026-04-14)
24
+
25
+
26
+ ### Features
27
+
28
+ * additional error types in validate locales ([d0e87d6](https://github.com/twinfoundation/framework/commit/d0e87d6d9430e91417636d30dd4865fa6a31d825))
29
+
30
+
31
+ ### Dependencies
32
+
33
+ * The following workspace dependencies were updated
34
+ * dependencies
35
+ * @twin.org/cli-core bumped from 0.0.3-next.29 to 0.0.3-next.30
36
+ * @twin.org/core bumped from 0.0.3-next.29 to 0.0.3-next.30
37
+ * @twin.org/nameof bumped from 0.0.3-next.29 to 0.0.3-next.30
38
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.29 to 0.0.3-next.30
39
+ * devDependencies
40
+ * @twin.org/merge-locales bumped from 0.0.3-next.29 to 0.0.3-next.30
41
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.29 to 0.0.3-next.30
42
+
43
+ ## [0.0.3-next.29](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.28...validate-locales-v0.0.3-next.29) (2026-04-14)
44
+
45
+
46
+ ### Miscellaneous Chores
47
+
48
+ * **validate-locales:** Synchronize repo versions
49
+
50
+
51
+ ### Dependencies
52
+
53
+ * The following workspace dependencies were updated
54
+ * dependencies
55
+ * @twin.org/cli-core bumped from 0.0.3-next.28 to 0.0.3-next.29
56
+ * @twin.org/core bumped from 0.0.3-next.28 to 0.0.3-next.29
57
+ * @twin.org/nameof bumped from 0.0.3-next.28 to 0.0.3-next.29
58
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.28 to 0.0.3-next.29
59
+ * devDependencies
60
+ * @twin.org/merge-locales bumped from 0.0.3-next.28 to 0.0.3-next.29
61
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.28 to 0.0.3-next.29
62
+
63
+ ## [0.0.3-next.28](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.27...validate-locales-v0.0.3-next.28) (2026-03-27)
64
+
65
+
66
+ ### Miscellaneous Chores
67
+
68
+ * **validate-locales:** Synchronize repo versions
69
+
70
+
71
+ ### Dependencies
72
+
73
+ * The following workspace dependencies were updated
74
+ * dependencies
75
+ * @twin.org/cli-core bumped from 0.0.3-next.27 to 0.0.3-next.28
76
+ * @twin.org/core bumped from 0.0.3-next.27 to 0.0.3-next.28
77
+ * @twin.org/nameof bumped from 0.0.3-next.27 to 0.0.3-next.28
78
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.27 to 0.0.3-next.28
79
+ * devDependencies
80
+ * @twin.org/merge-locales bumped from 0.0.3-next.27 to 0.0.3-next.28
81
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.27 to 0.0.3-next.28
82
+
83
+ ## [0.0.3-next.27](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.26...validate-locales-v0.0.3-next.27) (2026-03-27)
84
+
85
+
86
+ ### Miscellaneous Chores
87
+
88
+ * **validate-locales:** Synchronize repo versions
89
+
90
+
91
+ ### Dependencies
92
+
93
+ * The following workspace dependencies were updated
94
+ * dependencies
95
+ * @twin.org/cli-core bumped from 0.0.3-next.26 to 0.0.3-next.27
96
+ * @twin.org/core bumped from 0.0.3-next.26 to 0.0.3-next.27
97
+ * @twin.org/nameof bumped from 0.0.3-next.26 to 0.0.3-next.27
98
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.26 to 0.0.3-next.27
99
+ * devDependencies
100
+ * @twin.org/merge-locales bumped from 0.0.3-next.26 to 0.0.3-next.27
101
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.26 to 0.0.3-next.27
102
+
103
+ ## [0.0.3-next.26](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.25...validate-locales-v0.0.3-next.26) (2026-03-24)
104
+
105
+
106
+ ### Miscellaneous Chores
107
+
108
+ * **validate-locales:** Synchronize repo versions
109
+
110
+
111
+ ### Dependencies
112
+
113
+ * The following workspace dependencies were updated
114
+ * dependencies
115
+ * @twin.org/cli-core bumped from 0.0.3-next.25 to 0.0.3-next.26
116
+ * @twin.org/core bumped from 0.0.3-next.25 to 0.0.3-next.26
117
+ * @twin.org/nameof bumped from 0.0.3-next.25 to 0.0.3-next.26
118
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.25 to 0.0.3-next.26
119
+ * devDependencies
120
+ * @twin.org/merge-locales bumped from 0.0.3-next.25 to 0.0.3-next.26
121
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.25 to 0.0.3-next.26
122
+
123
+ ## [0.0.3-next.25](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.24...validate-locales-v0.0.3-next.25) (2026-03-23)
124
+
125
+
126
+ ### Miscellaneous Chores
127
+
128
+ * **validate-locales:** Synchronize repo versions
129
+
130
+
131
+ ### Dependencies
132
+
133
+ * The following workspace dependencies were updated
134
+ * dependencies
135
+ * @twin.org/cli-core bumped from 0.0.3-next.24 to 0.0.3-next.25
136
+ * @twin.org/core bumped from 0.0.3-next.24 to 0.0.3-next.25
137
+ * @twin.org/nameof bumped from 0.0.3-next.24 to 0.0.3-next.25
138
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.24 to 0.0.3-next.25
139
+ * devDependencies
140
+ * @twin.org/merge-locales bumped from 0.0.3-next.24 to 0.0.3-next.25
141
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.24 to 0.0.3-next.25
142
+
143
+ ## [0.0.3-next.24](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.23...validate-locales-v0.0.3-next.24) (2026-03-19)
144
+
145
+
146
+ ### Bug Fixes
147
+
148
+ * ensure __decorate is defined for decorators ([103a563](https://github.com/twinfoundation/framework/commit/103a563ce01ebdef6240d2e590e7b026e8692684))
149
+
150
+
151
+ ### Dependencies
152
+
153
+ * The following workspace dependencies were updated
154
+ * dependencies
155
+ * @twin.org/cli-core bumped from 0.0.3-next.23 to 0.0.3-next.24
156
+ * @twin.org/core bumped from 0.0.3-next.23 to 0.0.3-next.24
157
+ * @twin.org/nameof bumped from 0.0.3-next.23 to 0.0.3-next.24
158
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.23 to 0.0.3-next.24
159
+ * devDependencies
160
+ * @twin.org/merge-locales bumped from 0.0.3-next.23 to 0.0.3-next.24
161
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.23 to 0.0.3-next.24
162
+
163
+ ## [0.0.3-next.23](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.22...validate-locales-v0.0.3-next.23) (2026-03-17)
164
+
165
+
166
+ ### Miscellaneous Chores
167
+
168
+ * **validate-locales:** Synchronize repo versions
169
+
170
+
171
+ ### Dependencies
172
+
173
+ * The following workspace dependencies were updated
174
+ * dependencies
175
+ * @twin.org/cli-core bumped from 0.0.3-next.22 to 0.0.3-next.23
176
+ * @twin.org/core bumped from 0.0.3-next.22 to 0.0.3-next.23
177
+ * @twin.org/nameof bumped from 0.0.3-next.22 to 0.0.3-next.23
178
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.22 to 0.0.3-next.23
179
+ * devDependencies
180
+ * @twin.org/merge-locales bumped from 0.0.3-next.22 to 0.0.3-next.23
181
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.22 to 0.0.3-next.23
182
+
183
+ ## [0.0.3-next.22](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.21...validate-locales-v0.0.3-next.22) (2026-02-26)
184
+
185
+
186
+ ### Miscellaneous Chores
187
+
188
+ * **validate-locales:** Synchronize repo versions
189
+
190
+
191
+ ### Dependencies
192
+
193
+ * The following workspace dependencies were updated
194
+ * dependencies
195
+ * @twin.org/cli-core bumped from 0.0.3-next.21 to 0.0.3-next.22
196
+ * @twin.org/core bumped from 0.0.3-next.21 to 0.0.3-next.22
197
+ * @twin.org/nameof bumped from 0.0.3-next.21 to 0.0.3-next.22
198
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.21 to 0.0.3-next.22
199
+ * devDependencies
200
+ * @twin.org/merge-locales bumped from 0.0.3-next.21 to 0.0.3-next.22
201
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.21 to 0.0.3-next.22
202
+
203
+ ## [0.0.3-next.21](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.20...validate-locales-v0.0.3-next.21) (2026-02-26)
204
+
205
+
206
+ ### Features
207
+
208
+ * add context id features ([#206](https://github.com/twinfoundation/framework/issues/206)) ([ef0d4ee](https://github.com/twinfoundation/framework/commit/ef0d4ee11a4f5fc6cc6f52a4958ce905c04ee13b))
209
+ * detect unused prefixes and non i18 key messages ([a357810](https://github.com/twinfoundation/framework/commit/a357810754e25478496c2e6fd71ddc49dee9f747))
210
+ * locales validation ([#197](https://github.com/twinfoundation/framework/issues/197)) ([55fdadb](https://github.com/twinfoundation/framework/commit/55fdadb13595ce0047f787bd1d4135d429a99f12))
211
+ * support for "property" assignments in validate-locales ([2414a0c](https://github.com/twinfoundation/framework/commit/2414a0c2e29d8935a17b58b9bdc31609c0f97140))
212
+
213
+
214
+ ### Bug Fixes
215
+
216
+ * validate locales missing log key ([54fb89a](https://github.com/twinfoundation/framework/commit/54fb89ae9e05ab7dc79e42dc4933575c39bffd8a))
217
+ * validate locales missing log key ([14a649e](https://github.com/twinfoundation/framework/commit/14a649e569c0509bef045a76edf1818f3eca6ded))
218
+
219
+
220
+ ### Dependencies
221
+
222
+ * The following workspace dependencies were updated
223
+ * dependencies
224
+ * @twin.org/cli-core bumped from 0.0.3-next.20 to 0.0.3-next.21
225
+ * @twin.org/core bumped from 0.0.3-next.20 to 0.0.3-next.21
226
+ * @twin.org/nameof bumped from 0.0.3-next.20 to 0.0.3-next.21
227
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.20 to 0.0.3-next.21
228
+ * devDependencies
229
+ * @twin.org/merge-locales bumped from 0.0.3-next.20 to 0.0.3-next.21
230
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.20 to 0.0.3-next.21
231
+
232
+ ## [0.0.3-next.20](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.19...validate-locales-v0.0.3-next.20) (2026-02-26)
233
+
234
+
235
+ ### Miscellaneous Chores
236
+
237
+ * **validate-locales:** Synchronize repo versions
238
+
239
+
240
+ ### Dependencies
241
+
242
+ * The following workspace dependencies were updated
243
+ * dependencies
244
+ * @twin.org/cli-core bumped from 0.0.3-next.19 to 0.0.3-next.20
245
+ * @twin.org/core bumped from 0.0.3-next.19 to 0.0.3-next.20
246
+ * @twin.org/nameof bumped from 0.0.3-next.19 to 0.0.3-next.20
247
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.19 to 0.0.3-next.20
248
+ * devDependencies
249
+ * @twin.org/merge-locales bumped from 0.0.3-next.19 to 0.0.3-next.20
250
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.19 to 0.0.3-next.20
251
+
252
+ ## [0.0.3-next.19](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.18...validate-locales-v0.0.3-next.19) (2026-02-26)
253
+
254
+
255
+ ### Miscellaneous Chores
256
+
257
+ * **validate-locales:** Synchronize repo versions
258
+
259
+
260
+ ### Dependencies
261
+
262
+ * The following workspace dependencies were updated
263
+ * dependencies
264
+ * @twin.org/cli-core bumped from 0.0.3-next.18 to 0.0.3-next.19
265
+ * @twin.org/core bumped from 0.0.3-next.18 to 0.0.3-next.19
266
+ * @twin.org/nameof bumped from 0.0.3-next.18 to 0.0.3-next.19
267
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.18 to 0.0.3-next.19
268
+ * devDependencies
269
+ * @twin.org/merge-locales bumped from 0.0.3-next.18 to 0.0.3-next.19
270
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.18 to 0.0.3-next.19
271
+
272
+ ## [0.0.3-next.18](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.17...validate-locales-v0.0.3-next.18) (2026-02-23)
273
+
274
+
275
+ ### Miscellaneous Chores
276
+
277
+ * **validate-locales:** Synchronize repo versions
278
+
279
+
280
+ ### Dependencies
281
+
282
+ * The following workspace dependencies were updated
283
+ * dependencies
284
+ * @twin.org/cli-core bumped from 0.0.3-next.17 to 0.0.3-next.18
285
+ * @twin.org/core bumped from 0.0.3-next.17 to 0.0.3-next.18
286
+ * @twin.org/nameof bumped from 0.0.3-next.17 to 0.0.3-next.18
287
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.17 to 0.0.3-next.18
288
+ * devDependencies
289
+ * @twin.org/merge-locales bumped from 0.0.3-next.17 to 0.0.3-next.18
290
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.17 to 0.0.3-next.18
291
+
292
+ ## [0.0.3-next.17](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.16...validate-locales-v0.0.3-next.17) (2026-02-09)
293
+
294
+
295
+ ### Miscellaneous Chores
296
+
297
+ * **validate-locales:** Synchronize repo versions
298
+
299
+
300
+ ### Dependencies
301
+
302
+ * The following workspace dependencies were updated
303
+ * dependencies
304
+ * @twin.org/cli-core bumped from 0.0.3-next.16 to 0.0.3-next.17
305
+ * @twin.org/core bumped from 0.0.3-next.16 to 0.0.3-next.17
306
+ * @twin.org/nameof bumped from 0.0.3-next.16 to 0.0.3-next.17
307
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.16 to 0.0.3-next.17
308
+ * devDependencies
309
+ * @twin.org/merge-locales bumped from 0.0.3-next.16 to 0.0.3-next.17
310
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.16 to 0.0.3-next.17
311
+
312
+ ## [0.0.3-next.16](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.15...validate-locales-v0.0.3-next.16) (2026-02-06)
313
+
314
+
315
+ ### Miscellaneous Chores
316
+
317
+ * **validate-locales:** Synchronize repo versions
318
+
319
+
320
+ ### Dependencies
321
+
322
+ * The following workspace dependencies were updated
323
+ * dependencies
324
+ * @twin.org/cli-core bumped from 0.0.3-next.15 to 0.0.3-next.16
325
+ * @twin.org/core bumped from 0.0.3-next.15 to 0.0.3-next.16
326
+ * @twin.org/nameof bumped from 0.0.3-next.15 to 0.0.3-next.16
327
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.15 to 0.0.3-next.16
328
+ * devDependencies
329
+ * @twin.org/merge-locales bumped from 0.0.3-next.15 to 0.0.3-next.16
330
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.15 to 0.0.3-next.16
331
+
332
+ ## [0.0.3-next.15](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.14...validate-locales-v0.0.3-next.15) (2026-01-29)
333
+
334
+
335
+ ### Miscellaneous Chores
336
+
337
+ * **validate-locales:** Synchronize repo versions
338
+
339
+
340
+ ### Dependencies
341
+
342
+ * The following workspace dependencies were updated
343
+ * dependencies
344
+ * @twin.org/cli-core bumped from 0.0.3-next.14 to 0.0.3-next.15
345
+ * @twin.org/core bumped from 0.0.3-next.14 to 0.0.3-next.15
346
+ * @twin.org/nameof bumped from 0.0.3-next.14 to 0.0.3-next.15
347
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.14 to 0.0.3-next.15
348
+ * devDependencies
349
+ * @twin.org/merge-locales bumped from 0.0.3-next.14 to 0.0.3-next.15
350
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.14 to 0.0.3-next.15
351
+
352
+ ## [0.0.3-next.14](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.13...validate-locales-v0.0.3-next.14) (2026-01-22)
353
+
354
+
355
+ ### Miscellaneous Chores
356
+
357
+ * **validate-locales:** Synchronize repo versions
358
+
359
+
360
+ ### Dependencies
361
+
362
+ * The following workspace dependencies were updated
363
+ * dependencies
364
+ * @twin.org/cli-core bumped from 0.0.3-next.13 to 0.0.3-next.14
365
+ * @twin.org/core bumped from 0.0.3-next.13 to 0.0.3-next.14
366
+ * @twin.org/nameof bumped from 0.0.3-next.13 to 0.0.3-next.14
367
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.13 to 0.0.3-next.14
368
+ * devDependencies
369
+ * @twin.org/merge-locales bumped from 0.0.3-next.13 to 0.0.3-next.14
370
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.13 to 0.0.3-next.14
371
+
372
+ ## [0.0.3-next.13](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.12...validate-locales-v0.0.3-next.13) (2026-01-08)
373
+
374
+
375
+ ### Miscellaneous Chores
376
+
377
+ * **validate-locales:** Synchronize repo versions
378
+
379
+
380
+ ### Dependencies
381
+
382
+ * The following workspace dependencies were updated
383
+ * dependencies
384
+ * @twin.org/cli-core bumped from 0.0.3-next.12 to 0.0.3-next.13
385
+ * @twin.org/core bumped from 0.0.3-next.12 to 0.0.3-next.13
386
+ * @twin.org/nameof bumped from 0.0.3-next.12 to 0.0.3-next.13
387
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.12 to 0.0.3-next.13
388
+ * devDependencies
389
+ * @twin.org/merge-locales bumped from 0.0.3-next.12 to 0.0.3-next.13
390
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.12 to 0.0.3-next.13
391
+
392
+ ## [0.0.3-next.12](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.11...validate-locales-v0.0.3-next.12) (2026-01-08)
393
+
394
+
395
+ ### Miscellaneous Chores
396
+
397
+ * **validate-locales:** Synchronize repo versions
398
+
399
+
400
+ ### Dependencies
401
+
402
+ * The following workspace dependencies were updated
403
+ * dependencies
404
+ * @twin.org/cli-core bumped from 0.0.3-next.11 to 0.0.3-next.12
405
+ * @twin.org/core bumped from 0.0.3-next.11 to 0.0.3-next.12
406
+ * @twin.org/nameof bumped from 0.0.3-next.11 to 0.0.3-next.12
407
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.11 to 0.0.3-next.12
408
+ * devDependencies
409
+ * @twin.org/merge-locales bumped from 0.0.3-next.11 to 0.0.3-next.12
410
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.11 to 0.0.3-next.12
411
+
412
+ ## [0.0.3-next.11](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.10...validate-locales-v0.0.3-next.11) (2026-01-07)
413
+
414
+
415
+ ### Miscellaneous Chores
416
+
417
+ * **validate-locales:** Synchronize repo versions
418
+
419
+
420
+ ### Dependencies
421
+
422
+ * The following workspace dependencies were updated
423
+ * dependencies
424
+ * @twin.org/cli-core bumped from 0.0.3-next.10 to 0.0.3-next.11
425
+ * @twin.org/core bumped from 0.0.3-next.10 to 0.0.3-next.11
426
+ * @twin.org/nameof bumped from 0.0.3-next.10 to 0.0.3-next.11
427
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.10 to 0.0.3-next.11
428
+ * devDependencies
429
+ * @twin.org/merge-locales bumped from 0.0.3-next.10 to 0.0.3-next.11
430
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.10 to 0.0.3-next.11
431
+
432
+ ## [0.0.3-next.10](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.9...validate-locales-v0.0.3-next.10) (2026-01-07)
433
+
434
+
435
+ ### Miscellaneous Chores
436
+
437
+ * **validate-locales:** Synchronize repo versions
438
+
439
+
440
+ ### Dependencies
441
+
442
+ * The following workspace dependencies were updated
443
+ * dependencies
444
+ * @twin.org/cli-core bumped from 0.0.3-next.9 to 0.0.3-next.10
445
+ * @twin.org/core bumped from 0.0.3-next.9 to 0.0.3-next.10
446
+ * @twin.org/nameof bumped from 0.0.3-next.9 to 0.0.3-next.10
447
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.9 to 0.0.3-next.10
448
+ * devDependencies
449
+ * @twin.org/merge-locales bumped from 0.0.3-next.9 to 0.0.3-next.10
450
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.9 to 0.0.3-next.10
451
+
452
+ ## [0.0.3-next.9](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.8...validate-locales-v0.0.3-next.9) (2026-01-05)
453
+
454
+
455
+ ### Miscellaneous Chores
456
+
457
+ * **validate-locales:** Synchronize repo versions
458
+
459
+
460
+ ### Dependencies
461
+
462
+ * The following workspace dependencies were updated
463
+ * dependencies
464
+ * @twin.org/cli-core bumped from 0.0.3-next.8 to 0.0.3-next.9
465
+ * @twin.org/core bumped from 0.0.3-next.8 to 0.0.3-next.9
466
+ * @twin.org/nameof bumped from 0.0.3-next.8 to 0.0.3-next.9
467
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.8 to 0.0.3-next.9
468
+ * devDependencies
469
+ * @twin.org/merge-locales bumped from 0.0.3-next.8 to 0.0.3-next.9
470
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.8 to 0.0.3-next.9
471
+
472
+ ## [0.0.3-next.8](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.7...validate-locales-v0.0.3-next.8) (2025-11-26)
473
+
474
+
475
+ ### Features
476
+
477
+ * support for "property" assignments in validate-locales ([2414a0c](https://github.com/twinfoundation/framework/commit/2414a0c2e29d8935a17b58b9bdc31609c0f97140))
478
+
479
+
480
+ ### Dependencies
481
+
482
+ * The following workspace dependencies were updated
483
+ * dependencies
484
+ * @twin.org/cli-core bumped from 0.0.3-next.7 to 0.0.3-next.8
485
+ * @twin.org/core bumped from 0.0.3-next.7 to 0.0.3-next.8
486
+ * @twin.org/nameof bumped from 0.0.3-next.7 to 0.0.3-next.8
487
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.7 to 0.0.3-next.8
488
+ * devDependencies
489
+ * @twin.org/merge-locales bumped from 0.0.3-next.7 to 0.0.3-next.8
490
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.7 to 0.0.3-next.8
491
+
492
+ ## [0.0.3-next.7](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.6...validate-locales-v0.0.3-next.7) (2025-11-25)
493
+
494
+
495
+ ### Features
496
+
497
+ * add context id features ([#206](https://github.com/twinfoundation/framework/issues/206)) ([ef0d4ee](https://github.com/twinfoundation/framework/commit/ef0d4ee11a4f5fc6cc6f52a4958ce905c04ee13b))
498
+ * detect unused prefixes and non i18 key messages ([a357810](https://github.com/twinfoundation/framework/commit/a357810754e25478496c2e6fd71ddc49dee9f747))
499
+ * locales validation ([#197](https://github.com/twinfoundation/framework/issues/197)) ([55fdadb](https://github.com/twinfoundation/framework/commit/55fdadb13595ce0047f787bd1d4135d429a99f12))
500
+
501
+
502
+ ### Bug Fixes
503
+
504
+ * validate locales missing log key ([54fb89a](https://github.com/twinfoundation/framework/commit/54fb89ae9e05ab7dc79e42dc4933575c39bffd8a))
505
+ * validate locales missing log key ([14a649e](https://github.com/twinfoundation/framework/commit/14a649e569c0509bef045a76edf1818f3eca6ded))
506
+
507
+
508
+ ### Dependencies
509
+
510
+ * The following workspace dependencies were updated
511
+ * dependencies
512
+ * @twin.org/cli-core bumped from 0.0.3-next.6 to 0.0.3-next.7
513
+ * @twin.org/core bumped from 0.0.3-next.6 to 0.0.3-next.7
514
+ * @twin.org/nameof bumped from 0.0.3-next.6 to 0.0.3-next.7
515
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.6 to 0.0.3-next.7
516
+ * devDependencies
517
+ * @twin.org/merge-locales bumped from 0.0.3-next.6 to 0.0.3-next.7
518
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.6 to 0.0.3-next.7
519
+
520
+ ## [0.0.3-next.6](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.5...validate-locales-v0.0.3-next.6) (2025-11-25)
521
+
522
+
523
+ ### Miscellaneous Chores
524
+
525
+ * **validate-locales:** Synchronize repo versions
526
+
527
+
528
+ ### Dependencies
529
+
530
+ * The following workspace dependencies were updated
531
+ * dependencies
532
+ * @twin.org/cli-core bumped from 0.0.3-next.5 to 0.0.3-next.6
533
+ * @twin.org/core bumped from 0.0.3-next.5 to 0.0.3-next.6
534
+ * @twin.org/nameof bumped from 0.0.3-next.5 to 0.0.3-next.6
535
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.5 to 0.0.3-next.6
536
+ * devDependencies
537
+ * @twin.org/merge-locales bumped from 0.0.3-next.5 to 0.0.3-next.6
538
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.5 to 0.0.3-next.6
539
+
540
+ ## [0.0.3-next.5](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.4...validate-locales-v0.0.3-next.5) (2025-11-20)
541
+
542
+
543
+ ### Miscellaneous Chores
544
+
545
+ * **validate-locales:** Synchronize repo versions
546
+
547
+
548
+ ### Dependencies
549
+
550
+ * The following workspace dependencies were updated
551
+ * dependencies
552
+ * @twin.org/cli-core bumped from 0.0.3-next.4 to 0.0.3-next.5
553
+ * @twin.org/core bumped from 0.0.3-next.4 to 0.0.3-next.5
554
+ * @twin.org/nameof bumped from 0.0.3-next.4 to 0.0.3-next.5
555
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.4 to 0.0.3-next.5
556
+ * devDependencies
557
+ * @twin.org/merge-locales bumped from 0.0.3-next.4 to 0.0.3-next.5
558
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.4 to 0.0.3-next.5
559
+
560
+ ## [0.0.3-next.4](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.3...validate-locales-v0.0.3-next.4) (2025-11-13)
561
+
562
+
563
+ ### Miscellaneous Chores
564
+
565
+ * **validate-locales:** Synchronize repo versions
566
+
567
+
568
+ ### Dependencies
569
+
570
+ * The following workspace dependencies were updated
571
+ * dependencies
572
+ * @twin.org/cli-core bumped from 0.0.3-next.3 to 0.0.3-next.4
573
+ * @twin.org/core bumped from 0.0.3-next.3 to 0.0.3-next.4
574
+ * @twin.org/nameof bumped from 0.0.3-next.3 to 0.0.3-next.4
575
+ * @twin.org/nameof-transformer bumped from 0.0.3-next.3 to 0.0.3-next.4
576
+ * devDependencies
577
+ * @twin.org/merge-locales bumped from 0.0.3-next.3 to 0.0.3-next.4
578
+ * @twin.org/nameof-vitest-plugin bumped from 0.0.3-next.3 to 0.0.3-next.4
579
+
3
580
  ## [0.0.3-next.3](https://github.com/twinfoundation/framework/compare/validate-locales-v0.0.3-next.2...validate-locales-v0.0.3-next.3) (2025-11-12)
4
581
 
5
582
 
@@ -101,4 +678,4 @@
101
678
  * devDependencies
102
679
  * @twin.org/nameof-vitest-plugin bumped from 0.0.2-next.20 to 0.0.2-next.21
103
680
 
104
- ## @twin.org/validate-locales - Changelog
681
+ ## Changelog
@@ -22,7 +22,71 @@ The main entry point for the CLI.
22
22
 
23
23
  ## Methods
24
24
 
25
- ### run()
25
+ ### execute() {#execute}
26
+
27
+ > **execute**(`options`, `localesDirectory`, `argv`): `Promise`\<`number`\>
28
+
29
+ Execute the command line processing.
30
+
31
+ #### Parameters
32
+
33
+ ##### options
34
+
35
+ `ICliOptions`
36
+
37
+ The options for the CLI.
38
+
39
+ ##### localesDirectory
40
+
41
+ `string`
42
+
43
+ The path to load the locales from.
44
+
45
+ ##### argv
46
+
47
+ `string`[]
48
+
49
+ The process arguments.
50
+
51
+ #### Returns
52
+
53
+ `Promise`\<`number`\>
54
+
55
+ The exit code.
56
+
57
+ #### Inherited from
58
+
59
+ `CLIBase.execute`
60
+
61
+ ***
62
+
63
+ ### getCommands() {#getcommands}
64
+
65
+ > `protected` **getCommands**(`program`): `Command`[]
66
+
67
+ Get the commands for the CLI, override in derived class to supply your own.
68
+
69
+ #### Parameters
70
+
71
+ ##### program
72
+
73
+ `Command`
74
+
75
+ The main program that the commands will be added to.
76
+
77
+ #### Returns
78
+
79
+ `Command`[]
80
+
81
+ The commands for the CLI.
82
+
83
+ #### Inherited from
84
+
85
+ `CLIBase.getCommands`
86
+
87
+ ***
88
+
89
+ ### run() {#run}
26
90
 
27
91
  > **run**(`argv`, `localesDirectory?`, `options?`): `Promise`\<`number`\>
28
92
 
@@ -60,7 +124,7 @@ The exit code.
60
124
 
61
125
  ***
62
126
 
63
- ### configureRoot()
127
+ ### configureRoot() {#configureroot}
64
128
 
65
129
  > `protected` **configureRoot**(`program`): `void`
66
130
 
package/docs/usage.md ADDED
@@ -0,0 +1,35 @@
1
+ # Validate Locales Usage
2
+
3
+ Use this page to confirm validation options before scanning source files.
4
+
5
+ ## Running
6
+
7
+ To install and run the CLI locally use the following commands:
8
+
9
+ ```shell
10
+ npm install @twin.org/validate-locales -g
11
+ validate-locales
12
+ ```
13
+
14
+ or run directly using NPX:
15
+
16
+ ```shell
17
+ npx "@twin.org/validate-locales"
18
+ ```
19
+
20
+ ## Help
21
+
22
+ ```shell
23
+ validate-locales --help
24
+
25
+ Usage: validate-locales [options]
26
+
27
+ Options:
28
+ --cwd <path> Current working directory to scan. (default: ".")
29
+ --source-glob <glob> Glob for source files to validate.
30
+ --locale-file <path> Locale dictionary file to validate against.
31
+ --ignore-key-pattern <pattern> Regex pattern for keys to ignore.
32
+ --report-unused Include unused locale keys in the report.
33
+ --lang <lang> The language to display the output in. (default: "en")
34
+ -h, --help display help for command
35
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@twin.org/validate-locales",
3
- "version": "0.0.3-next.3",
4
- "description": "Tool to validate source files against the locales",
3
+ "version": "0.0.3-next.31",
4
+ "description": "Validate source files against the locales",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/twinfoundation/framework.git",
@@ -14,12 +14,12 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/cli-core": "0.0.3-next.3",
18
- "@twin.org/core": "0.0.3-next.3",
19
- "@twin.org/nameof": "0.0.3-next.3",
20
- "@twin.org/nameof-transformer": "0.0.3-next.3",
21
- "commander": "14.0.2",
22
- "glob": "11.0.3",
17
+ "@twin.org/cli-core": "0.0.3-next.31",
18
+ "@twin.org/core": "0.0.3-next.31",
19
+ "@twin.org/nameof": "0.0.3-next.31",
20
+ "@twin.org/nameof-transformer": "0.0.3-next.31",
21
+ "commander": "14.0.3",
22
+ "glob": "13.0.6",
23
23
  "typescript": "5.9.3"
24
24
  },
25
25
  "main": "./dist/es/index.js",
package/docs/examples.md DELETED
@@ -1,15 +0,0 @@
1
- # @twin.org/validate-locales - Examples
2
-
3
- ## Command Line Tool
4
-
5
- First install the tool with the following script.
6
-
7
- ```shell
8
- npm install @twin.org/validate-locales
9
- ```
10
-
11
- You can then run the tool from the command line e.g.
12
-
13
- ```shell
14
- validate-locales
15
- ```