i18next-cli 1.41.4 → 1.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -1
- package/dist/cjs/cli.js +2 -1
- package/dist/cjs/extractor/core/extractor.js +1 -1
- package/dist/cjs/heuristic-config.js +15 -0
- package/dist/cjs/linter.js +24 -10
- package/dist/cjs/syncer.js +1 -1
- package/dist/cjs/utils/file-utils.js +27 -0
- package/dist/esm/cli.js +2 -1
- package/dist/esm/extractor/core/extractor.js +2 -2
- package/dist/esm/heuristic-config.js +15 -0
- package/dist/esm/linter.js +24 -10
- package/dist/esm/syncer.js +2 -2
- package/dist/esm/utils/file-utils.js +27 -1
- package/package.json +6 -5
- package/types/heuristic-config.d.ts.map +1 -1
- package/types/linter.d.ts +2 -0
- package/types/linter.d.ts.map +1 -1
- package/types/types.d.ts +2 -1
- package/types/types.d.ts.map +1 -1
- package/types/utils/file-utils.d.ts +7 -0
- package/types/utils/file-utils.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -375,7 +375,8 @@ export default defineConfig({
|
|
|
375
375
|
|
|
376
376
|
// Use '.ts' files with `export default` instead of '.json'
|
|
377
377
|
// Or use 'json5' to enable JSON5 features (comments, trailing commas, formatting are tried to be preserved)
|
|
378
|
-
//
|
|
378
|
+
// Or use 'yaml' for YAML format (.yaml or .yml extensions)
|
|
379
|
+
// if the file ending is .json5, .yaml, or .yml it automatically uses the corresponding format
|
|
379
380
|
outputFormat: 'ts',
|
|
380
381
|
|
|
381
382
|
// Combine all namespaces into a single file per language (e.g., locales/en.ts)
|
|
@@ -875,6 +876,34 @@ export default {
|
|
|
875
876
|
} as const;
|
|
876
877
|
```
|
|
877
878
|
|
|
879
|
+
### YAML Translation Files
|
|
880
|
+
|
|
881
|
+
For projects that prefer YAML for better readability and compatibility with other tools, you can configure the CLI to output YAML files instead of JSON.
|
|
882
|
+
|
|
883
|
+
Configuration (`i18next.config.ts`):
|
|
884
|
+
|
|
885
|
+
```typescript
|
|
886
|
+
export default defineConfig({
|
|
887
|
+
extract: {
|
|
888
|
+
output: 'locales/{{language}}/{{namespace}}.yaml', // Use .yaml or .yml
|
|
889
|
+
outputFormat: 'yaml', // Optional - inferred from file extension
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
This will generate files like `locales/en/translation.yaml` with the following content:
|
|
895
|
+
|
|
896
|
+
```yaml
|
|
897
|
+
app:
|
|
898
|
+
title: My Application
|
|
899
|
+
description: Welcome to our app
|
|
900
|
+
button:
|
|
901
|
+
save: Save
|
|
902
|
+
cancel: Cancel
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
> **💡 Note:** Both `.yaml` and `.yml` extensions are supported and preserved. The `outputFormat: 'yaml'` option is optional when using these extensions - the format is automatically inferred from the file extension.
|
|
906
|
+
|
|
878
907
|
### Merging Namespaces
|
|
879
908
|
|
|
880
909
|
You can also combine all namespaces into a single file per language. This is useful for reducing the number of network requests in some application setups.
|
|
@@ -1140,6 +1169,7 @@ This programmatic API gives you the same power as the CLI but with full control
|
|
|
1140
1169
|
|
|
1141
1170
|
- [i18next-cli-plugin-svelte](https://github.com/dreamscached/i18next-cli-plugin-svelte) — a simple plugin to extract translation keys from Svelte components
|
|
1142
1171
|
- [rsbuild-plugin-i18next-extractor](https://github.com/rspack-contrib/rsbuild-plugin-i18next-extractor) — A Rsbuild plugin that leverages the Rspack module graph to extract only the i18n translations that are actually imported and used in your code, preventing unused translations from being bundled.
|
|
1172
|
+
- [i18next-cli-vue](https://github.com/PBK-B/i18next-cli-vue) — i18next-cli plugin for extracting i18n keys from Vue SFC files, applicable to vue2 and vue3
|
|
1143
1173
|
|
|
1144
1174
|
---
|
|
1145
1175
|
|
package/dist/cjs/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ require('node:path');
|
|
|
15
15
|
require('node:fs/promises');
|
|
16
16
|
require('jiti');
|
|
17
17
|
require('@croct/json5-parser');
|
|
18
|
+
require('yaml');
|
|
18
19
|
var typesGenerator = require('./types-generator.js');
|
|
19
20
|
var syncer = require('./syncer.js');
|
|
20
21
|
var migrator = require('./migrator.js');
|
|
@@ -28,7 +29,7 @@ const program = new commander.Command();
|
|
|
28
29
|
program
|
|
29
30
|
.name('i18next-cli')
|
|
30
31
|
.description('A unified, high-performance i18next CLI.')
|
|
31
|
-
.version('1.
|
|
32
|
+
.version('1.42.1'); // This string is replaced with the actual version at build time by rollup
|
|
32
33
|
// new: global config override option
|
|
33
34
|
program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
|
|
34
35
|
program
|
|
@@ -63,7 +63,7 @@ async function runExtractor(config, options = {}) {
|
|
|
63
63
|
anyFileUpdated = true;
|
|
64
64
|
if (!options.isDryRun) {
|
|
65
65
|
// prefer explicit outputFormat; otherwise infer from file extension per-file
|
|
66
|
-
const effectiveFormat = config.extract.outputFormat ?? (result.path
|
|
66
|
+
const effectiveFormat = config.extract.outputFormat ?? fileUtils.inferFormatFromPath(result.path);
|
|
67
67
|
const rawContent = effectiveFormat === 'json5'
|
|
68
68
|
? (await fileUtils.loadRawJson5Content(result.path)) ?? undefined
|
|
69
69
|
: undefined;
|
|
@@ -24,6 +24,18 @@ const HEURISTIC_PATTERNS = [
|
|
|
24
24
|
'src/assets/locales/en/*.json5',
|
|
25
25
|
'app/i18n/locales/en/*.json5',
|
|
26
26
|
'src/i18n/locales/en/*.json5',
|
|
27
|
+
'public/locales/en/*.yaml',
|
|
28
|
+
'locales/en/*.yaml',
|
|
29
|
+
'src/locales/en/*.yaml',
|
|
30
|
+
'src/assets/locales/en/*.yaml',
|
|
31
|
+
'app/i18n/locales/en/*.yaml',
|
|
32
|
+
'src/i18n/locales/en/*.yaml',
|
|
33
|
+
'public/locales/en/*.yml',
|
|
34
|
+
'locales/en/*.yml',
|
|
35
|
+
'src/locales/en/*.yml',
|
|
36
|
+
'src/assets/locales/en/*.yml',
|
|
37
|
+
'app/i18n/locales/en/*.yml',
|
|
38
|
+
'src/i18n/locales/en/*.yml',
|
|
27
39
|
'public/locales/en-*/*.json',
|
|
28
40
|
'locales/en-*/*.json',
|
|
29
41
|
'src/locales/en-*/*.json',
|
|
@@ -60,6 +72,9 @@ async function detectConfig() {
|
|
|
60
72
|
else if (extension === '.json5') {
|
|
61
73
|
outputFormat = 'json5';
|
|
62
74
|
}
|
|
75
|
+
else if (extension === '.yaml' || extension === '.yml') {
|
|
76
|
+
outputFormat = 'yaml';
|
|
77
|
+
}
|
|
63
78
|
try {
|
|
64
79
|
const allDirs = await promises.readdir(basePath);
|
|
65
80
|
let locales = allDirs.filter(dir => /^(dev|[a-z]{2}(-[A-Z]{2})?)$/.test(dir));
|
package/dist/cjs/linter.js
CHANGED
|
@@ -94,25 +94,37 @@ function lintInterpolationParams(ast, code, config) {
|
|
|
94
94
|
let paramKeys = [];
|
|
95
95
|
if (arg1?.type === 'ObjectExpression') {
|
|
96
96
|
paramKeys = arg1.properties
|
|
97
|
-
.filter((p) => p.type === 'KeyValueProperty')
|
|
98
97
|
.map((p) => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
// Standard key:value property like { name: "value" }
|
|
99
|
+
if (p.type === 'KeyValueProperty' && p.key) {
|
|
100
|
+
if (p.key.type === 'Identifier')
|
|
101
|
+
return p.key.value;
|
|
102
|
+
if (p.key.type === 'StringLiteral')
|
|
103
|
+
return p.key.value;
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
// Shorthand property like { hours, minutes }
|
|
107
|
+
if (p.type === 'ShorthandProperty' || p.type === 'Identifier') {
|
|
108
|
+
return p.value ?? p.name;
|
|
109
|
+
}
|
|
103
110
|
return undefined;
|
|
104
111
|
})
|
|
105
112
|
.filter((k) => typeof k === 'string');
|
|
106
113
|
}
|
|
107
114
|
if (!Array.isArray(paramKeys))
|
|
108
115
|
paramKeys = [];
|
|
116
|
+
// Use text search for accurate line numbers (SWC spans use global byte offsets, not per-file)
|
|
117
|
+
const searchText = arg0.raw ?? `"${arg0.value}"`;
|
|
118
|
+
const position = code.indexOf(searchText);
|
|
119
|
+
const issueLineNumber = position > -1 ? getLineNumber(position) : 1;
|
|
109
120
|
// Only check for unused parameters if there is at least one interpolation key in the string
|
|
110
121
|
if (keys.length > 0) {
|
|
111
122
|
for (const k of keys) {
|
|
112
123
|
if (!paramKeys.includes(k)) {
|
|
113
124
|
issues.push({
|
|
114
125
|
text: `Interpolation parameter "${k}" was not provided`,
|
|
115
|
-
line:
|
|
126
|
+
line: issueLineNumber,
|
|
127
|
+
type: 'interpolation',
|
|
116
128
|
});
|
|
117
129
|
}
|
|
118
130
|
}
|
|
@@ -120,7 +132,8 @@ function lintInterpolationParams(ast, code, config) {
|
|
|
120
132
|
if (!keys.includes(pk)) {
|
|
121
133
|
issues.push({
|
|
122
134
|
text: `Parameter "${pk}" is not used in translation string`,
|
|
123
|
-
line:
|
|
135
|
+
line: issueLineNumber,
|
|
136
|
+
type: 'interpolation',
|
|
124
137
|
});
|
|
125
138
|
}
|
|
126
139
|
}
|
|
@@ -302,11 +315,12 @@ async function runLinterCli(config, options = {}) {
|
|
|
302
315
|
internalLogger.info(chalk.yellow(`\n${file}`));
|
|
303
316
|
else
|
|
304
317
|
console.log(chalk.yellow(`\n${file}`));
|
|
305
|
-
issues.forEach(({ text, line }) => {
|
|
318
|
+
issues.forEach(({ text, line, type }) => {
|
|
319
|
+
const label = type === 'interpolation' ? 'Interpolation issue' : 'Found hardcoded string';
|
|
306
320
|
if (typeof internalLogger.info === 'function')
|
|
307
|
-
internalLogger.info(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')}
|
|
321
|
+
internalLogger.info(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')} ${label}: "${text}"`);
|
|
308
322
|
else
|
|
309
|
-
console.log(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')}
|
|
323
|
+
console.log(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')} ${label}: "${text}"`);
|
|
310
324
|
});
|
|
311
325
|
}
|
|
312
326
|
process.exit(1);
|
package/dist/cjs/syncer.js
CHANGED
|
@@ -97,7 +97,7 @@ async function runSyncer(config, options = {}) {
|
|
|
97
97
|
const newContent = JSON.stringify(newSecondaryTranslations);
|
|
98
98
|
if (newContent !== oldContent) {
|
|
99
99
|
wasAnythingSynced = true;
|
|
100
|
-
const perFileFormat = config.extract.outputFormat ?? (fullSecondaryPath
|
|
100
|
+
const perFileFormat = config.extract.outputFormat ?? fileUtils.inferFormatFromPath(fullSecondaryPath, outputFormat);
|
|
101
101
|
const raw = perFileFormat === 'json5' ? (await fileUtils.loadRawJson5Content(fullSecondaryPath)) ?? undefined : undefined;
|
|
102
102
|
const serializedContent = fileUtils.serializeTranslationFile(newSecondaryTranslations, perFileFormat, indentation, raw);
|
|
103
103
|
await promises.mkdir(node_path.dirname(fullSecondaryPath), { recursive: true });
|
|
@@ -5,6 +5,7 @@ var node_path = require('node:path');
|
|
|
5
5
|
var jiti = require('jiti');
|
|
6
6
|
var config = require('../config.js');
|
|
7
7
|
var json5Parser = require('@croct/json5-parser');
|
|
8
|
+
var yaml = require('yaml');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Resolve an output template (string or function) into an actual path string.
|
|
@@ -65,6 +66,10 @@ async function loadTranslationFile(filePath) {
|
|
|
65
66
|
const node = json5Parser.JsonParser.parse(content, json5Parser.JsonObjectNode);
|
|
66
67
|
return node.toJSON();
|
|
67
68
|
}
|
|
69
|
+
else if (ext === '.yaml' || ext === '.yml') {
|
|
70
|
+
const content = await promises.readFile(fullPath, 'utf-8');
|
|
71
|
+
return yaml.parse(content);
|
|
72
|
+
}
|
|
68
73
|
else if (ext === '.json') {
|
|
69
74
|
const content = await promises.readFile(fullPath, 'utf-8');
|
|
70
75
|
return JSON.parse(content);
|
|
@@ -116,6 +121,8 @@ function serializeTranslationFile(data, format = 'json', indentation = 2, rawCon
|
|
|
116
121
|
const node = json5Parser.JsonParser.parse(jsonString, json5Parser.JsonObjectNode);
|
|
117
122
|
return node.toString({ object: { indentationSize: Number(indentation) ?? 2 } });
|
|
118
123
|
}
|
|
124
|
+
case 'yaml':
|
|
125
|
+
return yaml.stringify(data, { indent: Number(indentation) || 2, lineWidth: 0 });
|
|
119
126
|
case 'js':
|
|
120
127
|
case 'js-esm':
|
|
121
128
|
return `export default ${jsonString};\n`;
|
|
@@ -129,8 +136,28 @@ function serializeTranslationFile(data, format = 'json', indentation = 2, rawCon
|
|
|
129
136
|
return `${jsonString}\n`;
|
|
130
137
|
}
|
|
131
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Infers the output format from the file path extension.
|
|
141
|
+
* @param filePath - The path to the translation file
|
|
142
|
+
* @param defaultFormat - The default format to return if no match (default: 'json')
|
|
143
|
+
* @returns The inferred output format
|
|
144
|
+
*/
|
|
145
|
+
function inferFormatFromPath(filePath, defaultFormat = 'json') {
|
|
146
|
+
if (filePath.endsWith('.json5'))
|
|
147
|
+
return 'json5';
|
|
148
|
+
if (filePath.endsWith('.yaml') || filePath.endsWith('.yml'))
|
|
149
|
+
return 'yaml';
|
|
150
|
+
if (filePath.endsWith('.ts'))
|
|
151
|
+
return 'ts';
|
|
152
|
+
if (filePath.endsWith('.js'))
|
|
153
|
+
return 'js';
|
|
154
|
+
if (filePath.endsWith('.json'))
|
|
155
|
+
return 'json';
|
|
156
|
+
return defaultFormat || 'json';
|
|
157
|
+
}
|
|
132
158
|
|
|
133
159
|
exports.getOutputPath = getOutputPath;
|
|
160
|
+
exports.inferFormatFromPath = inferFormatFromPath;
|
|
134
161
|
exports.loadRawJson5Content = loadRawJson5Content;
|
|
135
162
|
exports.loadTranslationFile = loadTranslationFile;
|
|
136
163
|
exports.serializeTranslationFile = serializeTranslationFile;
|
package/dist/esm/cli.js
CHANGED
|
@@ -13,6 +13,7 @@ import 'node:path';
|
|
|
13
13
|
import 'node:fs/promises';
|
|
14
14
|
import 'jiti';
|
|
15
15
|
import '@croct/json5-parser';
|
|
16
|
+
import 'yaml';
|
|
16
17
|
import { runTypesGenerator } from './types-generator.js';
|
|
17
18
|
import { runSyncer } from './syncer.js';
|
|
18
19
|
import { runMigrator } from './migrator.js';
|
|
@@ -26,7 +27,7 @@ const program = new Command();
|
|
|
26
27
|
program
|
|
27
28
|
.name('i18next-cli')
|
|
28
29
|
.description('A unified, high-performance i18next CLI.')
|
|
29
|
-
.version('1.
|
|
30
|
+
.version('1.42.1'); // This string is replaced with the actual version at build time by rollup
|
|
30
31
|
// new: global config override option
|
|
31
32
|
program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
|
|
32
33
|
program
|
|
@@ -8,7 +8,7 @@ import { getTranslations } from './translation-manager.js';
|
|
|
8
8
|
import { validateExtractorConfig, ExtractorError } from '../../utils/validation.js';
|
|
9
9
|
import { extractKeysFromComments } from '../parsers/comment-parser.js';
|
|
10
10
|
import { ConsoleLogger } from '../../utils/logger.js';
|
|
11
|
-
import { loadRawJson5Content, serializeTranslationFile } from '../../utils/file-utils.js';
|
|
11
|
+
import { inferFormatFromPath, loadRawJson5Content, serializeTranslationFile } from '../../utils/file-utils.js';
|
|
12
12
|
import { shouldShowFunnel, recordFunnelShown } from '../../utils/funnel-msg-tracker.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -61,7 +61,7 @@ async function runExtractor(config, options = {}) {
|
|
|
61
61
|
anyFileUpdated = true;
|
|
62
62
|
if (!options.isDryRun) {
|
|
63
63
|
// prefer explicit outputFormat; otherwise infer from file extension per-file
|
|
64
|
-
const effectiveFormat = config.extract.outputFormat ?? (result.path
|
|
64
|
+
const effectiveFormat = config.extract.outputFormat ?? inferFormatFromPath(result.path);
|
|
65
65
|
const rawContent = effectiveFormat === 'json5'
|
|
66
66
|
? (await loadRawJson5Content(result.path)) ?? undefined
|
|
67
67
|
: undefined;
|
|
@@ -22,6 +22,18 @@ const HEURISTIC_PATTERNS = [
|
|
|
22
22
|
'src/assets/locales/en/*.json5',
|
|
23
23
|
'app/i18n/locales/en/*.json5',
|
|
24
24
|
'src/i18n/locales/en/*.json5',
|
|
25
|
+
'public/locales/en/*.yaml',
|
|
26
|
+
'locales/en/*.yaml',
|
|
27
|
+
'src/locales/en/*.yaml',
|
|
28
|
+
'src/assets/locales/en/*.yaml',
|
|
29
|
+
'app/i18n/locales/en/*.yaml',
|
|
30
|
+
'src/i18n/locales/en/*.yaml',
|
|
31
|
+
'public/locales/en/*.yml',
|
|
32
|
+
'locales/en/*.yml',
|
|
33
|
+
'src/locales/en/*.yml',
|
|
34
|
+
'src/assets/locales/en/*.yml',
|
|
35
|
+
'app/i18n/locales/en/*.yml',
|
|
36
|
+
'src/i18n/locales/en/*.yml',
|
|
25
37
|
'public/locales/en-*/*.json',
|
|
26
38
|
'locales/en-*/*.json',
|
|
27
39
|
'src/locales/en-*/*.json',
|
|
@@ -58,6 +70,9 @@ async function detectConfig() {
|
|
|
58
70
|
else if (extension === '.json5') {
|
|
59
71
|
outputFormat = 'json5';
|
|
60
72
|
}
|
|
73
|
+
else if (extension === '.yaml' || extension === '.yml') {
|
|
74
|
+
outputFormat = 'yaml';
|
|
75
|
+
}
|
|
61
76
|
try {
|
|
62
77
|
const allDirs = await readdir(basePath);
|
|
63
78
|
let locales = allDirs.filter(dir => /^(dev|[a-z]{2}(-[A-Z]{2})?)$/.test(dir));
|
package/dist/esm/linter.js
CHANGED
|
@@ -92,25 +92,37 @@ function lintInterpolationParams(ast, code, config) {
|
|
|
92
92
|
let paramKeys = [];
|
|
93
93
|
if (arg1?.type === 'ObjectExpression') {
|
|
94
94
|
paramKeys = arg1.properties
|
|
95
|
-
.filter((p) => p.type === 'KeyValueProperty')
|
|
96
95
|
.map((p) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
// Standard key:value property like { name: "value" }
|
|
97
|
+
if (p.type === 'KeyValueProperty' && p.key) {
|
|
98
|
+
if (p.key.type === 'Identifier')
|
|
99
|
+
return p.key.value;
|
|
100
|
+
if (p.key.type === 'StringLiteral')
|
|
101
|
+
return p.key.value;
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
// Shorthand property like { hours, minutes }
|
|
105
|
+
if (p.type === 'ShorthandProperty' || p.type === 'Identifier') {
|
|
106
|
+
return p.value ?? p.name;
|
|
107
|
+
}
|
|
101
108
|
return undefined;
|
|
102
109
|
})
|
|
103
110
|
.filter((k) => typeof k === 'string');
|
|
104
111
|
}
|
|
105
112
|
if (!Array.isArray(paramKeys))
|
|
106
113
|
paramKeys = [];
|
|
114
|
+
// Use text search for accurate line numbers (SWC spans use global byte offsets, not per-file)
|
|
115
|
+
const searchText = arg0.raw ?? `"${arg0.value}"`;
|
|
116
|
+
const position = code.indexOf(searchText);
|
|
117
|
+
const issueLineNumber = position > -1 ? getLineNumber(position) : 1;
|
|
107
118
|
// Only check for unused parameters if there is at least one interpolation key in the string
|
|
108
119
|
if (keys.length > 0) {
|
|
109
120
|
for (const k of keys) {
|
|
110
121
|
if (!paramKeys.includes(k)) {
|
|
111
122
|
issues.push({
|
|
112
123
|
text: `Interpolation parameter "${k}" was not provided`,
|
|
113
|
-
line:
|
|
124
|
+
line: issueLineNumber,
|
|
125
|
+
type: 'interpolation',
|
|
114
126
|
});
|
|
115
127
|
}
|
|
116
128
|
}
|
|
@@ -118,7 +130,8 @@ function lintInterpolationParams(ast, code, config) {
|
|
|
118
130
|
if (!keys.includes(pk)) {
|
|
119
131
|
issues.push({
|
|
120
132
|
text: `Parameter "${pk}" is not used in translation string`,
|
|
121
|
-
line:
|
|
133
|
+
line: issueLineNumber,
|
|
134
|
+
type: 'interpolation',
|
|
122
135
|
});
|
|
123
136
|
}
|
|
124
137
|
}
|
|
@@ -300,11 +313,12 @@ async function runLinterCli(config, options = {}) {
|
|
|
300
313
|
internalLogger.info(chalk.yellow(`\n${file}`));
|
|
301
314
|
else
|
|
302
315
|
console.log(chalk.yellow(`\n${file}`));
|
|
303
|
-
issues.forEach(({ text, line }) => {
|
|
316
|
+
issues.forEach(({ text, line, type }) => {
|
|
317
|
+
const label = type === 'interpolation' ? 'Interpolation issue' : 'Found hardcoded string';
|
|
304
318
|
if (typeof internalLogger.info === 'function')
|
|
305
|
-
internalLogger.info(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')}
|
|
319
|
+
internalLogger.info(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')} ${label}: "${text}"`);
|
|
306
320
|
else
|
|
307
|
-
console.log(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')}
|
|
321
|
+
console.log(` ${chalk.gray(`${line}:`)} ${chalk.red('Error:')} ${label}: "${text}"`);
|
|
308
322
|
});
|
|
309
323
|
}
|
|
310
324
|
process.exit(1);
|
package/dist/esm/syncer.js
CHANGED
|
@@ -5,7 +5,7 @@ import { basename, resolve, dirname } from 'node:path';
|
|
|
5
5
|
import { createSpinnerLike } from './utils/wrap-ora.js';
|
|
6
6
|
import { ConsoleLogger } from './utils/logger.js';
|
|
7
7
|
import { resolveDefaultValue } from './utils/default-value.js';
|
|
8
|
-
import { getOutputPath, loadTranslationFile, loadRawJson5Content, serializeTranslationFile } from './utils/file-utils.js';
|
|
8
|
+
import { getOutputPath, loadTranslationFile, inferFormatFromPath, loadRawJson5Content, serializeTranslationFile } from './utils/file-utils.js';
|
|
9
9
|
import { shouldShowFunnel, recordFunnelShown } from './utils/funnel-msg-tracker.js';
|
|
10
10
|
import { getNestedKeys, getNestedValue, setNestedValue } from './utils/nested-object.js';
|
|
11
11
|
|
|
@@ -95,7 +95,7 @@ async function runSyncer(config, options = {}) {
|
|
|
95
95
|
const newContent = JSON.stringify(newSecondaryTranslations);
|
|
96
96
|
if (newContent !== oldContent) {
|
|
97
97
|
wasAnythingSynced = true;
|
|
98
|
-
const perFileFormat = config.extract.outputFormat ?? (fullSecondaryPath
|
|
98
|
+
const perFileFormat = config.extract.outputFormat ?? inferFormatFromPath(fullSecondaryPath, outputFormat);
|
|
99
99
|
const raw = perFileFormat === 'json5' ? (await loadRawJson5Content(fullSecondaryPath)) ?? undefined : undefined;
|
|
100
100
|
const serializedContent = serializeTranslationFile(newSecondaryTranslations, perFileFormat, indentation, raw);
|
|
101
101
|
await mkdir(dirname(fullSecondaryPath), { recursive: true });
|
|
@@ -3,6 +3,7 @@ import { resolve, normalize, extname } from 'node:path';
|
|
|
3
3
|
import { createJiti } from 'jiti';
|
|
4
4
|
import { getTsConfigAliases } from '../config.js';
|
|
5
5
|
import { JsonParser, JsonObjectNode } from '@croct/json5-parser';
|
|
6
|
+
import yaml from 'yaml';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Resolve an output template (string or function) into an actual path string.
|
|
@@ -63,6 +64,10 @@ async function loadTranslationFile(filePath) {
|
|
|
63
64
|
const node = JsonParser.parse(content, JsonObjectNode);
|
|
64
65
|
return node.toJSON();
|
|
65
66
|
}
|
|
67
|
+
else if (ext === '.yaml' || ext === '.yml') {
|
|
68
|
+
const content = await readFile(fullPath, 'utf-8');
|
|
69
|
+
return yaml.parse(content);
|
|
70
|
+
}
|
|
66
71
|
else if (ext === '.json') {
|
|
67
72
|
const content = await readFile(fullPath, 'utf-8');
|
|
68
73
|
return JSON.parse(content);
|
|
@@ -114,6 +119,8 @@ function serializeTranslationFile(data, format = 'json', indentation = 2, rawCon
|
|
|
114
119
|
const node = JsonParser.parse(jsonString, JsonObjectNode);
|
|
115
120
|
return node.toString({ object: { indentationSize: Number(indentation) ?? 2 } });
|
|
116
121
|
}
|
|
122
|
+
case 'yaml':
|
|
123
|
+
return yaml.stringify(data, { indent: Number(indentation) || 2, lineWidth: 0 });
|
|
117
124
|
case 'js':
|
|
118
125
|
case 'js-esm':
|
|
119
126
|
return `export default ${jsonString};\n`;
|
|
@@ -127,5 +134,24 @@ function serializeTranslationFile(data, format = 'json', indentation = 2, rawCon
|
|
|
127
134
|
return `${jsonString}\n`;
|
|
128
135
|
}
|
|
129
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Infers the output format from the file path extension.
|
|
139
|
+
* @param filePath - The path to the translation file
|
|
140
|
+
* @param defaultFormat - The default format to return if no match (default: 'json')
|
|
141
|
+
* @returns The inferred output format
|
|
142
|
+
*/
|
|
143
|
+
function inferFormatFromPath(filePath, defaultFormat = 'json') {
|
|
144
|
+
if (filePath.endsWith('.json5'))
|
|
145
|
+
return 'json5';
|
|
146
|
+
if (filePath.endsWith('.yaml') || filePath.endsWith('.yml'))
|
|
147
|
+
return 'yaml';
|
|
148
|
+
if (filePath.endsWith('.ts'))
|
|
149
|
+
return 'ts';
|
|
150
|
+
if (filePath.endsWith('.js'))
|
|
151
|
+
return 'js';
|
|
152
|
+
if (filePath.endsWith('.json'))
|
|
153
|
+
return 'json';
|
|
154
|
+
return defaultFormat || 'json';
|
|
155
|
+
}
|
|
130
156
|
|
|
131
|
-
export { getOutputPath, loadRawJson5Content, loadTranslationFile, serializeTranslationFile };
|
|
157
|
+
export { getOutputPath, inferFormatFromPath, loadRawJson5Content, loadTranslationFile, serializeTranslationFile };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18next-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.42.1",
|
|
4
4
|
"description": "A unified, high-performance i18next CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@rollup/plugin-terser": "0.4.4",
|
|
57
57
|
"@types/inquirer": "9.0.9",
|
|
58
58
|
"@types/node": "25.2.0",
|
|
59
|
-
"@types/react": "19.2.
|
|
59
|
+
"@types/react": "19.2.11",
|
|
60
60
|
"@vitest/coverage-v8": "4.0.18",
|
|
61
61
|
"eslint": "9.39.2",
|
|
62
62
|
"eslint-plugin-import": "2.32.0",
|
|
@@ -71,17 +71,18 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@croct/json5-parser": "0.2.2",
|
|
73
73
|
"@swc/core": "1.15.11",
|
|
74
|
+
"yaml": "2.8.2",
|
|
74
75
|
"chalk": "5.6.2",
|
|
75
76
|
"chokidar": "5.0.0",
|
|
76
77
|
"commander": "14.0.3",
|
|
77
78
|
"execa": "9.6.1",
|
|
78
|
-
"glob": "13.0.
|
|
79
|
+
"glob": "13.0.1",
|
|
79
80
|
"i18next-resources-for-ts": "2.0.0",
|
|
80
81
|
"inquirer": "13.2.2",
|
|
81
82
|
"jiti": "2.6.1",
|
|
82
83
|
"jsonc-parser": "3.3.1",
|
|
83
|
-
"minimatch": "10.1.
|
|
84
|
-
"ora": "9.
|
|
84
|
+
"minimatch": "10.1.2",
|
|
85
|
+
"ora": "9.3.0",
|
|
85
86
|
"react": "^19.2.4",
|
|
86
87
|
"react-i18next": "^16.5.4",
|
|
87
88
|
"swc-walk": "1.0.1"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heuristic-config.d.ts","sourceRoot":"","sources":["../src/heuristic-config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"heuristic-config.d.ts","sourceRoot":"","sources":["../src/heuristic-config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AA+CnD;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAK,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,CA6DnF"}
|
package/types/linter.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ interface HardcodedString {
|
|
|
77
77
|
text: string;
|
|
78
78
|
/** Line number where the string or error was found */
|
|
79
79
|
line: number;
|
|
80
|
+
/** The type of issue: 'hardcoded' for hardcoded strings, 'interpolation' for interpolation parameter errors */
|
|
81
|
+
type?: 'hardcoded' | 'interpolation';
|
|
80
82
|
}
|
|
81
83
|
export {};
|
|
82
84
|
//# sourceMappingURL=linter.d.ts.map
|
package/types/linter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAwI3D,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE;QAAC;YACT,OAAO,EAAE,MAAM,CAAC;SACjB;KAAC,CAAC;IACH,IAAI,EAAE;QAAC;YACL,OAAO,EAAE,OAAO,CAAC;YACjB,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;SAC1C;KAAC,CAAC;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;CACvB,CAAA;AAED,eAAO,MAAM,uBAAuB,UAET,CAAA;AAC3B,eAAO,MAAM,6BAA6B,UAAgN,CAAA;AAK1P,qBAAa,MAAO,SAAQ,YAAY,CAAC,cAAc,CAAC;IACtD,OAAO,CAAC,MAAM,CAAsB;gBAEvB,MAAM,EAAE,oBAAoB;IAKzC,SAAS,CAAE,KAAK,EAAE,OAAO;IAanB,GAAG;;;;;;;CA6FV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,SAAS,CAAE,MAAM,EAAE,oBAAoB;;;;;;GAE5D;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,iBAkCnD;AAED;;GAEG;AACH,UAAU,eAAe;IACvB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC;CACtC"}
|
package/types/types.d.ts
CHANGED
|
@@ -104,12 +104,13 @@ export interface I18nextToolkitConfig {
|
|
|
104
104
|
* The format of the output translation files.
|
|
105
105
|
* 'json': Standard JSON file (default)
|
|
106
106
|
* 'json5': JSON5 file
|
|
107
|
+
* 'yaml': YAML file
|
|
107
108
|
* 'js': JavaScript file with ES Module syntax (export default)
|
|
108
109
|
* 'js-esm': JavaScript file with ES Module syntax (export default)
|
|
109
110
|
* 'js-cjs': JavaScript file with CommonJS syntax (module.exports)
|
|
110
111
|
* 'ts': TypeScript file with ES Module syntax and `as const` for type safety
|
|
111
112
|
*/
|
|
112
|
-
outputFormat?: 'json' | 'json5' | 'js' | 'ts' | 'js-esm' | 'js-cjs' | 'ts';
|
|
113
|
+
outputFormat?: 'json' | 'json5' | 'yaml' | 'js' | 'ts' | 'js-esm' | 'js-cjs' | 'ts';
|
|
113
114
|
/**
|
|
114
115
|
* If true, all namespaces will be merged into a single file per language.
|
|
115
116
|
* The `output` path should not contain the `{{namespace}}` placeholder.
|
package/types/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAEnE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,2DAA2D;IAC3D,OAAO,EAAE;QACP,oEAAoE;QACpE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAEzB,4DAA4D;QAC5D,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAE3B,mGAAmG;QACnG,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;QAEpE;;;WAGG;QACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAE3B,gGAAgG;QAChG,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAE5B,uEAAuE;QACvE,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;QAErC,8EAA8E;QAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;QAEpC,oDAAoD;QACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAE1B,mDAAmD;QACnD,eAAe,CAAC,EAAE,MAAM,CAAC;QAEzB,+EAA+E;QAC/E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAErB,4EAA4E;QAC5E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAE3B;;;;;WAKG;QACH,mBAAmB,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG;YACnC,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC,CAAC;QAEH,kFAAkF;QAClF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAE7B,kGAAkG;QAClG,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAEvB;;;;;WAKG;QACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QAE9B;;;;;WAKG;QACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QAExB,8FAA8F;QAC9F,0BAA0B,CAAC,EAAE,MAAM,EAAE,CAAC;QAEtC,wFAAwF;QACxF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;QAE5B;;;;;WAKG;QACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAElC,2HAA2H;QAC3H,IAAI,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,MAAM,CAAC,CAAC;QAEhE,yDAAyD;QACzD,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAE9B,2EAA2E;QAC3E,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;QAEtG,4EAA4E;QAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;QAEzB,0DAA0D;QAC1D,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QAE9B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,4 +60,11 @@ export declare function loadRawJson5Content(filePath: string): Promise<string |
|
|
|
60
60
|
* For JSON5, preserves comments and formatting using JsonObjectNode.update().
|
|
61
61
|
*/
|
|
62
62
|
export declare function serializeTranslationFile(data: Record<string, any>, format?: I18nextToolkitConfig['extract']['outputFormat'], indentation?: number | string, rawContent?: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Infers the output format from the file path extension.
|
|
65
|
+
* @param filePath - The path to the translation file
|
|
66
|
+
* @param defaultFormat - The default format to return if no match (default: 'json')
|
|
67
|
+
* @returns The inferred output format
|
|
68
|
+
*/
|
|
69
|
+
export declare function inferFormatFromPath(filePath: string, defaultFormat?: I18nextToolkitConfig['extract']['outputFormat']): NonNullable<I18nextToolkitConfig['extract']['outputFormat']>;
|
|
63
70
|
//# sourceMappingURL=file-utils.d.ts.map
|
|
@@ -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;
|
|
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"}
|