i18next-cli 1.42.9 → 1.42.11

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/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.42.9'); // This string is replaced with the actual version at build time by rollup
31
+ .version('1.42.11'); // 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
@@ -114,7 +114,8 @@ async function loadConfig(configPath, logger$1 = new logger.ConsoleLogger()) {
114
114
  catch (error) {
115
115
  logger$1.error(`Error loading configuration from ${configPathFound}`);
116
116
  logger$1.error(error);
117
- return null;
117
+ // Returning null causes ensureConfig to prompt "would you like to create one?"
118
+ throw new Error(`Error loading configuration from ${configPathFound}: ${error?.message || error?.name}`);
118
119
  }
119
120
  }
120
121
  /**
@@ -181,6 +181,12 @@ class ASTVisitors {
181
181
  const extractStringLiteralValue = (node) => {
182
182
  if (!node)
183
183
  return undefined;
184
+ // Handle: typeof SomeConst → TsTypeQuery { exprName: { value: 'SomeConst' } }
185
+ if (node?.type === 'TsTypeQuery') {
186
+ const name = node.exprName?.value ?? node.exprName?.name;
187
+ if (name)
188
+ return this.scopeManager.resolveSimpleStringIdentifier(name);
189
+ }
184
190
  // shapes: TsLiteralType -> { literal: { type: 'StringLiteral', value: 'x' } }
185
191
  if (node.type === 'TsLiteralType' && node.literal)
186
192
  return node.literal.value ?? node.literal.raw;
@@ -231,8 +237,21 @@ class ASTVisitors {
231
237
  }
232
238
  }
233
239
  const ns = extractStringLiteralValue(tp);
234
- if (ns) {
235
- this.scopeManager.setVarInScope(paramKey, { defaultNs: ns });
240
+ // Extract the second type parameter for KPrefix
241
+ // We need to find the second element from the same type parameter list
242
+ const typeParams = typeAnn.typeParameters?.params ??
243
+ typeAnn.typeArguments?.params ??
244
+ typeAnn.typeParams?.params ??
245
+ undefined;
246
+ let kpFromType;
247
+ if (typeParams && typeParams.length >= 2) {
248
+ kpFromType = extractStringLiteralValue(typeParams[1]);
249
+ }
250
+ if (ns || kpFromType) {
251
+ this.scopeManager.setVarInScope(paramKey, {
252
+ defaultNs: ns,
253
+ keyPrefix: kpFromType // honour TFunction<Ns, KPrefix>
254
+ });
236
255
  }
237
256
  }
238
257
  }
@@ -194,6 +194,7 @@ async function processFile(file, plugins, astVisitors, pluginContext, config, lo
194
194
  // "Wire up" the visitor's scope method to the context.
195
195
  // This avoids a circular dependency while giving plugins access to the scope.
196
196
  pluginContext.getVarFromScope = astVisitors.getVarFromScope.bind(astVisitors);
197
+ pluginContext.setVarInScope = astVisitors.scopeManager.setVarInScope.bind(astVisitors.scopeManager);
197
198
  // Pass BOTH file and code
198
199
  astVisitors.setCurrentFile(file, code);
199
200
  // 3. FIRST: Visit the AST to build scope information
@@ -226,15 +226,29 @@ class ScopeManager {
226
226
  if (nsNode?.type === 'StringLiteral') {
227
227
  defaultNs = nsNode.value;
228
228
  }
229
- else if (nsNode?.type === 'ArrayExpression' && nsNode.elements[0]?.expression?.type === 'StringLiteral') {
230
- defaultNs = nsNode.elements[0].expression.value;
229
+ else if (nsNode?.type === 'Identifier') {
230
+ // ← FIX A: resolve const I18N_NS = 'users'
231
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
232
+ }
233
+ else if (nsNode?.type === 'ArrayExpression') {
234
+ const first = nsNode.elements[0]?.expression;
235
+ if (first?.type === 'StringLiteral')
236
+ defaultNs = first.value;
237
+ else if (first?.type === 'Identifier')
238
+ defaultNs = this.resolveSimpleStringIdentifier(first.value);
231
239
  }
232
240
  }
233
241
  kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
234
242
  }
235
243
  if (kpArg?.type === 'ObjectExpression') {
236
244
  const kp = astUtils.getObjectPropValue(kpArg, 'keyPrefix');
237
- keyPrefix = typeof kp === 'string' ? kp : undefined;
245
+ if (typeof kp === 'string') {
246
+ keyPrefix = kp;
247
+ }
248
+ else if (kp && typeof kp === 'object' && kp.type === 'Identifier') {
249
+ // ← FIX B: resolve { keyPrefix: I18N_PREFIX } where the value is an Identifier
250
+ keyPrefix = this.resolveSimpleStringIdentifier(kp.value);
251
+ }
238
252
  }
239
253
  else if (kpArg?.type === 'StringLiteral') {
240
254
  keyPrefix = kpArg.value;
@@ -290,17 +304,32 @@ class ScopeManager {
290
304
  else {
291
305
  if (nsArgIndex !== -1) {
292
306
  const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
293
- if (nsNode?.type === 'StringLiteral')
307
+ if (nsNode?.type === 'StringLiteral') {
294
308
  defaultNs = nsNode.value;
295
- else if (nsNode?.type === 'ArrayExpression' && nsNode.elements[0]?.expression?.type === 'StringLiteral') {
296
- defaultNs = nsNode.elements[0].expression.value;
309
+ }
310
+ else if (nsNode?.type === 'Identifier') {
311
+ // ← FIX A: resolve const I18N_NS = 'users'
312
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
313
+ }
314
+ else if (nsNode?.type === 'ArrayExpression') {
315
+ const first = nsNode.elements[0]?.expression;
316
+ if (first?.type === 'StringLiteral')
317
+ defaultNs = first.value;
318
+ else if (first?.type === 'Identifier')
319
+ defaultNs = this.resolveSimpleStringIdentifier(first.value);
297
320
  }
298
321
  }
299
322
  kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
300
323
  }
301
324
  if (kpArg?.type === 'ObjectExpression') {
302
325
  const kp = astUtils.getObjectPropValue(kpArg, 'keyPrefix');
303
- keyPrefix = typeof kp === 'string' ? kp : undefined;
326
+ if (typeof kp === 'string') {
327
+ keyPrefix = kp;
328
+ }
329
+ else if (kp && typeof kp === 'object' && kp.type === 'Identifier') {
330
+ // ← FIX B: resolve { keyPrefix: I18N_PREFIX } where the value is an Identifier
331
+ keyPrefix = this.resolveSimpleStringIdentifier(kp.value);
332
+ }
304
333
  }
305
334
  else if (kpArg?.type === 'StringLiteral') {
306
335
  keyPrefix = kpArg.value;
@@ -99,6 +99,8 @@ function createPluginContext(allKeys, plugins, config, logger) {
99
99
  logger,
100
100
  // This will be attached later, so we provide a placeholder
101
101
  getVarFromScope: () => undefined,
102
+ // This will be attached later, so we provide a placeholder
103
+ setVarInScope: (_name, _info) => undefined,
102
104
  };
103
105
  }
104
106
 
@@ -9,6 +9,67 @@ var node_util = require('node:util');
9
9
  var logger = require('./utils/logger.js');
10
10
  var wrapOra = require('./utils/wrap-ora.js');
11
11
 
12
+ /**
13
+ * Loads all translation values from the primary locale's JSON files and returns
14
+ * a flat Map of key -> translated string. Used by the interpolation linter so it
15
+ * can resolve a lookup key (e.g. "ABC") to its actual value ("hello {{name}}")
16
+ * and check interpolation parameters against the real string, not the key.
17
+ */
18
+ async function loadPrimaryTranslationValues(config) {
19
+ const result = new Map();
20
+ const output = config.extract?.output;
21
+ if (!output || typeof output !== 'string')
22
+ return result;
23
+ const primaryLang = config.extract?.primaryLanguage ?? config.locales?.[0] ?? 'en';
24
+ // Candidate paths: substitute language + try common namespace names (including no namespace).
25
+ // This covers patterns like:
26
+ // locales/{{language}}.json -> no namespace token
27
+ // locales/{{language}}/{{namespace}}.json -> substitute 'translation' (i18next default)
28
+ // Deliberately uses readFile directly (not glob) so it works correctly in test
29
+ // environments that mock fs/promises via memfs.
30
+ const candidatePaths = [];
31
+ if (!output.includes('{{namespace}}')) {
32
+ candidatePaths.push(output.replace(/\{\{language\}\}/g, primaryLang));
33
+ }
34
+ else {
35
+ for (const ns of ['translation', 'common', 'default']) {
36
+ candidatePaths.push(output
37
+ .replace(/\{\{language\}\}/g, primaryLang)
38
+ .replace(/\{\{namespace\}\}/g, ns));
39
+ }
40
+ }
41
+ // For each candidate, try: (1) the path as-is resolved from cwd, and
42
+ // (2) an absolute path with a leading '/' — the latter ensures we hit
43
+ // memfs in test environments where vol.fromJSON uses absolute paths like
44
+ // '/locales/en.json' but the output template is relative ('locales/...').
45
+ const seen = new Set();
46
+ const resolvedPaths = [];
47
+ for (const p of candidatePaths) {
48
+ const abs = node_path.resolve(p);
49
+ const leadingSlash = '/' + p.replace(/^\//, '');
50
+ for (const candidate of [abs, leadingSlash]) {
51
+ if (!seen.has(candidate)) {
52
+ seen.add(candidate);
53
+ resolvedPaths.push(candidate);
54
+ }
55
+ }
56
+ }
57
+ for (const filePath of resolvedPaths) {
58
+ try {
59
+ const raw = await promises.readFile(filePath, 'utf-8');
60
+ const json = JSON.parse(raw);
61
+ for (const [k, v] of Object.entries(json)) {
62
+ if (typeof v === 'string')
63
+ result.set(k, v);
64
+ }
65
+ break; // stop after first successful read
66
+ }
67
+ catch {
68
+ // file doesn't exist or is malformed — try next candidate
69
+ }
70
+ }
71
+ return result;
72
+ }
12
73
  // Helper to extract interpolation keys from a translation string
13
74
  function extractInterpolationKeys(str, config) {
14
75
  const prefix = config.extract.interpolationPrefix ?? '{{';
@@ -40,12 +101,17 @@ function isI18nextOptionKey(key) {
40
101
  return false;
41
102
  }
42
103
  // Helper to lint interpolation parameter errors in t() calls
43
- function lintInterpolationParams(ast, code, config) {
104
+ function lintInterpolationParams(ast, code, config, translationValues) {
44
105
  const issues = [];
45
106
  // Only run if enabled (default true)
46
107
  const enabled = config.lint?.checkInterpolationParams !== false;
47
108
  if (!enabled)
48
109
  return issues;
110
+ // Helper for line number
111
+ const getLineNumber = (pos) => {
112
+ return code.substring(0, pos).split('\n').length;
113
+ };
114
+ const callSites = [];
49
115
  // Traverse AST for CallExpressions matching t() or i18n.t()
50
116
  function walk(node, ancestors) {
51
117
  if (!node || typeof node !== 'object')
@@ -103,10 +169,9 @@ function lintInterpolationParams(ast, code, config) {
103
169
  const arg1raw = node.arguments?.[1];
104
170
  const arg0 = arg0raw?.expression ?? arg0raw;
105
171
  const arg1 = arg1raw?.expression ?? arg1raw;
106
- // Only check interpolation params if the first argument is a string literal (translation string)
172
+ // Only check interpolation params if the first argument is a string literal (translation key or string)
107
173
  if (arg0?.type === 'StringLiteral') {
108
- const str = arg0.value;
109
- const keys = extractInterpolationKeys(str, config);
174
+ const keyOrStr = arg0.value;
110
175
  let paramKeys = [];
111
176
  if (arg1?.type === 'ObjectExpression') {
112
177
  paramKeys = arg1.properties
@@ -129,47 +194,56 @@ function lintInterpolationParams(ast, code, config) {
129
194
  }
130
195
  if (!Array.isArray(paramKeys))
131
196
  paramKeys = [];
132
- // Use text search for accurate line numbers (SWC spans use global byte offsets, not per-file)
197
+ // Resolve the actual translation string to check against:
198
+ // fix — if the first arg is a lookup key (no interpolation markers of its own)
199
+ // and we have a loaded translation map, use the translated value instead.
200
+ const resolvedStr = translationValues?.get(keyOrStr) ?? keyOrStr;
133
201
  const searchText = arg0.raw ?? `"${arg0.value}"`;
134
- const position = code.indexOf(searchText);
135
- const issueLineNumber = position > -1 ? getLineNumber(position) : 1;
136
- // Only check for unused parameters if there is at least one interpolation key in the string
137
- if (keys.length > 0) {
138
- // i18next supports nested object access via dot notation (e.g. {{author.name}} with { author }).
139
- // For each interpolation key, check if the root (part before the first dot) matches a provided param.
140
- for (const k of keys) {
141
- const root = k.split('.')[0];
142
- if (!paramKeys.includes(k) && !paramKeys.includes(root)) {
143
- issues.push({
144
- text: `Interpolation parameter "${k}" was not provided`,
145
- line: issueLineNumber,
146
- type: 'interpolation',
147
- });
148
- }
149
- }
150
- // For each provided param, check if it is used either directly or as the root of a dotted key.
151
- // Skip known i18next t() option keys that are not interpolation parameters.
152
- for (const pk of paramKeys) {
153
- if (isI18nextOptionKey(pk))
154
- continue;
155
- const isUsed = keys.some(k => k === pk || k.split('.')[0] === pk);
156
- if (!isUsed) {
157
- issues.push({
158
- text: `Parameter "${pk}" is not used in translation string`,
159
- line: issueLineNumber,
160
- type: 'interpolation',
161
- });
162
- }
163
- }
164
- }
202
+ callSites.push({ translationStr: resolvedStr, searchText, paramKeys });
165
203
  }
166
204
  }
167
205
  }
168
- // Helper for line number
169
- const getLineNumber = (pos) => {
170
- return code.substring(0, pos).split('\n').length;
171
- };
172
206
  walk(ast, []);
207
+ // 187 fix — process call sites in source order, advancing lastSearchIndex so that
208
+ // each occurrence of the same string literal finds its own line, not always the first.
209
+ let lastSearchIndex = 0;
210
+ for (const { translationStr, searchText, paramKeys } of callSites) {
211
+ const position = code.indexOf(searchText, lastSearchIndex);
212
+ if (position === -1)
213
+ continue;
214
+ lastSearchIndex = position + searchText.length;
215
+ const issueLineNumber = getLineNumber(position);
216
+ const keys = extractInterpolationKeys(translationStr, config);
217
+ // Only check for unused parameters if there is at least one interpolation key in the string
218
+ if (keys.length > 0) {
219
+ // i18next supports nested object access via dot notation (e.g. {{author.name}} with { author }).
220
+ // For each interpolation key, check if the root (part before the first dot) matches a provided param.
221
+ for (const k of keys) {
222
+ const root = k.split('.')[0];
223
+ if (!paramKeys.includes(k) && !paramKeys.includes(root)) {
224
+ issues.push({
225
+ text: `Interpolation parameter "${k}" was not provided`,
226
+ line: issueLineNumber,
227
+ type: 'interpolation',
228
+ });
229
+ }
230
+ }
231
+ // For each provided param, check if it is used either directly or as the root of a dotted key.
232
+ // Skip known i18next t() option keys that are not interpolation parameters.
233
+ for (const pk of paramKeys) {
234
+ if (isI18nextOptionKey(pk))
235
+ continue;
236
+ const isUsed = keys.some(k => k === pk || k.split('.')[0] === pk);
237
+ if (!isUsed) {
238
+ issues.push({
239
+ text: `Parameter "${pk}" is not used in translation string`,
240
+ line: issueLineNumber,
241
+ type: 'interpolation',
242
+ });
243
+ }
244
+ }
245
+ }
246
+ }
173
247
  return issues;
174
248
  }
175
249
  const recommendedAcceptedTags = [
@@ -211,6 +285,9 @@ class Linter extends node_events.EventEmitter {
211
285
  ignore: [...defaultIgnore, ...extractIgnore, ...lintIgnore]
212
286
  });
213
287
  this.emit('progress', { message: `Analyzing ${sourceFiles.length} source files...` });
288
+ // Load translation values once so the interpolation linter can resolve lookup keys
289
+ // to their translated strings (fixes: key != value interpolation not detected)
290
+ const translationValues = await loadPrimaryTranslationValues(config);
214
291
  let totalIssues = 0;
215
292
  const issuesByFile = new Map();
216
293
  for (const file of sourceFiles) {
@@ -271,7 +348,7 @@ class Linter extends node_events.EventEmitter {
271
348
  // Collect hardcoded string issues
272
349
  const hardcodedStrings = findHardcodedStrings(ast, code, config);
273
350
  // Collect interpolation parameter issues
274
- const interpolationIssues = lintInterpolationParams(ast, code, config);
351
+ const interpolationIssues = lintInterpolationParams(ast, code, config, translationValues);
275
352
  const allIssues = [...hardcodedStrings, ...interpolationIssues];
276
353
  if (allIssues.length > 0) {
277
354
  totalIssues += allIssues.length;
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.42.9'); // This string is replaced with the actual version at build time by rollup
29
+ .version('1.42.11'); // 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
@@ -112,7 +112,8 @@ async function loadConfig(configPath, logger = new ConsoleLogger()) {
112
112
  catch (error) {
113
113
  logger.error(`Error loading configuration from ${configPathFound}`);
114
114
  logger.error(error);
115
- return null;
115
+ // Returning null causes ensureConfig to prompt "would you like to create one?"
116
+ throw new Error(`Error loading configuration from ${configPathFound}: ${error?.message || error?.name}`);
116
117
  }
117
118
  }
118
119
  /**
@@ -179,6 +179,12 @@ class ASTVisitors {
179
179
  const extractStringLiteralValue = (node) => {
180
180
  if (!node)
181
181
  return undefined;
182
+ // Handle: typeof SomeConst → TsTypeQuery { exprName: { value: 'SomeConst' } }
183
+ if (node?.type === 'TsTypeQuery') {
184
+ const name = node.exprName?.value ?? node.exprName?.name;
185
+ if (name)
186
+ return this.scopeManager.resolveSimpleStringIdentifier(name);
187
+ }
182
188
  // shapes: TsLiteralType -> { literal: { type: 'StringLiteral', value: 'x' } }
183
189
  if (node.type === 'TsLiteralType' && node.literal)
184
190
  return node.literal.value ?? node.literal.raw;
@@ -229,8 +235,21 @@ class ASTVisitors {
229
235
  }
230
236
  }
231
237
  const ns = extractStringLiteralValue(tp);
232
- if (ns) {
233
- this.scopeManager.setVarInScope(paramKey, { defaultNs: ns });
238
+ // Extract the second type parameter for KPrefix
239
+ // We need to find the second element from the same type parameter list
240
+ const typeParams = typeAnn.typeParameters?.params ??
241
+ typeAnn.typeArguments?.params ??
242
+ typeAnn.typeParams?.params ??
243
+ undefined;
244
+ let kpFromType;
245
+ if (typeParams && typeParams.length >= 2) {
246
+ kpFromType = extractStringLiteralValue(typeParams[1]);
247
+ }
248
+ if (ns || kpFromType) {
249
+ this.scopeManager.setVarInScope(paramKey, {
250
+ defaultNs: ns,
251
+ keyPrefix: kpFromType // honour TFunction<Ns, KPrefix>
252
+ });
234
253
  }
235
254
  }
236
255
  }
@@ -192,6 +192,7 @@ async function processFile(file, plugins, astVisitors, pluginContext, config, lo
192
192
  // "Wire up" the visitor's scope method to the context.
193
193
  // This avoids a circular dependency while giving plugins access to the scope.
194
194
  pluginContext.getVarFromScope = astVisitors.getVarFromScope.bind(astVisitors);
195
+ pluginContext.setVarInScope = astVisitors.scopeManager.setVarInScope.bind(astVisitors.scopeManager);
195
196
  // Pass BOTH file and code
196
197
  astVisitors.setCurrentFile(file, code);
197
198
  // 3. FIRST: Visit the AST to build scope information
@@ -224,15 +224,29 @@ class ScopeManager {
224
224
  if (nsNode?.type === 'StringLiteral') {
225
225
  defaultNs = nsNode.value;
226
226
  }
227
- else if (nsNode?.type === 'ArrayExpression' && nsNode.elements[0]?.expression?.type === 'StringLiteral') {
228
- defaultNs = nsNode.elements[0].expression.value;
227
+ else if (nsNode?.type === 'Identifier') {
228
+ // ← FIX A: resolve const I18N_NS = 'users'
229
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
230
+ }
231
+ else if (nsNode?.type === 'ArrayExpression') {
232
+ const first = nsNode.elements[0]?.expression;
233
+ if (first?.type === 'StringLiteral')
234
+ defaultNs = first.value;
235
+ else if (first?.type === 'Identifier')
236
+ defaultNs = this.resolveSimpleStringIdentifier(first.value);
229
237
  }
230
238
  }
231
239
  kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
232
240
  }
233
241
  if (kpArg?.type === 'ObjectExpression') {
234
242
  const kp = getObjectPropValue(kpArg, 'keyPrefix');
235
- keyPrefix = typeof kp === 'string' ? kp : undefined;
243
+ if (typeof kp === 'string') {
244
+ keyPrefix = kp;
245
+ }
246
+ else if (kp && typeof kp === 'object' && kp.type === 'Identifier') {
247
+ // ← FIX B: resolve { keyPrefix: I18N_PREFIX } where the value is an Identifier
248
+ keyPrefix = this.resolveSimpleStringIdentifier(kp.value);
249
+ }
236
250
  }
237
251
  else if (kpArg?.type === 'StringLiteral') {
238
252
  keyPrefix = kpArg.value;
@@ -288,17 +302,32 @@ class ScopeManager {
288
302
  else {
289
303
  if (nsArgIndex !== -1) {
290
304
  const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
291
- if (nsNode?.type === 'StringLiteral')
305
+ if (nsNode?.type === 'StringLiteral') {
292
306
  defaultNs = nsNode.value;
293
- else if (nsNode?.type === 'ArrayExpression' && nsNode.elements[0]?.expression?.type === 'StringLiteral') {
294
- defaultNs = nsNode.elements[0].expression.value;
307
+ }
308
+ else if (nsNode?.type === 'Identifier') {
309
+ // ← FIX A: resolve const I18N_NS = 'users'
310
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
311
+ }
312
+ else if (nsNode?.type === 'ArrayExpression') {
313
+ const first = nsNode.elements[0]?.expression;
314
+ if (first?.type === 'StringLiteral')
315
+ defaultNs = first.value;
316
+ else if (first?.type === 'Identifier')
317
+ defaultNs = this.resolveSimpleStringIdentifier(first.value);
295
318
  }
296
319
  }
297
320
  kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
298
321
  }
299
322
  if (kpArg?.type === 'ObjectExpression') {
300
323
  const kp = getObjectPropValue(kpArg, 'keyPrefix');
301
- keyPrefix = typeof kp === 'string' ? kp : undefined;
324
+ if (typeof kp === 'string') {
325
+ keyPrefix = kp;
326
+ }
327
+ else if (kp && typeof kp === 'object' && kp.type === 'Identifier') {
328
+ // ← FIX B: resolve { keyPrefix: I18N_PREFIX } where the value is an Identifier
329
+ keyPrefix = this.resolveSimpleStringIdentifier(kp.value);
330
+ }
302
331
  }
303
332
  else if (kpArg?.type === 'StringLiteral') {
304
333
  keyPrefix = kpArg.value;
@@ -97,6 +97,8 @@ function createPluginContext(allKeys, plugins, config, logger) {
97
97
  logger,
98
98
  // This will be attached later, so we provide a placeholder
99
99
  getVarFromScope: () => undefined,
100
+ // This will be attached later, so we provide a placeholder
101
+ setVarInScope: (_name, _info) => undefined,
100
102
  };
101
103
  }
102
104
 
@@ -1,12 +1,73 @@
1
1
  import { glob } from 'glob';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { parse } from '@swc/core';
4
- import { extname } from 'node:path';
4
+ import { extname, resolve } from 'node:path';
5
5
  import { EventEmitter } from 'node:events';
6
6
  import { styleText } from 'node:util';
7
7
  import { ConsoleLogger } from './utils/logger.js';
8
8
  import { createSpinnerLike } from './utils/wrap-ora.js';
9
9
 
10
+ /**
11
+ * Loads all translation values from the primary locale's JSON files and returns
12
+ * a flat Map of key -> translated string. Used by the interpolation linter so it
13
+ * can resolve a lookup key (e.g. "ABC") to its actual value ("hello {{name}}")
14
+ * and check interpolation parameters against the real string, not the key.
15
+ */
16
+ async function loadPrimaryTranslationValues(config) {
17
+ const result = new Map();
18
+ const output = config.extract?.output;
19
+ if (!output || typeof output !== 'string')
20
+ return result;
21
+ const primaryLang = config.extract?.primaryLanguage ?? config.locales?.[0] ?? 'en';
22
+ // Candidate paths: substitute language + try common namespace names (including no namespace).
23
+ // This covers patterns like:
24
+ // locales/{{language}}.json -> no namespace token
25
+ // locales/{{language}}/{{namespace}}.json -> substitute 'translation' (i18next default)
26
+ // Deliberately uses readFile directly (not glob) so it works correctly in test
27
+ // environments that mock fs/promises via memfs.
28
+ const candidatePaths = [];
29
+ if (!output.includes('{{namespace}}')) {
30
+ candidatePaths.push(output.replace(/\{\{language\}\}/g, primaryLang));
31
+ }
32
+ else {
33
+ for (const ns of ['translation', 'common', 'default']) {
34
+ candidatePaths.push(output
35
+ .replace(/\{\{language\}\}/g, primaryLang)
36
+ .replace(/\{\{namespace\}\}/g, ns));
37
+ }
38
+ }
39
+ // For each candidate, try: (1) the path as-is resolved from cwd, and
40
+ // (2) an absolute path with a leading '/' — the latter ensures we hit
41
+ // memfs in test environments where vol.fromJSON uses absolute paths like
42
+ // '/locales/en.json' but the output template is relative ('locales/...').
43
+ const seen = new Set();
44
+ const resolvedPaths = [];
45
+ for (const p of candidatePaths) {
46
+ const abs = resolve(p);
47
+ const leadingSlash = '/' + p.replace(/^\//, '');
48
+ for (const candidate of [abs, leadingSlash]) {
49
+ if (!seen.has(candidate)) {
50
+ seen.add(candidate);
51
+ resolvedPaths.push(candidate);
52
+ }
53
+ }
54
+ }
55
+ for (const filePath of resolvedPaths) {
56
+ try {
57
+ const raw = await readFile(filePath, 'utf-8');
58
+ const json = JSON.parse(raw);
59
+ for (const [k, v] of Object.entries(json)) {
60
+ if (typeof v === 'string')
61
+ result.set(k, v);
62
+ }
63
+ break; // stop after first successful read
64
+ }
65
+ catch {
66
+ // file doesn't exist or is malformed — try next candidate
67
+ }
68
+ }
69
+ return result;
70
+ }
10
71
  // Helper to extract interpolation keys from a translation string
11
72
  function extractInterpolationKeys(str, config) {
12
73
  const prefix = config.extract.interpolationPrefix ?? '{{';
@@ -38,12 +99,17 @@ function isI18nextOptionKey(key) {
38
99
  return false;
39
100
  }
40
101
  // Helper to lint interpolation parameter errors in t() calls
41
- function lintInterpolationParams(ast, code, config) {
102
+ function lintInterpolationParams(ast, code, config, translationValues) {
42
103
  const issues = [];
43
104
  // Only run if enabled (default true)
44
105
  const enabled = config.lint?.checkInterpolationParams !== false;
45
106
  if (!enabled)
46
107
  return issues;
108
+ // Helper for line number
109
+ const getLineNumber = (pos) => {
110
+ return code.substring(0, pos).split('\n').length;
111
+ };
112
+ const callSites = [];
47
113
  // Traverse AST for CallExpressions matching t() or i18n.t()
48
114
  function walk(node, ancestors) {
49
115
  if (!node || typeof node !== 'object')
@@ -101,10 +167,9 @@ function lintInterpolationParams(ast, code, config) {
101
167
  const arg1raw = node.arguments?.[1];
102
168
  const arg0 = arg0raw?.expression ?? arg0raw;
103
169
  const arg1 = arg1raw?.expression ?? arg1raw;
104
- // Only check interpolation params if the first argument is a string literal (translation string)
170
+ // Only check interpolation params if the first argument is a string literal (translation key or string)
105
171
  if (arg0?.type === 'StringLiteral') {
106
- const str = arg0.value;
107
- const keys = extractInterpolationKeys(str, config);
172
+ const keyOrStr = arg0.value;
108
173
  let paramKeys = [];
109
174
  if (arg1?.type === 'ObjectExpression') {
110
175
  paramKeys = arg1.properties
@@ -127,47 +192,56 @@ function lintInterpolationParams(ast, code, config) {
127
192
  }
128
193
  if (!Array.isArray(paramKeys))
129
194
  paramKeys = [];
130
- // Use text search for accurate line numbers (SWC spans use global byte offsets, not per-file)
195
+ // Resolve the actual translation string to check against:
196
+ // fix — if the first arg is a lookup key (no interpolation markers of its own)
197
+ // and we have a loaded translation map, use the translated value instead.
198
+ const resolvedStr = translationValues?.get(keyOrStr) ?? keyOrStr;
131
199
  const searchText = arg0.raw ?? `"${arg0.value}"`;
132
- const position = code.indexOf(searchText);
133
- const issueLineNumber = position > -1 ? getLineNumber(position) : 1;
134
- // Only check for unused parameters if there is at least one interpolation key in the string
135
- if (keys.length > 0) {
136
- // i18next supports nested object access via dot notation (e.g. {{author.name}} with { author }).
137
- // For each interpolation key, check if the root (part before the first dot) matches a provided param.
138
- for (const k of keys) {
139
- const root = k.split('.')[0];
140
- if (!paramKeys.includes(k) && !paramKeys.includes(root)) {
141
- issues.push({
142
- text: `Interpolation parameter "${k}" was not provided`,
143
- line: issueLineNumber,
144
- type: 'interpolation',
145
- });
146
- }
147
- }
148
- // For each provided param, check if it is used either directly or as the root of a dotted key.
149
- // Skip known i18next t() option keys that are not interpolation parameters.
150
- for (const pk of paramKeys) {
151
- if (isI18nextOptionKey(pk))
152
- continue;
153
- const isUsed = keys.some(k => k === pk || k.split('.')[0] === pk);
154
- if (!isUsed) {
155
- issues.push({
156
- text: `Parameter "${pk}" is not used in translation string`,
157
- line: issueLineNumber,
158
- type: 'interpolation',
159
- });
160
- }
161
- }
162
- }
200
+ callSites.push({ translationStr: resolvedStr, searchText, paramKeys });
163
201
  }
164
202
  }
165
203
  }
166
- // Helper for line number
167
- const getLineNumber = (pos) => {
168
- return code.substring(0, pos).split('\n').length;
169
- };
170
204
  walk(ast, []);
205
+ // 187 fix — process call sites in source order, advancing lastSearchIndex so that
206
+ // each occurrence of the same string literal finds its own line, not always the first.
207
+ let lastSearchIndex = 0;
208
+ for (const { translationStr, searchText, paramKeys } of callSites) {
209
+ const position = code.indexOf(searchText, lastSearchIndex);
210
+ if (position === -1)
211
+ continue;
212
+ lastSearchIndex = position + searchText.length;
213
+ const issueLineNumber = getLineNumber(position);
214
+ const keys = extractInterpolationKeys(translationStr, config);
215
+ // Only check for unused parameters if there is at least one interpolation key in the string
216
+ if (keys.length > 0) {
217
+ // i18next supports nested object access via dot notation (e.g. {{author.name}} with { author }).
218
+ // For each interpolation key, check if the root (part before the first dot) matches a provided param.
219
+ for (const k of keys) {
220
+ const root = k.split('.')[0];
221
+ if (!paramKeys.includes(k) && !paramKeys.includes(root)) {
222
+ issues.push({
223
+ text: `Interpolation parameter "${k}" was not provided`,
224
+ line: issueLineNumber,
225
+ type: 'interpolation',
226
+ });
227
+ }
228
+ }
229
+ // For each provided param, check if it is used either directly or as the root of a dotted key.
230
+ // Skip known i18next t() option keys that are not interpolation parameters.
231
+ for (const pk of paramKeys) {
232
+ if (isI18nextOptionKey(pk))
233
+ continue;
234
+ const isUsed = keys.some(k => k === pk || k.split('.')[0] === pk);
235
+ if (!isUsed) {
236
+ issues.push({
237
+ text: `Parameter "${pk}" is not used in translation string`,
238
+ line: issueLineNumber,
239
+ type: 'interpolation',
240
+ });
241
+ }
242
+ }
243
+ }
244
+ }
171
245
  return issues;
172
246
  }
173
247
  const recommendedAcceptedTags = [
@@ -209,6 +283,9 @@ class Linter extends EventEmitter {
209
283
  ignore: [...defaultIgnore, ...extractIgnore, ...lintIgnore]
210
284
  });
211
285
  this.emit('progress', { message: `Analyzing ${sourceFiles.length} source files...` });
286
+ // Load translation values once so the interpolation linter can resolve lookup keys
287
+ // to their translated strings (fixes: key != value interpolation not detected)
288
+ const translationValues = await loadPrimaryTranslationValues(config);
212
289
  let totalIssues = 0;
213
290
  const issuesByFile = new Map();
214
291
  for (const file of sourceFiles) {
@@ -269,7 +346,7 @@ class Linter extends EventEmitter {
269
346
  // Collect hardcoded string issues
270
347
  const hardcodedStrings = findHardcodedStrings(ast, code, config);
271
348
  // Collect interpolation parameter issues
272
- const interpolationIssues = lintInterpolationParams(ast, code, config);
349
+ const interpolationIssues = lintInterpolationParams(ast, code, config, translationValues);
273
350
  const allIssues = [...hardcodedStrings, ...interpolationIssues];
274
351
  if (allIssues.length > 0) {
275
352
  totalIssues += allIssues.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.42.9",
3
+ "version": "1.42.11",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -55,8 +55,8 @@
55
55
  "@rollup/plugin-replace": "6.0.3",
56
56
  "@rollup/plugin-terser": "0.4.4",
57
57
  "@types/inquirer": "9.0.9",
58
- "@types/node": "25.2.1",
59
- "@types/react": "19.2.13",
58
+ "@types/node": "25.3.0",
59
+ "@types/react": "19.2.14",
60
60
  "@vitest/coverage-v8": "4.0.18",
61
61
  "eslint": "9.39.2",
62
62
  "eslint-plugin-import": "2.32.0",
@@ -74,12 +74,12 @@
74
74
  "chokidar": "5.0.0",
75
75
  "commander": "14.0.3",
76
76
  "execa": "9.6.1",
77
- "glob": "13.0.1",
77
+ "glob": "13.0.6",
78
78
  "i18next-resources-for-ts": "2.0.0",
79
- "inquirer": "13.2.2",
79
+ "inquirer": "13.2.5",
80
80
  "jiti": "2.6.1",
81
81
  "jsonc-parser": "3.3.1",
82
- "minimatch": "10.1.2",
82
+ "minimatch": "10.2.2",
83
83
  "ora": "9.3.0",
84
84
  "react": "^19.2.4",
85
85
  "react-i18next": "^16.5.4"
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAc3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAE,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAEhF;AAgCD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA8CjI;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA8B5H;AAyBD;;;GAGG;AACH,wBAAsB,kBAAkB,IAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyB3E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAc3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAE,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAEhF;AAgCD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA+CjI;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA8B5H;AAyBD;;;GAGG;AACH,wBAAsB,kBAAkB,IAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyB3E"}
@@ -1,5 +1,6 @@
1
1
  import type { Module } from '@swc/core';
2
2
  import type { PluginContext, I18nextToolkitConfig, Logger, ASTVisitorHooks, ScopeInfo } from '../../types';
3
+ import { ScopeManager } from '../parsers/scope-manager';
3
4
  import { ExpressionResolver } from '../parsers/expression-resolver';
4
5
  /**
5
6
  * AST visitor class that traverses JavaScript/TypeScript syntax trees to extract translation keys.
@@ -29,7 +30,7 @@ export declare class ASTVisitors {
29
30
  private readonly logger;
30
31
  private hooks;
31
32
  get objectKeys(): Set<string>;
32
- private readonly scopeManager;
33
+ readonly scopeManager: ScopeManager;
33
34
  private readonly expressionResolver;
34
35
  private readonly callExpressionHandler;
35
36
  private readonly jsxHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAInE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAEhC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAgCzC;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IA8NZ;;;;;;;;OAQG;IACI,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI5D;;OAEG;IACI,cAAc,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxD;;;;;;OAMG;IACI,cAAc,IAAK,MAAM;IAIhC;;OAEG;IACI,cAAc,IAAK,MAAM;CAGjC"}
1
+ {"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC1G,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAInE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,SAAgB,YAAY,EAAE,YAAY,CAAA;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAEhC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe,EACvB,kBAAkB,CAAC,EAAE,kBAAkB;IAgCzC;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IAoPZ;;;;;;;;OAQG;IACI,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI5D;;OAEG;IACI,cAAc,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxD;;;;;;OAMG;IACI,cAAc,IAAK,MAAM;IAIhC;;OAEG;IACI,cAAc,IAAK,MAAM;CAGjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/extractor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMtF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAK5C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CACX,GACL,OAAO,CAAC,OAAO,CAAC,CAkElB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,MAAM,GAAE,MAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CA0Gf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,uBAA+B,EAAE,GAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAO,sDAO3I"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/extractor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMtF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAK5C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CACX,GACL,OAAO,CAAC,OAAO,CAAC,CAkElB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,MAAM,GAAE,MAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CA2Gf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,uBAA+B,EAAE,GAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAO,sDAO3I"}
@@ -44,7 +44,7 @@ export declare class ScopeManager {
44
44
  /**
45
45
  * Resolve simple identifier declared in-file to its string literal value, if known.
46
46
  */
47
- private resolveSimpleStringIdentifier;
47
+ resolveSimpleStringIdentifier(name: string): string | undefined;
48
48
  /**
49
49
  * Handles variable declarations that might define translation functions.
50
50
  *
@@ -1 +1 @@
1
- {"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAmC,MAAM,WAAW,CAAA;AACpF,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG5F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;IAGlF,OAAO,CAAC,eAAe,CAAiC;gBAE3C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAMrB;;;OAGG;IACH,UAAU,IAAK,IAAI;IAInB;;;OAGG;IACH,SAAS,IAAK,IAAI;IAIlB;;;;;;OAMG;IACH,aAAa,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAUnD;;;;;;OAMG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAkBrD,OAAO,CAAC,uBAAuB;IAoB/B;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAIrC;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAuDzD;;;;;;;;OAQG;IACH,OAAO,CAAC,+BAA+B;IA4FvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAmEtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;IAoBjC;;;;;;;;;OASG;IACH,OAAO,CAAC,qCAAqC;CAuB9C"}
1
+ {"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAmC,MAAM,WAAW,CAAA;AACpF,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG5F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;IAGlF,OAAO,CAAC,eAAe,CAAiC;gBAE3C,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAMrB;;;OAGG;IACH,UAAU,IAAK,IAAI;IAInB;;;OAGG;IACH,SAAS,IAAK,IAAI;IAIlB;;;;;;OAMG;IACH,aAAa,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAUnD;;;;;;OAMG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAkBrD,OAAO,CAAC,uBAAuB;IAoB/B;;OAEG;IACI,6BAA6B,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvE;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAuDzD;;;;;;;;OAQG;IACH,OAAO,CAAC,+BAA+B;IAsGvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IA8EtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;IAoBjC;;;;;;;;;OASG;IACH,OAAO,CAAC,qCAAqC;CAuB9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/extractor/plugin-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjG;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAClC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,MAAM,EAAE,MAAM,GACb,aAAa,CAqEf"}
1
+ {"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/extractor/plugin-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAa,MAAM,UAAU,CAAA;AAE5G;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAClC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,MAAM,EAAE,MAAM,GACb,aAAa,CAuEf"}
@@ -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;AA8J3D,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"}
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;AAwP3D,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;;;;;;;CAgGV;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
@@ -463,6 +463,35 @@ export interface PluginContext {
463
463
  * @returns Scope information if found, otherwise undefined.
464
464
  */
465
465
  getVarFromScope: (name: string) => ScopeInfo | undefined;
466
+ /**
467
+ * Injects or overrides variable scope information in the innermost active scope.
468
+ *
469
+ * Use this inside an `onVisitNode` hook to teach the extractor about translation
470
+ * functions whose namespace or key prefix cannot be determined by static analysis
471
+ * alone — for example, when the namespace is derived from an external constant,
472
+ * a config file, or a naming convention that the built-in resolver does not cover.
473
+ *
474
+ * The injected scope will be picked up by subsequent `t()` call resolution for
475
+ * any variable matching `name` in the current scope chain, exactly as if the
476
+ * extractor had found it through a `useTranslation` or `getFixedT` call.
477
+ *
478
+ * @param name - The variable name to register (e.g., `'t'`, `'myT'`).
479
+ * @param info - The scope information to associate: `defaultNs` and/or `keyPrefix`.
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * // Plugin that resolves namespace from a well-known module-level constant
484
+ * onVisitNode(node, context) {
485
+ * if (node.type === 'VariableDeclarator' && isMyHookCall(node)) {
486
+ * context.setVarInScope('t', {
487
+ * defaultNs: 'users',
488
+ * keyPrefix: 'login',
489
+ * })
490
+ * }
491
+ * }
492
+ * ```
493
+ */
494
+ setVarInScope: (name: string, info: ScopeInfo) => void;
466
495
  }
467
496
  /**
468
497
  * Represents variable scope information tracked during AST traversal.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}