i18next-cli 1.42.5 → 1.42.7

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.
@@ -2,7 +2,7 @@ import { ConsoleLogger } from './utils/logger.js';
2
2
  import { mergeResourcesAsInterface } from 'i18next-resources-for-ts';
3
3
  import { glob } from 'glob';
4
4
  import { createSpinnerLike } from './utils/wrap-ora.js';
5
- import chalk from 'chalk';
5
+ import { styleText } from 'node:util';
6
6
  import { mkdir, writeFile, access, readFile } from 'node:fs/promises';
7
7
  import { join, dirname, basename, extname, resolve, relative } from 'node:path';
8
8
  import { transform } from '@swc/core';
@@ -109,7 +109,7 @@ async function runTypesGenerator(config, options = {}) {
109
109
  }
110
110
  const nonObjectKeys = keys.filter(k => !parsedContent[k] || typeof parsedContent[k] !== 'object');
111
111
  if (nonObjectKeys.length > 0) {
112
- console.warn(chalk.yellow(`Warning: The file ${file} contains top-level keys that are not objects (${nonObjectKeys.join(', ')}). When 'mergeNamespaces' is enabled, top-level keys are treated as namespaces. These keys will be ignored.`));
112
+ console.warn(styleText('yellow', `Warning: The file ${file} contains top-level keys that are not objects (${nonObjectKeys.join(', ')}). When 'mergeNamespaces' is enabled, top-level keys are treated as namespaces. These keys will be ignored.`));
113
113
  }
114
114
  continue;
115
115
  }
