i18next-cli 1.34.0 → 1.34.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 +1 -1
- package/dist/cjs/cli.js +271 -1
- package/dist/cjs/config.js +211 -1
- package/dist/cjs/extractor/core/ast-visitors.js +364 -1
- package/dist/cjs/extractor/core/extractor.js +245 -1
- package/dist/cjs/extractor/core/key-finder.js +132 -1
- package/dist/cjs/extractor/core/translation-manager.js +745 -1
- package/dist/cjs/extractor/parsers/ast-utils.js +85 -1
- package/dist/cjs/extractor/parsers/call-expression-handler.js +941 -1
- package/dist/cjs/extractor/parsers/comment-parser.js +375 -1
- package/dist/cjs/extractor/parsers/expression-resolver.js +362 -1
- package/dist/cjs/extractor/parsers/jsx-handler.js +492 -1
- package/dist/cjs/extractor/parsers/jsx-parser.js +355 -1
- package/dist/cjs/extractor/parsers/scope-manager.js +408 -1
- package/dist/cjs/extractor/plugin-manager.js +106 -1
- package/dist/cjs/heuristic-config.js +99 -1
- package/dist/cjs/index.js +28 -1
- package/dist/cjs/init.js +174 -1
- package/dist/cjs/linter.js +431 -1
- package/dist/cjs/locize.js +269 -1
- package/dist/cjs/migrator.js +196 -1
- package/dist/cjs/rename-key.js +354 -1
- package/dist/cjs/status.js +336 -1
- package/dist/cjs/syncer.js +120 -1
- package/dist/cjs/types-generator.js +165 -1
- package/dist/cjs/utils/default-value.js +43 -1
- package/dist/cjs/utils/file-utils.js +136 -1
- package/dist/cjs/utils/funnel-msg-tracker.js +75 -1
- package/dist/cjs/utils/logger.js +36 -1
- package/dist/cjs/utils/nested-object.js +124 -1
- package/dist/cjs/utils/validation.js +71 -1
- package/dist/esm/cli.js +269 -1
- package/dist/esm/config.js +206 -1
- package/dist/esm/extractor/core/ast-visitors.js +362 -1
- package/dist/esm/extractor/core/extractor.js +241 -1
- package/dist/esm/extractor/core/key-finder.js +130 -1
- package/dist/esm/extractor/core/translation-manager.js +743 -1
- package/dist/esm/extractor/parsers/ast-utils.js +80 -1
- package/dist/esm/extractor/parsers/call-expression-handler.js +939 -1
- package/dist/esm/extractor/parsers/comment-parser.js +373 -1
- package/dist/esm/extractor/parsers/expression-resolver.js +360 -1
- package/dist/esm/extractor/parsers/jsx-handler.js +490 -1
- package/dist/esm/extractor/parsers/jsx-parser.js +334 -1
- package/dist/esm/extractor/parsers/scope-manager.js +406 -1
- package/dist/esm/extractor/plugin-manager.js +103 -1
- package/dist/esm/heuristic-config.js +97 -1
- package/dist/esm/index.js +11 -1
- package/dist/esm/init.js +172 -1
- package/dist/esm/linter.js +425 -1
- package/dist/esm/locize.js +265 -1
- package/dist/esm/migrator.js +194 -1
- package/dist/esm/rename-key.js +352 -1
- package/dist/esm/status.js +334 -1
- package/dist/esm/syncer.js +118 -1
- package/dist/esm/types-generator.js +163 -1
- package/dist/esm/utils/default-value.js +41 -1
- package/dist/esm/utils/file-utils.js +131 -1
- package/dist/esm/utils/funnel-msg-tracker.js +72 -1
- package/dist/esm/utils/logger.js +34 -1
- package/dist/esm/utils/nested-object.js +120 -1
- package/dist/esm/utils/validation.js +68 -1
- package/package.json +2 -2
- package/types/locize.d.ts.map +1 -1
|
@@ -1 +1,130 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { processFile } from './extractor.js';
|
|
3
|
+
import { ConsoleLogger } from '../../utils/logger.js';
|
|
4
|
+
import { createPluginContext, initializePlugins } from '../plugin-manager.js';
|
|
5
|
+
import { ASTVisitors } from './ast-visitors.js';
|
|
6
|
+
import { ExpressionResolver } from '../parsers/expression-resolver.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Main function for finding translation keys across all source files in a project.
|
|
10
|
+
*
|
|
11
|
+
* This function orchestrates the key extraction process:
|
|
12
|
+
* 1. Processes source files based on input patterns
|
|
13
|
+
* 2. Initializes and manages plugins
|
|
14
|
+
* 3. Processes each file through AST parsing and key extraction
|
|
15
|
+
* 4. Runs plugin lifecycle hooks
|
|
16
|
+
* 5. Returns a deduplicated map of all found keys
|
|
17
|
+
*
|
|
18
|
+
* @param config - The i18next toolkit configuration object
|
|
19
|
+
* @param logger - Logger instance for output (defaults to ConsoleLogger)
|
|
20
|
+
* @returns Promise resolving to a Map of unique translation keys with metadata
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const config = {
|
|
25
|
+
* extract: {
|
|
26
|
+
* input: ['src/**\/*.{ts,tsx}'],
|
|
27
|
+
* functions: ['t', '*.t'],
|
|
28
|
+
* transComponents: ['Trans']
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* const keys = await findKeys(config)
|
|
33
|
+
* console.log(`Found ${keys.size} unique translation keys`)
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
async function findKeys(config, logger = new ConsoleLogger()) {
|
|
37
|
+
const { plugins: pluginsOrUndefined, ...otherConfig } = config;
|
|
38
|
+
const plugins = pluginsOrUndefined || [];
|
|
39
|
+
const sourceFiles = await processSourceFiles(config);
|
|
40
|
+
const allKeys = new Map();
|
|
41
|
+
// 1. Create the base context with config and logger.
|
|
42
|
+
const pluginContext = createPluginContext(allKeys, plugins, otherConfig, logger);
|
|
43
|
+
// 2. Create hooks for plugins to hook into AST
|
|
44
|
+
const hooks = {
|
|
45
|
+
onBeforeVisitNode: (node) => {
|
|
46
|
+
for (const plugin of plugins) {
|
|
47
|
+
try {
|
|
48
|
+
plugin.onVisitNode?.(node, pluginContext);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
logger.warn(`Plugin ${plugin.name} onVisitNode failed:`, err);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
resolvePossibleKeyStringValues: (expression) => {
|
|
56
|
+
return plugins.flatMap(plugin => {
|
|
57
|
+
try {
|
|
58
|
+
return plugin.extractKeysFromExpression?.(expression, config, logger) ?? [];
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
logger.warn(`Plugin ${plugin.name} extractKeysFromExpression failed:`, err);
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
resolvePossibleContextStringValues: (expression) => {
|
|
67
|
+
return plugins.flatMap(plugin => {
|
|
68
|
+
try {
|
|
69
|
+
return plugin.extractContextFromExpression?.(expression, config, logger) ?? [];
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
logger.warn(`Plugin ${plugin.name} extractContextFromExpression failed:`, err);
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
// 3. Create the visitor instance, passing it the context.
|
|
79
|
+
// Use a shared ExpressionResolver so captured enums/objects in one file are available when resolving MemberExpressions
|
|
80
|
+
const sharedExpressionResolver = new ExpressionResolver(hooks);
|
|
81
|
+
const astVisitors = new ASTVisitors(otherConfig, pluginContext, logger, hooks, sharedExpressionResolver);
|
|
82
|
+
// 4. "Wire up" the visitor's scope method to the context.
|
|
83
|
+
// This avoids a circular dependency while giving plugins access to the scope.
|
|
84
|
+
pluginContext.getVarFromScope = astVisitors.getVarFromScope.bind(astVisitors);
|
|
85
|
+
// 5. Initialize plugins
|
|
86
|
+
await initializePlugins(plugins);
|
|
87
|
+
// 6. Process each file
|
|
88
|
+
for (const file of sourceFiles) {
|
|
89
|
+
await processFile(file, plugins, astVisitors, pluginContext, otherConfig, logger);
|
|
90
|
+
}
|
|
91
|
+
// 7. Run onEnd hooks
|
|
92
|
+
for (const plugin of plugins) {
|
|
93
|
+
await plugin.onEnd?.(allKeys);
|
|
94
|
+
}
|
|
95
|
+
// Normalization: mark already-expanded plural keys
|
|
96
|
+
const pluralSeparator = otherConfig.extract?.pluralSeparator ?? '_';
|
|
97
|
+
const categories = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|
98
|
+
for (const ek of allKeys.values()) {
|
|
99
|
+
const parts = String(ek.key).split(pluralSeparator);
|
|
100
|
+
const last = parts[parts.length - 1];
|
|
101
|
+
const isOrdinal = parts.length >= 3 && parts[parts.length - 2] === 'ordinal';
|
|
102
|
+
if (categories.includes(last) || (isOrdinal && categories.includes(last))) {
|
|
103
|
+
ek.isExpandedPlural = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { allKeys, objectKeys: astVisitors.objectKeys };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Processes source files using glob patterns from configuration.
|
|
110
|
+
* Excludes node_modules by default and resolves relative to current working directory.
|
|
111
|
+
*
|
|
112
|
+
* @param config - The i18next toolkit configuration object
|
|
113
|
+
* @returns Promise resolving to array of file paths to process
|
|
114
|
+
*
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
117
|
+
async function processSourceFiles(config) {
|
|
118
|
+
const defaultIgnore = ['node_modules/**'];
|
|
119
|
+
// Normalize the user's ignore option into an array
|
|
120
|
+
const userIgnore = Array.isArray(config.extract.ignore)
|
|
121
|
+
? config.extract.ignore
|
|
122
|
+
: config.extract.ignore ? [config.extract.ignore] : [];
|
|
123
|
+
return await glob(config.extract.input, {
|
|
124
|
+
// Combine default ignore patterns with user-configured ones
|
|
125
|
+
ignore: [...defaultIgnore, ...userIgnore],
|
|
126
|
+
cwd: process.cwd(),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export { findKeys };
|