i18next-cli 1.54.2 → 1.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/cjs/cli.js +66 -2
- package/dist/cjs/extractor/core/ast-visitors.js +11 -1
- package/dist/cjs/extractor/core/extractor.js +1 -1
- package/dist/cjs/extractor/core/translation-manager.js +127 -54
- package/dist/cjs/extractor/parsers/call-expression-handler.js +17 -93
- package/dist/cjs/extractor/parsers/expression-resolver.js +96 -11
- package/dist/cjs/status.js +73 -12
- package/dist/cjs/utils/context-variants.js +59 -0
- package/dist/cjs/utils/nesting.js +100 -0
- package/dist/esm/cli.js +66 -2
- package/dist/esm/extractor/core/ast-visitors.js +11 -1
- package/dist/esm/extractor/core/extractor.js +1 -1
- package/dist/esm/extractor/core/translation-manager.js +126 -53
- package/dist/esm/extractor/parsers/call-expression-handler.js +17 -93
- package/dist/esm/extractor/parsers/expression-resolver.js +96 -11
- package/dist/esm/status.js +74 -13
- package/dist/esm/utils/context-variants.js +57 -0
- package/dist/esm/utils/nesting.js +98 -0
- package/package.json +1 -1
- package/types/cli.d.ts.map +1 -1
- package/types/extractor/core/ast-visitors.d.ts.map +1 -1
- package/types/extractor/core/extractor.d.ts +1 -0
- package/types/extractor/core/extractor.d.ts.map +1 -1
- package/types/extractor/core/translation-manager.d.ts.map +1 -1
- package/types/extractor/parsers/call-expression-handler.d.ts +3 -2
- package/types/extractor/parsers/call-expression-handler.d.ts.map +1 -1
- package/types/extractor/parsers/expression-resolver.d.ts +11 -0
- package/types/extractor/parsers/expression-resolver.d.ts.map +1 -1
- package/types/status.d.ts.map +1 -1
- package/types/utils/context-variants.d.ts +22 -0
- package/types/utils/context-variants.d.ts.map +1 -0
- package/types/utils/nesting.d.ts +36 -0
- package/types/utils/nesting.d.ts.map +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for reasoning about context variants of translation keys.
|
|
3
|
+
*
|
|
4
|
+
* A "key accepting context" is a base key that was called with a `context`
|
|
5
|
+
* option in source code (e.g. `t('friend', { context: gender })`). Its
|
|
6
|
+
* variants in the translation file look like `<base><contextSeparator><ctx>`
|
|
7
|
+
* (optionally suffixed with a CLDR plural form).
|
|
8
|
+
*/
|
|
9
|
+
const pluralForms = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|
10
|
+
/**
|
|
11
|
+
* Checks if an existing key is a context variant of a base key that accepts context.
|
|
12
|
+
* Handles:
|
|
13
|
+
* - Keys suffixed with a CLDR plural form (e.g. `friend_male_one`).
|
|
14
|
+
* - Context values that contain the separator (e.g. `mc_laren`).
|
|
15
|
+
*
|
|
16
|
+
* @param existingKey - The key from the translation file to check
|
|
17
|
+
* @param keysAcceptingContext - Set of base keys that were used with context in source code
|
|
18
|
+
* @param pluralSeparator - The separator used for plural forms (default: '_')
|
|
19
|
+
* @param contextSeparator - The separator used for context variants (default: '_')
|
|
20
|
+
* @returns true if the existing key is a context variant of a key accepting context
|
|
21
|
+
*/
|
|
22
|
+
function isContextVariantOfAcceptingKey(existingKey, keysAcceptingContext, pluralSeparator, contextSeparator) {
|
|
23
|
+
if (keysAcceptingContext.size === 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
let potentialBaseKey = existingKey;
|
|
27
|
+
// First, try removing plural suffixes if present
|
|
28
|
+
for (const form of pluralForms) {
|
|
29
|
+
if (potentialBaseKey.endsWith(`${pluralSeparator}${form}`)) {
|
|
30
|
+
potentialBaseKey = potentialBaseKey.slice(0, -(pluralSeparator.length + form.length));
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
if (potentialBaseKey.endsWith(`${pluralSeparator}ordinal${pluralSeparator}${form}`)) {
|
|
34
|
+
potentialBaseKey = potentialBaseKey.slice(0, -(pluralSeparator.length + 'ordinal'.length + pluralSeparator.length + form.length));
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// The context value itself may contain the separator — try every possible
|
|
39
|
+
// split to find a base that matches an accepting-context key.
|
|
40
|
+
const parts = potentialBaseKey.split(contextSeparator);
|
|
41
|
+
if (parts.length > 1) {
|
|
42
|
+
for (let i = 1; i < parts.length; i++) {
|
|
43
|
+
const baseWithoutContext = parts.slice(0, -i).join(contextSeparator);
|
|
44
|
+
if (keysAcceptingContext.has(baseWithoutContext)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Also accept the plural-stripped key itself as a direct match
|
|
50
|
+
// (e.g. `friend_other` → base `friend`).
|
|
51
|
+
if (keysAcceptingContext.has(potentialBaseKey)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { isContextVariantOfAcceptingKey };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared parser for i18next-style nested translation references of the form
|
|
3
|
+
* `$t(key, { options })`.
|
|
4
|
+
*
|
|
5
|
+
* Used in two places:
|
|
6
|
+
* 1. The extractor's AST pass scans source-code keys and default values for
|
|
7
|
+
* nested references and registers the referenced keys (so they show up in
|
|
8
|
+
* output translation files).
|
|
9
|
+
* 2. The translation-manager uses it during `removeUnusedKeys` cleanup so
|
|
10
|
+
* keys that are only referenced from inside a translation value (and thus
|
|
11
|
+
* invisible to the AST pass) are preserved instead of being deleted.
|
|
12
|
+
*/
|
|
13
|
+
const naturalLanguageChars = /[ ,?!;]/;
|
|
14
|
+
const looksLikeNaturalLanguage = (s) => naturalLanguageChars.test(s);
|
|
15
|
+
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
16
|
+
/**
|
|
17
|
+
* Scans a string for `$t(...)` references and returns metadata about each one.
|
|
18
|
+
* The implementation mirrors the behaviour of i18next's Interpolator so that
|
|
19
|
+
* the extractor and translation manager agree on what counts as a reference.
|
|
20
|
+
*/
|
|
21
|
+
function parseNestedReferences(text, config) {
|
|
22
|
+
if (!text || typeof text !== 'string')
|
|
23
|
+
return [];
|
|
24
|
+
const prefix = config.nestingPrefix ?? '$t(';
|
|
25
|
+
const suffix = config.nestingSuffix ?? ')';
|
|
26
|
+
const separator = config.nestingOptionsSeparator ?? ',';
|
|
27
|
+
const nsSeparator = config.nsSeparator ?? ':';
|
|
28
|
+
const escapedPrefix = escapeRegex(prefix);
|
|
29
|
+
const escapedSuffix = escapeRegex(suffix);
|
|
30
|
+
// Regex adapted from i18next Interpolator.js — matches `$t(key)` or
|
|
31
|
+
// `$t(key, { options })` with (limited) support for balanced parens and
|
|
32
|
+
// quoted strings.
|
|
33
|
+
const nestingRegexp = new RegExp(`${escapedPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${escapedSuffix}`, 'g');
|
|
34
|
+
const results = [];
|
|
35
|
+
let match;
|
|
36
|
+
while ((match = nestingRegexp.exec(text)) !== null) {
|
|
37
|
+
const content = match[1];
|
|
38
|
+
if (!content)
|
|
39
|
+
continue;
|
|
40
|
+
let key = content;
|
|
41
|
+
let optionsString = '';
|
|
42
|
+
if (content.indexOf(separator) < 0) {
|
|
43
|
+
key = content.trim();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// i18next does: const c = key.split(new RegExp(`${sep}[ ]*{`));
|
|
47
|
+
// This assumes options start with `{`.
|
|
48
|
+
const sepRegex = new RegExp(`${escapeRegex(separator)}[ ]*{`);
|
|
49
|
+
const parts = content.split(sepRegex);
|
|
50
|
+
if (parts.length > 1) {
|
|
51
|
+
key = parts[0].trim();
|
|
52
|
+
optionsString = `{${parts.slice(1).join(separator + ' {')}`;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const sepIdx = content.indexOf(separator);
|
|
56
|
+
key = content.substring(0, sepIdx).trim();
|
|
57
|
+
optionsString = content.substring(sepIdx + 1).trim();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith('"') && key.endsWith('"'))) {
|
|
61
|
+
key = key.slice(1, -1);
|
|
62
|
+
}
|
|
63
|
+
if (!key)
|
|
64
|
+
continue;
|
|
65
|
+
let ns;
|
|
66
|
+
if (nsSeparator && typeof nsSeparator === 'string' && key.includes(nsSeparator)) {
|
|
67
|
+
const parts = key.split(nsSeparator);
|
|
68
|
+
const candidateNs = parts[0];
|
|
69
|
+
if (!looksLikeNaturalLanguage(candidateNs)) {
|
|
70
|
+
ns = parts.shift();
|
|
71
|
+
key = parts.join(nsSeparator);
|
|
72
|
+
if (!key || key.trim() === '')
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
ns = config.defaultNS;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
ns = config.defaultNS;
|
|
81
|
+
}
|
|
82
|
+
let hasCount = false;
|
|
83
|
+
let context;
|
|
84
|
+
if (optionsString) {
|
|
85
|
+
if (/['"]?count['"]?\s*:/.test(optionsString)) {
|
|
86
|
+
hasCount = true;
|
|
87
|
+
}
|
|
88
|
+
const contextMatch = /['"]?context['"]?\s*:\s*(['"])(.*?)\1/.exec(optionsString);
|
|
89
|
+
if (contextMatch) {
|
|
90
|
+
context = contextMatch[2];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
results.push({ key, ns, hasCount, context });
|
|
94
|
+
}
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { parseNestedReferences };
|
package/package.json
CHANGED
package/types/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoBnC,QAAA,MAAM,OAAO,SAAgB,CAAA;AAiZ7B,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -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,gBAAgB,CAAA;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAItE;;;;;;;;;;;;;;;;;;;;;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;IAiCzC;;;;;;;;;;;;;OAaG;IACI,mBAAmB,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,OAAO,CAAC,iBAAiB;
|
|
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,gBAAgB,CAAA;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAItE;;;;;;;;;;;;;;;;;;;;;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;IAiCzC;;;;;;;;;;;;;OAaG;IACI,mBAAmB,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/C;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8CzB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAUjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IAoXZ;;;;;;;;OAQG;IACH,OAAO,CAAC,gCAAgC;IAqDxC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;;;;;;;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"}
|
|
@@ -37,6 +37,7 @@ export declare function runExtractor(config: I18nextToolkitConfig, options?: {
|
|
|
37
37
|
}): Promise<{
|
|
38
38
|
anyFileUpdated: boolean;
|
|
39
39
|
hasErrors: boolean;
|
|
40
|
+
results: TranslationResult[];
|
|
40
41
|
}>;
|
|
41
42
|
/**
|
|
42
43
|
* Processes an individual source file for translation key extraction.
|
|
@@ -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,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAO5G,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAK/C;;;;;;;;;;;;;;;;;;;;;;;;;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,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CACX,GACL,OAAO,CAAC;IAAE,cAAc,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,
|
|
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,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAO5G,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAK/C;;;;;;;;;;;;;;;;;;;;;;;;;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,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CACX,GACL,OAAO,CAAC;IAAE,cAAc,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CA8ExF;AAwBD;;;;;;;;;;;;;;;;;;;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,EACpC,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,IAAI,CAAC,CAoJf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,MAAM,GAAE,MAA4B,EACpC,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,IAAI,CAAC,CA6Df;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,uBAA+B,EAAE,GAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAO1K"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAohC9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,oBAAoB,EAC5B,EACE,uBAA+B,EAC/B,OAAe,EACf,oBAA4B,EAC5B,MAA4B,EAC7B,GAAE;IACD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;CACX,GACL,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiK9B"}
|
|
@@ -35,10 +35,11 @@ export declare class CallExpressionHandler {
|
|
|
35
35
|
*/
|
|
36
36
|
handleCallExpression(node: CallExpression, getScopeInfo: (name: string) => ScopeInfo | undefined): void;
|
|
37
37
|
/**
|
|
38
|
-
* Scans a string for nested translations like $t(key, options) and
|
|
38
|
+
* Scans a string for nested translations like $t(key, options) and registers
|
|
39
|
+
* the referenced keys (plus their plural / context variants) on the current
|
|
40
|
+
* plugin context.
|
|
39
41
|
*/
|
|
40
42
|
private extractNestedKeys;
|
|
41
|
-
private processNestedContent;
|
|
42
43
|
private generateNestedPluralKeys;
|
|
43
44
|
/**
|
|
44
45
|
* Processed a call expression to extract keys from the specified argument.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-expression-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/call-expression-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAgB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"call-expression-handler.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/call-expression-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAgB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1G,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAa7D,qBAAa,qBAAqB;IAChC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,kBAAkB,CAAoB;IACvC,UAAU,cAAoB;IACrC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,iBAAiB,CAAsC;gBAG7D,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,MAAM,MAAM,EAC5B,cAAc,EAAE,MAAM,MAAM,EAC5B,iBAAiB,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAA2B;IAW3E;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;;;;;;;;;OAcG;IACH,oBAAoB,CAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,GAAG,IAAI;IA0ZxG;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,wBAAwB;IAyEhC;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IA8BpC;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,uBAAuB;IAgE/B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,gBAAgB;IAyMxB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;CA2BxB"}
|
|
@@ -7,6 +7,7 @@ export declare class ExpressionResolver {
|
|
|
7
7
|
private typeAliasTable;
|
|
8
8
|
private sharedVariableTable;
|
|
9
9
|
private sharedTypeAliasTable;
|
|
10
|
+
private sharedFunctionReturnTable;
|
|
10
11
|
private temporaryVariables;
|
|
11
12
|
constructor(hooks: ASTVisitorHooks);
|
|
12
13
|
/**
|
|
@@ -44,6 +45,16 @@ export declare class ExpressionResolver {
|
|
|
44
45
|
* SWC node shapes: `FunctionDeclaration` / `FnDecl`
|
|
45
46
|
*/
|
|
46
47
|
captureFunctionDeclaration(node: any): void;
|
|
48
|
+
/**
|
|
49
|
+
* Walk a function body's ReturnStatements and union the statically-resolvable
|
|
50
|
+
* string values of their argument expressions. Does NOT descend into nested
|
|
51
|
+
* function declarations (their returns belong to the inner function, not us).
|
|
52
|
+
*
|
|
53
|
+
* This is how we mirror TypeScript's implicit return-type inference for the
|
|
54
|
+
* purpose of extracting translation keys — we don't need exhaustiveness, just
|
|
55
|
+
* the set of string values any return statement could produce.
|
|
56
|
+
*/
|
|
57
|
+
private inferReturnValuesFromFunctionBody;
|
|
47
58
|
/**
|
|
48
59
|
* Extract a raw TsType node from an identifier's type annotation.
|
|
49
60
|
* SWC may wrap it in a `TsTypeAnnotation` node — this unwraps it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression-resolver.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/expression-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAkD,MAAM,WAAW,CAAA;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAK9B,OAAO,CAAC,aAAa,CAA4D;IAGjF,OAAO,CAAC,eAAe,CAAiD;IAIxE,OAAO,CAAC,cAAc,CAAmC;IAIzD,OAAO,CAAC,mBAAmB,CAAmC;IAI9D,OAAO,CAAC,oBAAoB,CAAmC;
|
|
1
|
+
{"version":3,"file":"expression-resolver.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/expression-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAkD,MAAM,WAAW,CAAA;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAiB;IAK9B,OAAO,CAAC,aAAa,CAA4D;IAGjF,OAAO,CAAC,eAAe,CAAiD;IAIxE,OAAO,CAAC,cAAc,CAAmC;IAIzD,OAAO,CAAC,mBAAmB,CAAmC;IAI9D,OAAO,CAAC,oBAAoB,CAAmC;IAM/D,OAAO,CAAC,yBAAyB,CAAmC;IAIpE,OAAO,CAAC,kBAAkB,CAAmC;gBAEhD,KAAK,EAAE,eAAe;IAInC;;OAEG;IACI,gBAAgB,IAAK,IAAI;IAMhC;;;;;;;;;OASG;IACH,yBAAyB,CAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IA2J3C;;;;;;;OAOG;IACH,2BAA2B,CAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAkB7C;;;;;;;;;OASG;IACH,0BAA0B,CAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAqC5C;;;;;;;;OAQG;IACH,OAAO,CAAC,iCAAiC;IA6CzC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAQ7B;;;;OAIG;IACI,oBAAoB,CAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAIlE;;OAEG;IACI,uBAAuB,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAInD;;;;OAIG;IACI,yBAAyB,CAAE,MAAM,EAAE,GAAG,GAAG,MAAM,EAAE;IAQxD;;;OAGG;IACI,iBAAiB,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAQ7D;;;;OAIG;IACI,YAAY,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAQtE;;;;;OAKG;IACH,sBAAsB,CAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAwBxC;;;;;;;OAOG;IACH,kCAAkC,CAAE,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE;IAKrE;;;;;;;OAOG;IACH,8BAA8B,CAAE,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE;IAKjE;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,yCAAyC;IA2NjD,OAAO,CAAC,mCAAmC;IAiH3C;;;;;;OAMG;IACH,OAAO,CAAC,6CAA6C;IAyBrD;;;;;;OAMG;IACH,OAAO,CAAC,kDAAkD;CAwB3D"}
|
package/types/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAgB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAgB,MAAM,YAAY,CAAA;AAMpE;;GAEG;AACH,UAAU,aAAa;IACrB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAqDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,SAAS,CAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,aAAkB,iBAuBzF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for reasoning about context variants of translation keys.
|
|
3
|
+
*
|
|
4
|
+
* A "key accepting context" is a base key that was called with a `context`
|
|
5
|
+
* option in source code (e.g. `t('friend', { context: gender })`). Its
|
|
6
|
+
* variants in the translation file look like `<base><contextSeparator><ctx>`
|
|
7
|
+
* (optionally suffixed with a CLDR plural form).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Checks if an existing key is a context variant of a base key that accepts context.
|
|
11
|
+
* Handles:
|
|
12
|
+
* - Keys suffixed with a CLDR plural form (e.g. `friend_male_one`).
|
|
13
|
+
* - Context values that contain the separator (e.g. `mc_laren`).
|
|
14
|
+
*
|
|
15
|
+
* @param existingKey - The key from the translation file to check
|
|
16
|
+
* @param keysAcceptingContext - Set of base keys that were used with context in source code
|
|
17
|
+
* @param pluralSeparator - The separator used for plural forms (default: '_')
|
|
18
|
+
* @param contextSeparator - The separator used for context variants (default: '_')
|
|
19
|
+
* @returns true if the existing key is a context variant of a key accepting context
|
|
20
|
+
*/
|
|
21
|
+
export declare function isContextVariantOfAcceptingKey(existingKey: string, keysAcceptingContext: ReadonlySet<string>, pluralSeparator: string, contextSeparator: string): boolean;
|
|
22
|
+
//# sourceMappingURL=context-variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-variants.d.ts","sourceRoot":"","sources":["../../src/utils/context-variants.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,EACzC,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAsCT"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared parser for i18next-style nested translation references of the form
|
|
3
|
+
* `$t(key, { options })`.
|
|
4
|
+
*
|
|
5
|
+
* Used in two places:
|
|
6
|
+
* 1. The extractor's AST pass scans source-code keys and default values for
|
|
7
|
+
* nested references and registers the referenced keys (so they show up in
|
|
8
|
+
* output translation files).
|
|
9
|
+
* 2. The translation-manager uses it during `removeUnusedKeys` cleanup so
|
|
10
|
+
* keys that are only referenced from inside a translation value (and thus
|
|
11
|
+
* invisible to the AST pass) are preserved instead of being deleted.
|
|
12
|
+
*/
|
|
13
|
+
export interface NestingConfig {
|
|
14
|
+
nestingPrefix?: string;
|
|
15
|
+
nestingSuffix?: string;
|
|
16
|
+
nestingOptionsSeparator?: string;
|
|
17
|
+
nsSeparator?: string | false | null;
|
|
18
|
+
defaultNS?: string | false;
|
|
19
|
+
}
|
|
20
|
+
export interface NestedReference {
|
|
21
|
+
/** The referenced key (namespace-stripped when a namespace was resolved). */
|
|
22
|
+
key: string;
|
|
23
|
+
/** Resolved namespace for the reference (or defaultNS / undefined). */
|
|
24
|
+
ns: string | false | undefined;
|
|
25
|
+
/** True when the nested options object contains a `count` property. */
|
|
26
|
+
hasCount: boolean;
|
|
27
|
+
/** Static context string, if the nested options contain `context: 'foo'`. */
|
|
28
|
+
context?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Scans a string for `$t(...)` references and returns metadata about each one.
|
|
32
|
+
* The implementation mirrors the behaviour of i18next's Interpolator so that
|
|
33
|
+
* the extractor and translation manager agree on what counts as a reference.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseNestedReferences(text: string, config: NestingConfig): NestedReference[];
|
|
36
|
+
//# sourceMappingURL=nesting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nesting.d.ts","sourceRoot":"","sources":["../../src/utils/nesting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAA;IACnC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAA;IACX,uEAAuE;IACvE,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IAC9B,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAA;IACjB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,eAAe,EAAE,CAoF7F"}
|