@@ -125,7 +125,7 @@ ${mergeResourcesAsInterface(resources, { optimize: !!enableSelector, indentation
125
125
  const resourcesOutputPath = resolve(process.cwd(), config.types.resourcesFile);
126
126
  await mkdir(dirname(resourcesOutputPath), { recursive: true });
127
127
  await writeFile(resourcesOutputPath, interfaceDefinition);
128
- logMessages.push(` ${chalk.green('✓')} Resources interface written to ${config.types.resourcesFile}`);
128
+ logMessages.push(` ${styleText('green', '✓')} Resources interface written to ${config.types.resourcesFile}`);
129
129
  let outputPathExists;
130
130
  try {
131
131
  await access(outputPath);
@@ -152,13 +152,13 @@ declare module 'i18next' {
152
152
  }`;
153
153
  await mkdir(dirname(outputPath), { recursive: true });
154
154
  await writeFile(outputPath, fileContent);
155
- logMessages.push(` ${chalk.green('✓')} TypeScript definitions written to ${config.types.output || ''}`);
155
+ logMessages.push(` ${styleText('green', '✓')} TypeScript definitions written to ${config.types.output || ''}`);
156
156
  }
157
- spinner.succeed(chalk.bold('TypeScript definitions generated successfully.'));
157
+ spinner.succeed(styleText('bold', 'TypeScript definitions generated successfully.'));
158
158
  logMessages.forEach(msg => typeof internalLogger.info === 'function' ? internalLogger.info(msg) : console.log(msg));
159
159
  }
160
160
  catch (error) {
161
- spinner.fail(chalk.red('Failed to generate TypeScript definitions.'));
161
+ spinner.fail(styleText('red', 'Failed to generate TypeScript definitions.'));
162
162
  if (typeof internalLogger.error === 'function')
163
163
  internalLogger.error(error);
164
164
  else
@@ -43,6 +43,43 @@ function getOutputPath(outputTemplate, language, namespace) {
43
43
  out = out.replace(/\/\/+/g, '/');
44
44
  return normalize(out);
45
45
  }
46
+ /**
47
+ * Extracts the namespace value from a concrete file path by matching it against
48
+ * the output template.
49
+ *
50
+ * Given a template like `src/{{namespace}}/locales/{{language}}.json` and a file
51
+ * path like `src/widgets/component/locales/en.json`, this returns `widgets/component`.
52
+ *
53
+ * This handles multi-segment namespaces (namespaces containing `/`) which
54
+ * `basename()` cannot recover.
55
+ *
56
+ * @param outputTemplate - The output path template string (must contain `{{namespace}}`)
57
+ * @param language - The language value used when the file was generated
58
+ * @param filePath - The concrete file path to extract the namespace from
59
+ * @returns The namespace string, or `undefined` if the path doesn't match the template
60
+ */
61
+ function extractNamespaceFromPath(outputTemplate, language, filePath) {
62
+ // Build a regex from the template by escaping everything except the placeholders.
63
+ // Replace {{language}}/{{lng}} with the literal language value and
64
+ // {{namespace}} with a named capture group that matches one or more path segments.
65
+ const pattern = outputTemplate
66
+ // Normalise to forward slashes for matching
67
+ .replace(/\\/g, '/');
68
+ // Escape regex-special characters (but keep our placeholders intact first)
69
+ const nsPlaceholder = '{{namespace}}';
70
+ const parts = pattern.split(nsPlaceholder);
71
+ // Escape each part individually then rejoin with the capture group
72
+ const escaped = parts.map(p => p
73
+ .replace(/\{\{language\}\}|\{\{lng\}\}/g, () => escapeForRegex(language))
74
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
75
+ // Don't anchor the start — the glob may return absolute or prefixed paths.
76
+ // Anchor only the end so that the namespace capture is unambiguous.
77
+ const regexStr = escaped.join('(.+)') + '$';
78
+ const normalized = filePath.replace(/\\/g, '/');
79
+ const m = new RegExp(regexStr).exec(normalized);
80
+ return m?.[1];
81
+ }
82
+ const escapeForRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
46
83
  /**
47
84
  * Dynamically loads a translation file, supporting .json, .js, and .ts formats.
48
85
  * @param filePath - The path to the translation file.
@@ -154,4 +191,4 @@ function inferFormatFromPath(filePath, defaultFormat = 'json') {
154
191
  return defaultFormat || 'json';
155
192
  }
156
193
 
157
- export { getOutputPath, inferFormatFromPath, loadRawJson5Content, loadTranslationFile, serializeTranslationFile };
194
+ export { extractNamespaceFromPath, getOutputPath, inferFormatFromPath, loadRawJson5Content, loadTranslationFile, serializeTranslationFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.42.5",
3
+ "version": "1.42.7",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -63,7 +63,6 @@
63
63
  "memfs": "4.56.10",
64
64
  "neostandard": "0.12.2",
65
65
  "rollup-plugin-typescript2": "0.36.0",
66
- "ts-node": "10.9.2",
67
66
  "typescript": "5.9.3",
68
67
  "unplugin-swc": "1.5.9",
69
68
  "vitest": "4.0.18"
@@ -72,7 +71,6 @@
72
71
  "@croct/json5-parser": "0.2.2",
73
72
  "@swc/core": "1.15.11",
74
73
  "yaml": "2.8.2",
75
- "chalk": "5.6.2",
76
74
  "chokidar": "5.0.0",
77
75
  "commander": "14.0.3",
78
76
  "execa": "9.6.1",
@@ -84,7 +82,6 @@
84
82
  "minimatch": "10.1.2",
85
83
  "ora": "9.3.0",
86
84
  "react": "^19.2.4",
87
- "react-i18next": "^16.5.4",
88
- "swc-walk": "1.0.1"
85
+ "react-i18next": "^16.5.4"
89
86
  }
90
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAgyBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,oBAAoB,EAC5B,EACE,uBAA+B,EAC/B,OAAe,EAChB,GAAE;IACD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAA;CACb,GACL,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA0I9B"}
1
+ {"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAgyBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,oBAAoB,EAC5B,EACE,uBAA+B,EAC/B,OAAe,EAChB,GAAE;IACD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAA;CACb,GACL,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAmJ9B"}
@@ -48,6 +48,22 @@ export declare function writeFileAsync(filePath: string, data: string): Promise<
48
48
  * - Normalizes duplicate slashes and returns a platform-correct path.
49
49
  */
50
50
  export declare function getOutputPath(outputTemplate: string | ((language: string, namespace?: string) => string) | undefined, language: string, namespace?: string): string;
51
+ /**
52
+ * Extracts the namespace value from a concrete file path by matching it against
53
+ * the output template.
54
+ *
55
+ * Given a template like `src/{{namespace}}/locales/{{language}}.json` and a file
56
+ * path like `src/widgets/component/locales/en.json`, this returns `widgets/component`.
57
+ *
58
+ * This handles multi-segment namespaces (namespaces containing `/`) which
59
+ * `basename()` cannot recover.
60
+ *
61
+ * @param outputTemplate - The output path template string (must contain `{{namespace}}`)
62
+ * @param language - The language value used when the file was generated
63
+ * @param filePath - The concrete file path to extract the namespace from
64
+ * @returns The namespace string, or `undefined` if the path doesn't match the template
65
+ */
66
+ export declare function extractNamespaceFromPath(outputTemplate: string, language: string, filePath: string): string | undefined;
51
67
  /**
52
68
  * Dynamically loads a translation file, supporting .json, .js, and .ts formats.
53
69
  * @param filePath - The path to the translation file.
@@ -1 +1 @@
1
- {"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAKpD;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,EACvF,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA8BR;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAwChG;AAGD,wBAAsB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQnF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,GAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAU,EAChE,WAAW,GAAE,MAAM,GAAG,MAAU,EAChC,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CA6BR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,GAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAU,GACtE,WAAW,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC,CAO9D"}
1
+ {"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAKpD;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,EACvF,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA8BR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CAwBpB;AAID;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAwChG;AAGD,wBAAsB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQnF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,GAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAU,EAChE,WAAW,GAAE,MAAM,GAAG,MAAU,EAChC,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CA6BR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,GAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAU,GACtE,WAAW,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC,CAO9D"}