i18next-cli 1.38.2 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/rename-key.js +60 -24
- package/dist/esm/cli.js +1 -1
- package/dist/esm/rename-key.js +60 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ A unified, high-performance i18next CLI toolchain, powered by SWC.
|
|
|
33
33
|
|
|
34
34
|
## Features
|
|
35
35
|
|
|
36
|
-
- **Key Extraction**:
|
|
36
|
+
- **Key Extraction**: Extraction means automatically finding and collecting all translation keys used in your source code (JavaScript/TypeScript, etc.) by analyzing the code's structure (AST). This ensures every string that needs translation is identified and included in your translation files, reducing manual work and preventing missing keys.
|
|
37
37
|
- **Type Safety**: Generate TypeScript definitions for full autocomplete and type safety.
|
|
38
38
|
- **Locale Synchronization**: Keep all language files in sync with your primary language.
|
|
39
39
|
- **Accurate Code Linting**: Detect hardcoded strings with high precision and configurable rules.
|
package/dist/cjs/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ const program = new commander.Command();
|
|
|
28
28
|
program
|
|
29
29
|
.name('i18next-cli')
|
|
30
30
|
.description('A unified, high-performance i18next CLI.')
|
|
31
|
-
.version('1.
|
|
31
|
+
.version('1.39.0'); // This string is replaced with the actual version at build time by rollup
|
|
32
32
|
// new: global config override option
|
|
33
33
|
program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
|
|
34
34
|
program
|
package/dist/cjs/rename-key.js
CHANGED
|
@@ -307,28 +307,56 @@ async function updateTranslationFiles(oldParts, newParts, config, dryRun, logger
|
|
|
307
307
|
const results = [];
|
|
308
308
|
const keySeparator = config.extract.keySeparator ?? '.';
|
|
309
309
|
for (const locale of config.locales) {
|
|
310
|
-
const
|
|
311
|
-
const
|
|
310
|
+
const oldOutputPath = fileUtils.getOutputPath(config.extract.output, locale, oldParts.namespace);
|
|
311
|
+
const oldFullPath = node_path.resolve(process.cwd(), oldOutputPath);
|
|
312
|
+
const newOutputPath = fileUtils.getOutputPath(config.extract.output, locale, newParts.namespace);
|
|
313
|
+
const newFullPath = node_path.resolve(process.cwd(), newOutputPath);
|
|
314
|
+
let oldTranslations;
|
|
315
|
+
let newTranslations;
|
|
312
316
|
try {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
317
|
+
oldTranslations = await fileUtils.loadTranslationFile(oldFullPath);
|
|
318
|
+
}
|
|
319
|
+
catch { }
|
|
320
|
+
if (!oldTranslations)
|
|
321
|
+
continue;
|
|
322
|
+
const oldValue = nestedObject.getNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
323
|
+
if (oldValue === undefined)
|
|
324
|
+
continue;
|
|
325
|
+
if (oldParts.namespace === newParts.namespace) {
|
|
326
|
+
// Rename within the same namespace
|
|
327
|
+
deleteNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
328
|
+
nestedObject.setNestedValue(oldTranslations, newParts.key, oldValue, keySeparator);
|
|
323
329
|
if (!dryRun) {
|
|
324
|
-
const content = fileUtils.serializeTranslationFile(
|
|
325
|
-
await promises.writeFile(
|
|
330
|
+
const content = fileUtils.serializeTranslationFile(oldTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
331
|
+
await promises.writeFile(oldFullPath, content, 'utf-8');
|
|
326
332
|
}
|
|
327
|
-
results.push({ path:
|
|
328
|
-
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${
|
|
333
|
+
results.push({ path: oldFullPath, updated: true });
|
|
334
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${oldFullPath}`);
|
|
329
335
|
}
|
|
330
|
-
|
|
331
|
-
//
|
|
336
|
+
else {
|
|
337
|
+
// Move across namespaces
|
|
338
|
+
// Remove from old namespace
|
|
339
|
+
deleteNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
340
|
+
if (!dryRun) {
|
|
341
|
+
const content = fileUtils.serializeTranslationFile(oldTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
342
|
+
await promises.writeFile(oldFullPath, content, 'utf-8');
|
|
343
|
+
}
|
|
344
|
+
results.push({ path: oldFullPath, updated: true });
|
|
345
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${oldFullPath}`);
|
|
346
|
+
// Add to new namespace
|
|
347
|
+
try {
|
|
348
|
+
newTranslations = await fileUtils.loadTranslationFile(newFullPath);
|
|
349
|
+
}
|
|
350
|
+
catch { }
|
|
351
|
+
if (!newTranslations)
|
|
352
|
+
newTranslations = {};
|
|
353
|
+
nestedObject.setNestedValue(newTranslations, newParts.key, oldValue, keySeparator);
|
|
354
|
+
if (!dryRun) {
|
|
355
|
+
const content = fileUtils.serializeTranslationFile(newTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
356
|
+
await promises.writeFile(newFullPath, content, 'utf-8');
|
|
357
|
+
}
|
|
358
|
+
results.push({ path: newFullPath, updated: true });
|
|
359
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${newFullPath}`);
|
|
332
360
|
}
|
|
333
361
|
}
|
|
334
362
|
if (results.length > 0) {
|
|
@@ -342,13 +370,21 @@ function deleteNestedValue(obj, path, separator) {
|
|
|
342
370
|
return;
|
|
343
371
|
}
|
|
344
372
|
const keys = path.split(String(separator));
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
373
|
+
function _delete(current, idx) {
|
|
374
|
+
const key = keys[idx];
|
|
375
|
+
if (idx === keys.length - 1) {
|
|
376
|
+
delete current[key];
|
|
377
|
+
}
|
|
378
|
+
else if (current[key]) {
|
|
379
|
+
const shouldDelete = _delete(current[key], idx + 1);
|
|
380
|
+
if (shouldDelete) {
|
|
381
|
+
delete current[key];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// Return true if current is now empty
|
|
385
|
+
return typeof current === 'object' && current !== null && Object.keys(current).length === 0;
|
|
350
386
|
}
|
|
351
|
-
|
|
387
|
+
_delete(obj, 0);
|
|
352
388
|
}
|
|
353
389
|
|
|
354
390
|
exports.runRenameKey = runRenameKey;
|
package/dist/esm/cli.js
CHANGED
|
@@ -26,7 +26,7 @@ const program = new Command();
|
|
|
26
26
|
program
|
|
27
27
|
.name('i18next-cli')
|
|
28
28
|
.description('A unified, high-performance i18next CLI.')
|
|
29
|
-
.version('1.
|
|
29
|
+
.version('1.39.0'); // This string is replaced with the actual version at build time by rollup
|
|
30
30
|
// new: global config override option
|
|
31
31
|
program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
|
|
32
32
|
program
|
package/dist/esm/rename-key.js
CHANGED
|
@@ -305,28 +305,56 @@ async function updateTranslationFiles(oldParts, newParts, config, dryRun, logger
|
|
|
305
305
|
const results = [];
|
|
306
306
|
const keySeparator = config.extract.keySeparator ?? '.';
|
|
307
307
|
for (const locale of config.locales) {
|
|
308
|
-
const
|
|
309
|
-
const
|
|
308
|
+
const oldOutputPath = getOutputPath(config.extract.output, locale, oldParts.namespace);
|
|
309
|
+
const oldFullPath = resolve(process.cwd(), oldOutputPath);
|
|
310
|
+
const newOutputPath = getOutputPath(config.extract.output, locale, newParts.namespace);
|
|
311
|
+
const newFullPath = resolve(process.cwd(), newOutputPath);
|
|
312
|
+
let oldTranslations;
|
|
313
|
+
let newTranslations;
|
|
310
314
|
try {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
315
|
+
oldTranslations = await loadTranslationFile(oldFullPath);
|
|
316
|
+
}
|
|
317
|
+
catch { }
|
|
318
|
+
if (!oldTranslations)
|
|
319
|
+
continue;
|
|
320
|
+
const oldValue = getNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
321
|
+
if (oldValue === undefined)
|
|
322
|
+
continue;
|
|
323
|
+
if (oldParts.namespace === newParts.namespace) {
|
|
324
|
+
// Rename within the same namespace
|
|
325
|
+
deleteNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
326
|
+
setNestedValue(oldTranslations, newParts.key, oldValue, keySeparator);
|
|
321
327
|
if (!dryRun) {
|
|
322
|
-
const content = serializeTranslationFile(
|
|
323
|
-
await writeFile(
|
|
328
|
+
const content = serializeTranslationFile(oldTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
329
|
+
await writeFile(oldFullPath, content, 'utf-8');
|
|
324
330
|
}
|
|
325
|
-
results.push({ path:
|
|
326
|
-
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${
|
|
331
|
+
results.push({ path: oldFullPath, updated: true });
|
|
332
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${oldFullPath}`);
|
|
327
333
|
}
|
|
328
|
-
|
|
329
|
-
//
|
|
334
|
+
else {
|
|
335
|
+
// Move across namespaces
|
|
336
|
+
// Remove from old namespace
|
|
337
|
+
deleteNestedValue(oldTranslations, oldParts.key, keySeparator);
|
|
338
|
+
if (!dryRun) {
|
|
339
|
+
const content = serializeTranslationFile(oldTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
340
|
+
await writeFile(oldFullPath, content, 'utf-8');
|
|
341
|
+
}
|
|
342
|
+
results.push({ path: oldFullPath, updated: true });
|
|
343
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${oldFullPath}`);
|
|
344
|
+
// Add to new namespace
|
|
345
|
+
try {
|
|
346
|
+
newTranslations = await loadTranslationFile(newFullPath);
|
|
347
|
+
}
|
|
348
|
+
catch { }
|
|
349
|
+
if (!newTranslations)
|
|
350
|
+
newTranslations = {};
|
|
351
|
+
setNestedValue(newTranslations, newParts.key, oldValue, keySeparator);
|
|
352
|
+
if (!dryRun) {
|
|
353
|
+
const content = serializeTranslationFile(newTranslations, config.extract.outputFormat, config.extract.indentation);
|
|
354
|
+
await writeFile(newFullPath, content, 'utf-8');
|
|
355
|
+
}
|
|
356
|
+
results.push({ path: newFullPath, updated: true });
|
|
357
|
+
logger.info(` ${dryRun ? '(dry-run) ' : ''}✓ ${newFullPath}`);
|
|
330
358
|
}
|
|
331
359
|
}
|
|
332
360
|
if (results.length > 0) {
|
|
@@ -340,13 +368,21 @@ function deleteNestedValue(obj, path, separator) {
|
|
|
340
368
|
return;
|
|
341
369
|
}
|
|
342
370
|
const keys = path.split(String(separator));
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
|
|
371
|
+
function _delete(current, idx) {
|
|
372
|
+
const key = keys[idx];
|
|
373
|
+
if (idx === keys.length - 1) {
|
|
374
|
+
delete current[key];
|
|
375
|
+
}
|
|
376
|
+
else if (current[key]) {
|
|
377
|
+
const shouldDelete = _delete(current[key], idx + 1);
|
|
378
|
+
if (shouldDelete) {
|
|
379
|
+
delete current[key];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Return true if current is now empty
|
|
383
|
+
return typeof current === 'object' && current !== null && Object.keys(current).length === 0;
|
|
348
384
|
}
|
|
349
|
-
|
|
385
|
+
_delete(obj, 0);
|
|
350
386
|
}
|
|
351
387
|
|
|
352
388
|
export { runRenameKey };
|