i18next-cli 1.39.6 → 1.39.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/rename-key.js +78 -56
- package/dist/esm/cli.js +1 -1
- package/dist/esm/rename-key.js +78 -56
- package/package.json +1 -1
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.39.
|
|
31
|
+
.version('1.39.7'); // 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
|
@@ -246,11 +246,9 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
246
246
|
// Helper to create function-prefix regex fragment
|
|
247
247
|
const fnPrefixToRegex = (fnPattern) => {
|
|
248
248
|
if (fnPattern.startsWith('*.')) {
|
|
249
|
-
// '*.t' -> match anyIdentifier.t
|
|
250
249
|
const suffix = fnPattern.slice(2);
|
|
251
|
-
return `\\b[\\w$]+\\.${escapeRegex(suffix)}`;
|
|
250
|
+
return `\\b[\\w$]+\\.${escapeRegex(suffix)}`;
|
|
252
251
|
}
|
|
253
|
-
// exact function name (may include dot like 'i18n.t' or 'translate')
|
|
254
252
|
return `\\b${escapeRegex(fnPattern)}`;
|
|
255
253
|
};
|
|
256
254
|
// Helper: check whether the old key exists in a given namespace (from the prebuilt map)
|
|
@@ -260,55 +258,73 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
260
258
|
const set = namespaceKeyMap.get(ns);
|
|
261
259
|
return !!(set && set.has(oldParts.key));
|
|
262
260
|
};
|
|
263
|
-
// Replace exact string-key usages inside function calls: fn('key') or fn(`key`) or fn("key")
|
|
264
261
|
for (const fnPattern of configuredFunctions) {
|
|
265
262
|
const prefix = fnPrefixToRegex(fnPattern);
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
//
|
|
263
|
+
//
|
|
264
|
+
// 1) If moving TO the defaultNS, remove the explicit ns option and update key in one go.
|
|
265
|
+
// Only if the old key exists in the old namespace.
|
|
266
|
+
//
|
|
269
267
|
if (oldParts.namespace && newParts.namespace &&
|
|
270
268
|
oldParts.namespace !== newParts.namespace &&
|
|
271
269
|
config.extract.defaultNS === newParts.namespace &&
|
|
272
270
|
hasKeyInNamespace(oldParts.namespace)) {
|
|
273
|
-
// t('key', { ns: 'oldNs' }) -> t('key')
|
|
274
271
|
const nsRegexToDefault = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
275
272
|
newCode = newCode.replace(nsRegexToDefault, (match, keyQ, beforeNs, nsQ, afterNs) => {
|
|
276
273
|
changes++;
|
|
277
|
-
// Build remaining object props (everything except the ns property)
|
|
278
274
|
const obj = (beforeNs + afterNs).replace(/,?\s*$/, '').replace(/^\s*,?/, '').trim();
|
|
279
|
-
// Replace the key string itself, preserving the original quote style
|
|
280
275
|
let updated = match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${keyQ}${newParts.key}${keyQ}`);
|
|
281
276
|
if (obj) {
|
|
282
|
-
// If other properties remain, keep them
|
|
283
277
|
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
284
278
|
}
|
|
285
279
|
else {
|
|
286
|
-
// No other props — remove the options object entirely
|
|
287
280
|
updated = updated.replace(/\s*,\s*\{[^}]*\}\s*\)/, ')');
|
|
288
281
|
}
|
|
289
282
|
return updated;
|
|
290
283
|
});
|
|
291
284
|
}
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
285
|
+
//
|
|
286
|
+
// 2) Handle calls that include an options object with ns: 'oldNs'.
|
|
287
|
+
// This covers both:
|
|
288
|
+
// - renames *inside the same namespace* (ns stays the same, key changes),
|
|
289
|
+
// - renames *across namespaces* (ns changes to new namespace OR removed if new default).
|
|
290
|
+
// Only run if old namespace actually contains the key (to avoid touching unrelated ns calls).
|
|
291
|
+
//
|
|
292
|
+
if (oldParts.namespace && newParts.namespace && hasKeyInNamespace(oldParts.namespace)) {
|
|
296
293
|
const nsRegexFullKey = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
297
|
-
newCode = newCode.replace(nsRegexFullKey, (match) => {
|
|
294
|
+
newCode = newCode.replace(nsRegexFullKey, (match, keyQ, beforeNs, nsQ, afterNs) => {
|
|
298
295
|
changes++;
|
|
299
|
-
//
|
|
300
|
-
|
|
296
|
+
// remaining props except ns
|
|
297
|
+
const obj = (beforeNs + afterNs).replace(/,?\s*$/, '').replace(/^\s*,?/, '').trim();
|
|
298
|
+
// start by replacing the key (preserve original quote style)
|
|
299
|
+
let updated = match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${keyQ}${newParts.key}${keyQ}`);
|
|
300
|
+
if (oldParts.namespace === newParts.namespace) {
|
|
301
|
+
// same namespace: keep ns value untouched, but keep other props
|
|
302
|
+
if (obj) {
|
|
303
|
+
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
// moving across namespaces
|
|
308
|
+
if (config.extract.defaultNS === newParts.namespace) {
|
|
309
|
+
// moving INTO the default namespace -> remove the ns property
|
|
310
|
+
if (obj) {
|
|
311
|
+
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
updated = updated.replace(/\s*,\s*\{[^}]*\}\s*\)/, ')');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
// replace ns value to new namespace
|
|
319
|
+
updated = updated.replace(new RegExp(`(\\bns\\s*:\\s*['"\`])${escapeRegex(oldParts.namespace ?? '')}(['"\`])`), `$1${newParts.namespace ?? ''}$2`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return updated;
|
|
301
323
|
});
|
|
302
|
-
// case where fullKey was used inside the string (e.g. t('ns:key', { ns: 'oldNs' }))
|
|
303
|
-
if (oldParts.fullKey && oldParts.explicitNamespace) {
|
|
304
|
-
const nsRegexFull = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.fullKey)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
305
|
-
newCode = newCode.replace(nsRegexFull, (match) => {
|
|
306
|
-
changes++;
|
|
307
|
-
return match.replace(new RegExp(`(\\bns\\s*:\\s*['"\`])${escapeRegex(oldParts.namespace ?? '')}(['"\`])`), `$1${newParts.namespace ?? ''}$2`);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
324
|
}
|
|
311
|
-
//
|
|
325
|
+
//
|
|
326
|
+
// 3) fullKey (explicitly namespaced string in call): only when user supplied a namespaced target
|
|
327
|
+
//
|
|
312
328
|
if (oldParts.fullKey && oldParts.explicitNamespace) {
|
|
313
329
|
const regexFull = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.fullKey)}\\1`, 'g');
|
|
314
330
|
newCode = newCode.replace(regexFull, (match) => {
|
|
@@ -317,14 +333,14 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
317
333
|
return match.replace(oldParts.fullKey, replacementKey);
|
|
318
334
|
});
|
|
319
335
|
}
|
|
320
|
-
//
|
|
321
|
-
// Selector
|
|
336
|
+
//
|
|
337
|
+
// 4) Selector / bracket forms
|
|
338
|
+
//
|
|
322
339
|
{
|
|
323
340
|
const dotRegex = new RegExp(`${prefix}\\s*\\(\\s*\\(?\\s*([a-zA-Z_$][\\w$]*)\\s*\\)?\\s*=>\\s*\\1\\.${escapeRegex(oldParts.key)}\\s*\\)`, 'g');
|
|
324
341
|
newCode = newCode.replace(dotRegex, (match) => {
|
|
325
342
|
changes++;
|
|
326
|
-
|
|
327
|
-
return match.replace(`.${oldParts.key}`, `.${replacementKey}`);
|
|
343
|
+
return match.replace(`.${oldParts.key}`, `.${newParts.key}`);
|
|
328
344
|
});
|
|
329
345
|
const bracketRegex = new RegExp(`${prefix}\\s*\\(\\s*\\(?\\s*([a-zA-Z_$][\\w$]*)\\s*\\)?\\s*=>\\s*\\1\\s*\\[\\s*(['"\`])${escapeRegex(oldParts.key)}\\2\\s*\\]\\s*\\)`, 'g');
|
|
330
346
|
newCode = newCode.replace(bracketRegex, (match) => {
|
|
@@ -338,20 +354,11 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
338
354
|
}
|
|
339
355
|
});
|
|
340
356
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
changes++;
|
|
347
|
-
const replacementKey = newParts.key;
|
|
348
|
-
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${q}${replacementKey}${q}`);
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
// 6) Handle the case where we have fn('key', /*no ns*/ { otherProps }) and we are moving
|
|
352
|
-
// from defaultNS to another namespace: add ns when appropriate.
|
|
353
|
-
// This block is only relevant when moving FROM defaultNS (add ns option). Only perform it
|
|
354
|
-
// if the old key exists in the old namespace (if we tracked one).
|
|
357
|
+
//
|
|
358
|
+
// 5) Special-case: moving FROM defaultNS to another namespace for bare calls.
|
|
359
|
+
// Add ns option for bare calls. This must happen *before* the plain bare-call replacement
|
|
360
|
+
// so the final call includes the ns option.
|
|
361
|
+
//
|
|
355
362
|
if (oldParts.namespace && newParts.namespace &&
|
|
356
363
|
oldParts.namespace !== newParts.namespace &&
|
|
357
364
|
config.extract.defaultNS === oldParts.namespace &&
|
|
@@ -362,19 +369,34 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
362
369
|
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1\\s*\\)`), `${quote}${newParts.key}${quote}, { ns: '${newParts.namespace}' })`);
|
|
363
370
|
});
|
|
364
371
|
}
|
|
365
|
-
//
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
newCode = newCode.replace(p.regex, (match, q) => {
|
|
372
|
+
//
|
|
373
|
+
// 6) Bare calls without options: fn('key') -> fn('newKey')
|
|
374
|
+
//
|
|
375
|
+
{
|
|
376
|
+
const regexKeyNoOptions = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*\\)`, 'g');
|
|
377
|
+
newCode = newCode.replace(regexKeyNoOptions, (match, q) => {
|
|
372
378
|
changes++;
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
return `i18nKey=${q}${replacement}${q}`;
|
|
379
|
+
const replacementKey = newParts.key;
|
|
380
|
+
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${q}${replacementKey}${q}`);
|
|
376
381
|
});
|
|
377
382
|
}
|
|
383
|
+
//
|
|
384
|
+
// 7) JSX i18nKey attribute (handles both fullKey and key)
|
|
385
|
+
//
|
|
386
|
+
{
|
|
387
|
+
const jsxPatterns = [
|
|
388
|
+
{ orig: oldParts.fullKey, regex: new RegExp(`i18nKey=(['"\`])${escapeRegex(oldParts.fullKey)}\\1`, 'g') },
|
|
389
|
+
{ orig: oldParts.key, regex: new RegExp(`i18nKey=(['"\`])${escapeRegex(oldParts.key)}\\1`, 'g') }
|
|
390
|
+
];
|
|
391
|
+
for (const p of jsxPatterns) {
|
|
392
|
+
newCode = newCode.replace(p.regex, (match, q) => {
|
|
393
|
+
changes++;
|
|
394
|
+
const nsSepStr = nsSeparator === false ? ':' : nsSeparator;
|
|
395
|
+
const replacement = (p.orig === oldParts.fullKey && oldParts.fullKey.includes(nsSepStr)) ? newParts.fullKey : newParts.key;
|
|
396
|
+
return `i18nKey=${q}${replacement}${q}`;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
378
400
|
}
|
|
379
401
|
return { newCode, changes };
|
|
380
402
|
}
|
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.39.
|
|
29
|
+
.version('1.39.7'); // 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
|
@@ -244,11 +244,9 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
244
244
|
// Helper to create function-prefix regex fragment
|
|
245
245
|
const fnPrefixToRegex = (fnPattern) => {
|
|
246
246
|
if (fnPattern.startsWith('*.')) {
|
|
247
|
-
// '*.t' -> match anyIdentifier.t
|
|
248
247
|
const suffix = fnPattern.slice(2);
|
|
249
|
-
return `\\b[\\w$]+\\.${escapeRegex(suffix)}`;
|
|
248
|
+
return `\\b[\\w$]+\\.${escapeRegex(suffix)}`;
|
|
250
249
|
}
|
|
251
|
-
// exact function name (may include dot like 'i18n.t' or 'translate')
|
|
252
250
|
return `\\b${escapeRegex(fnPattern)}`;
|
|
253
251
|
};
|
|
254
252
|
// Helper: check whether the old key exists in a given namespace (from the prebuilt map)
|
|
@@ -258,55 +256,73 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
258
256
|
const set = namespaceKeyMap.get(ns);
|
|
259
257
|
return !!(set && set.has(oldParts.key));
|
|
260
258
|
};
|
|
261
|
-
// Replace exact string-key usages inside function calls: fn('key') or fn(`key`) or fn("key")
|
|
262
259
|
for (const fnPattern of configuredFunctions) {
|
|
263
260
|
const prefix = fnPrefixToRegex(fnPattern);
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
261
|
+
//
|
|
262
|
+
// 1) If moving TO the defaultNS, remove the explicit ns option and update key in one go.
|
|
263
|
+
// Only if the old key exists in the old namespace.
|
|
264
|
+
//
|
|
267
265
|
if (oldParts.namespace && newParts.namespace &&
|
|
268
266
|
oldParts.namespace !== newParts.namespace &&
|
|
269
267
|
config.extract.defaultNS === newParts.namespace &&
|
|
270
268
|
hasKeyInNamespace(oldParts.namespace)) {
|
|
271
|
-
// t('key', { ns: 'oldNs' }) -> t('key')
|
|
272
269
|
const nsRegexToDefault = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
273
270
|
newCode = newCode.replace(nsRegexToDefault, (match, keyQ, beforeNs, nsQ, afterNs) => {
|
|
274
271
|
changes++;
|
|
275
|
-
// Build remaining object props (everything except the ns property)
|
|
276
272
|
const obj = (beforeNs + afterNs).replace(/,?\s*$/, '').replace(/^\s*,?/, '').trim();
|
|
277
|
-
// Replace the key string itself, preserving the original quote style
|
|
278
273
|
let updated = match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${keyQ}${newParts.key}${keyQ}`);
|
|
279
274
|
if (obj) {
|
|
280
|
-
// If other properties remain, keep them
|
|
281
275
|
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
282
276
|
}
|
|
283
277
|
else {
|
|
284
|
-
// No other props — remove the options object entirely
|
|
285
278
|
updated = updated.replace(/\s*,\s*\{[^}]*\}\s*\)/, ')');
|
|
286
279
|
}
|
|
287
280
|
return updated;
|
|
288
281
|
});
|
|
289
282
|
}
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
|
|
283
|
+
//
|
|
284
|
+
// 2) Handle calls that include an options object with ns: 'oldNs'.
|
|
285
|
+
// This covers both:
|
|
286
|
+
// - renames *inside the same namespace* (ns stays the same, key changes),
|
|
287
|
+
// - renames *across namespaces* (ns changes to new namespace OR removed if new default).
|
|
288
|
+
// Only run if old namespace actually contains the key (to avoid touching unrelated ns calls).
|
|
289
|
+
//
|
|
290
|
+
if (oldParts.namespace && newParts.namespace && hasKeyInNamespace(oldParts.namespace)) {
|
|
294
291
|
const nsRegexFullKey = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
295
|
-
newCode = newCode.replace(nsRegexFullKey, (match) => {
|
|
292
|
+
newCode = newCode.replace(nsRegexFullKey, (match, keyQ, beforeNs, nsQ, afterNs) => {
|
|
296
293
|
changes++;
|
|
297
|
-
//
|
|
298
|
-
|
|
294
|
+
// remaining props except ns
|
|
295
|
+
const obj = (beforeNs + afterNs).replace(/,?\s*$/, '').replace(/^\s*,?/, '').trim();
|
|
296
|
+
// start by replacing the key (preserve original quote style)
|
|
297
|
+
let updated = match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${keyQ}${newParts.key}${keyQ}`);
|
|
298
|
+
if (oldParts.namespace === newParts.namespace) {
|
|
299
|
+
// same namespace: keep ns value untouched, but keep other props
|
|
300
|
+
if (obj) {
|
|
301
|
+
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// moving across namespaces
|
|
306
|
+
if (config.extract.defaultNS === newParts.namespace) {
|
|
307
|
+
// moving INTO the default namespace -> remove the ns property
|
|
308
|
+
if (obj) {
|
|
309
|
+
updated = updated.replace(/\{\s*([^}]*)\s*\}/, `{${obj}}`);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
updated = updated.replace(/\s*,\s*\{[^}]*\}\s*\)/, ')');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// replace ns value to new namespace
|
|
317
|
+
updated = updated.replace(new RegExp(`(\\bns\\s*:\\s*['"\`])${escapeRegex(oldParts.namespace ?? '')}(['"\`])`), `$1${newParts.namespace ?? ''}$2`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return updated;
|
|
299
321
|
});
|
|
300
|
-
// case where fullKey was used inside the string (e.g. t('ns:key', { ns: 'oldNs' }))
|
|
301
|
-
if (oldParts.fullKey && oldParts.explicitNamespace) {
|
|
302
|
-
const nsRegexFull = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.fullKey)}\\1\\s*,\\s*\\{([^}]*)\\bns\\s*:\\s*(['"\`])${escapeRegex(oldParts.namespace)}\\3([^}]*)\\}\\s*\\)`, 'g');
|
|
303
|
-
newCode = newCode.replace(nsRegexFull, (match) => {
|
|
304
|
-
changes++;
|
|
305
|
-
return match.replace(new RegExp(`(\\bns\\s*:\\s*['"\`])${escapeRegex(oldParts.namespace ?? '')}(['"\`])`), `$1${newParts.namespace ?? ''}$2`);
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
322
|
}
|
|
309
|
-
//
|
|
323
|
+
//
|
|
324
|
+
// 3) fullKey (explicitly namespaced string in call): only when user supplied a namespaced target
|
|
325
|
+
//
|
|
310
326
|
if (oldParts.fullKey && oldParts.explicitNamespace) {
|
|
311
327
|
const regexFull = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.fullKey)}\\1`, 'g');
|
|
312
328
|
newCode = newCode.replace(regexFull, (match) => {
|
|
@@ -315,14 +331,14 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
315
331
|
return match.replace(oldParts.fullKey, replacementKey);
|
|
316
332
|
});
|
|
317
333
|
}
|
|
318
|
-
//
|
|
319
|
-
// Selector
|
|
334
|
+
//
|
|
335
|
+
// 4) Selector / bracket forms
|
|
336
|
+
//
|
|
320
337
|
{
|
|
321
338
|
const dotRegex = new RegExp(`${prefix}\\s*\\(\\s*\\(?\\s*([a-zA-Z_$][\\w$]*)\\s*\\)?\\s*=>\\s*\\1\\.${escapeRegex(oldParts.key)}\\s*\\)`, 'g');
|
|
322
339
|
newCode = newCode.replace(dotRegex, (match) => {
|
|
323
340
|
changes++;
|
|
324
|
-
|
|
325
|
-
return match.replace(`.${oldParts.key}`, `.${replacementKey}`);
|
|
341
|
+
return match.replace(`.${oldParts.key}`, `.${newParts.key}`);
|
|
326
342
|
});
|
|
327
343
|
const bracketRegex = new RegExp(`${prefix}\\s*\\(\\s*\\(?\\s*([a-zA-Z_$][\\w$]*)\\s*\\)?\\s*=>\\s*\\1\\s*\\[\\s*(['"\`])${escapeRegex(oldParts.key)}\\2\\s*\\]\\s*\\)`, 'g');
|
|
328
344
|
newCode = newCode.replace(bracketRegex, (match) => {
|
|
@@ -336,20 +352,11 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
336
352
|
}
|
|
337
353
|
});
|
|
338
354
|
}
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
changes++;
|
|
345
|
-
const replacementKey = newParts.key;
|
|
346
|
-
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${q}${replacementKey}${q}`);
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
// 6) Handle the case where we have fn('key', /*no ns*/ { otherProps }) and we are moving
|
|
350
|
-
// from defaultNS to another namespace: add ns when appropriate.
|
|
351
|
-
// This block is only relevant when moving FROM defaultNS (add ns option). Only perform it
|
|
352
|
-
// if the old key exists in the old namespace (if we tracked one).
|
|
355
|
+
//
|
|
356
|
+
// 5) Special-case: moving FROM defaultNS to another namespace for bare calls.
|
|
357
|
+
// Add ns option for bare calls. This must happen *before* the plain bare-call replacement
|
|
358
|
+
// so the final call includes the ns option.
|
|
359
|
+
//
|
|
353
360
|
if (oldParts.namespace && newParts.namespace &&
|
|
354
361
|
oldParts.namespace !== newParts.namespace &&
|
|
355
362
|
config.extract.defaultNS === oldParts.namespace &&
|
|
@@ -360,19 +367,34 @@ function replaceKeyWithRegex(code, oldParts, newParts, config, namespaceKeyMap)
|
|
|
360
367
|
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1\\s*\\)`), `${quote}${newParts.key}${quote}, { ns: '${newParts.namespace}' })`);
|
|
361
368
|
});
|
|
362
369
|
}
|
|
363
|
-
//
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
newCode = newCode.replace(p.regex, (match, q) => {
|
|
370
|
+
//
|
|
371
|
+
// 6) Bare calls without options: fn('key') -> fn('newKey')
|
|
372
|
+
//
|
|
373
|
+
{
|
|
374
|
+
const regexKeyNoOptions = new RegExp(`${prefix}\\s*\\(\\s*(['"\`])${escapeRegex(oldParts.key)}\\1\\s*\\)`, 'g');
|
|
375
|
+
newCode = newCode.replace(regexKeyNoOptions, (match, q) => {
|
|
370
376
|
changes++;
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
return `i18nKey=${q}${replacement}${q}`;
|
|
377
|
+
const replacementKey = newParts.key;
|
|
378
|
+
return match.replace(new RegExp(`(['"\`])${escapeRegex(oldParts.key)}\\1`), `${q}${replacementKey}${q}`);
|
|
374
379
|
});
|
|
375
380
|
}
|
|
381
|
+
//
|
|
382
|
+
// 7) JSX i18nKey attribute (handles both fullKey and key)
|
|
383
|
+
//
|
|
384
|
+
{
|
|
385
|
+
const jsxPatterns = [
|
|
386
|
+
{ orig: oldParts.fullKey, regex: new RegExp(`i18nKey=(['"\`])${escapeRegex(oldParts.fullKey)}\\1`, 'g') },
|
|
387
|
+
{ orig: oldParts.key, regex: new RegExp(`i18nKey=(['"\`])${escapeRegex(oldParts.key)}\\1`, 'g') }
|
|
388
|
+
];
|
|
389
|
+
for (const p of jsxPatterns) {
|
|
390
|
+
newCode = newCode.replace(p.regex, (match, q) => {
|
|
391
|
+
changes++;
|
|
392
|
+
const nsSepStr = nsSeparator === false ? ':' : nsSeparator;
|
|
393
|
+
const replacement = (p.orig === oldParts.fullKey && oldParts.fullKey.includes(nsSepStr)) ? newParts.fullKey : newParts.key;
|
|
394
|
+
return `i18nKey=${q}${replacement}${q}`;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
376
398
|
}
|
|
377
399
|
return { newCode, changes };
|
|
378
400
|
}
|