i18next-cli 1.56.7 → 1.56.9

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
@@ -32,7 +32,7 @@ const program = new commander.Command();
32
32
  program
33
33
  .name('i18next-cli')
34
34
  .description('A unified, high-performance i18next CLI.')
35
- .version('1.56.7'); // This string is replaced with the actual version at build time by rollup
35
+ .version('1.56.9'); // This string is replaced with the actual version at build time by rollup
36
36
  // new: global config override option
37
37
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
38
38
  program
@@ -165,7 +165,37 @@ class ASTVisitors {
165
165
  if (!node)
166
166
  return;
167
167
  let isNewScope = false;
168
+ let isNewClassScope = false;
168
169
  let paramTemporaries;
170
+ // ENTER CLASS SCOPE for class declarations / expressions and pre-register
171
+ // class field initializers so that later `this.<field>` references inside
172
+ // method bodies can inherit the namespace/keyPrefix from the field.
173
+ if (node.type === 'ClassDeclaration' ||
174
+ node.type === 'ClassExpression' ||
175
+ node.type === 'ClassDecl' ||
176
+ node.type === 'ClassExpr') {
177
+ this.scopeManager.enterClassScope();
178
+ isNewClassScope = true;
179
+ const classBody = Array.isArray(node.body) ? node.body : (node.body?.body ?? []);
180
+ for (const member of classBody) {
181
+ if (!member || typeof member !== 'object')
182
+ continue;
183
+ if (member.type === 'ClassProperty' ||
184
+ member.type === 'PrivateProperty' ||
185
+ member.type === 'PropertyDefinition' ||
186
+ member.type === 'ClassPrivateProperty') {
187
+ let fieldName;
188
+ const key = member.key;
189
+ if (key?.type === 'Identifier')
190
+ fieldName = key.value ?? key.name;
191
+ else if (key?.type === 'PrivateName')
192
+ fieldName = '#' + (key.value ?? key.name ?? key.id?.value ?? key.id?.name);
193
+ if (!fieldName)
194
+ continue;
195
+ this.scopeManager.registerClassField(fieldName, member.value);
196
+ }
197
+ }
198
+ }
169
199
  // ENTER SCOPE for functions
170
200
  // Accept many SWC/TS AST variants for function-like nodes (declarations, expressions, arrow functions)
171
201
  if (node.type === 'Function' ||
@@ -540,6 +570,10 @@ class ASTVisitors {
540
570
  }
541
571
  this.scopeManager.exitScope();
542
572
  }
573
+ // LEAVE CLASS SCOPE for classes
574
+ if (isNewClassScope) {
575
+ this.scopeManager.exitClassScope();
576
+ }
543
577
  }
544
578
  /**
545
579
  * If `node` is a call like `ARRAY.map(param => ...)` where ARRAY is a known
@@ -749,11 +749,23 @@ function buildNewTranslationsForNs(nsKeys, existingTranslations, config, locale,
749
749
  }
750
750
  }
751
751
  else {
752
+ // A key is a synthesized plural variant only when the extractor flagged it
753
+ // with `hasCount` AND its suffix matches a CLDR plural form. Relying purely
754
+ // on the presence of the separator misclassifies regular keys that happen to
755
+ // contain `_` (e.g. `abc_123`) — see issue #250. Context variants are caught
756
+ // by `isDerivedDefault` below (their synthesized default mirrors the base key).
757
+ const isVariantKey = (() => {
758
+ if (!hasCount)
759
+ return false;
760
+ const parts = key.split(pluralSeparator);
761
+ if (parts.length < 2)
762
+ return false;
763
+ return pluralForms.includes(parts[parts.length - 1]);
764
+ })();
752
765
  // Existing value exists - decide whether to preserve, sync primary, or clear other locales when requested
753
766
  if (locale === primaryLanguage && syncPrimaryWithDefaults) {
754
- // If this key looks like a plural/context variant and the default
755
- // wasn't explicitly provided in source code, preserve the existing value.
756
- const isVariantKey = key.includes(pluralSeparator) || key.includes(contextSeparator);
767
+ // If this key is a plural/context variant and the default wasn't explicitly
768
+ // provided in source code, preserve the existing value.
757
769
  if (isVariantKey && !explicitDefault) {
758
770
  valueToSet = existingValue;
759
771
  }
@@ -766,7 +778,6 @@ function buildNewTranslationsForNs(nsKeys, existingTranslations, config, locale,
766
778
  }
767
779
  else {
768
780
  // Non-primary locale behavior
769
- const isVariantKey = key.includes(pluralSeparator) || key.includes(contextSeparator);
770
781
  // A plural variant whose category exists in the current locale but not in the
771
782
  // primary language (e.g. French `_many` vs English `one`/`other`) will always be
772
783
  // absent from the primary file by CLDR design. Treat that absence as expected —
@@ -6,6 +6,11 @@ class ScopeManager {
6
6
  scopeStack = [];
7
7
  config;
8
8
  scope = new Map();
9
+ // Stack of class scopes; each entry maps a class field name (e.g. `myField`
10
+ // or `#privateField`) to the ScopeInfo derived from its initializer. Used to
11
+ // resolve `const { t } = this.field` and `const { t } = this.field()` patterns
12
+ // inside class methods.
13
+ thisFieldStack = [];
9
14
  // Track simple local constants with string literal values to resolve identifier args
10
15
  simpleConstants = new Map();
11
16
  // Track simple local constant objects with string literal property values
@@ -63,6 +68,49 @@ class ScopeManager {
63
68
  this.scope = new Map();
64
69
  this.simpleConstants.clear();
65
70
  this.simpleConstantObjects.clear();
71
+ this.thisFieldStack = [];
72
+ }
73
+ /**
74
+ * Pushes a new class scope used for tracking class field → ScopeInfo
75
+ * mappings. Should be called when entering a ClassDeclaration or
76
+ * ClassExpression.
77
+ */
78
+ enterClassScope() {
79
+ this.thisFieldStack.push(new Map());
80
+ }
81
+ /**
82
+ * Pops the current class scope. Should be called when leaving a
83
+ * ClassDeclaration or ClassExpression.
84
+ */
85
+ exitClassScope() {
86
+ this.thisFieldStack.pop();
87
+ }
88
+ /**
89
+ * Records a class field's ScopeInfo so that later `this.<field>` or
90
+ * `this.<field>()` accesses inside the class can inherit the namespace
91
+ * and keyPrefix from its initializer.
92
+ *
93
+ * @param fieldName - Field name (private fields are prefixed with `#`)
94
+ * @param info - Scope information derived from the field's initializer
95
+ */
96
+ setThisField(fieldName, info) {
97
+ if (this.thisFieldStack.length > 0) {
98
+ this.thisFieldStack[this.thisFieldStack.length - 1].set(fieldName, info);
99
+ }
100
+ }
101
+ /**
102
+ * Looks up a class field's ScopeInfo from the innermost class scope outward.
103
+ *
104
+ * @param fieldName - Field name (private fields are prefixed with `#`)
105
+ * @returns Scope information if found, undefined otherwise
106
+ */
107
+ getThisField(fieldName) {
108
+ for (let i = this.thisFieldStack.length - 1; i >= 0; i--) {
109
+ if (this.thisFieldStack[i].has(fieldName)) {
110
+ return this.thisFieldStack[i].get(fieldName);
111
+ }
112
+ }
113
+ return undefined;
66
114
  }
67
115
  /**
68
116
  * Enters a new variable scope by pushing a new scope map onto the stack.
@@ -219,6 +267,17 @@ class ScopeManager {
219
267
  }
220
268
  // continue processing; still may be a useTranslation/getFixedT call below
221
269
  }
270
+ // Handle: const { t } = this.#field OR const { t } = this.#field()
271
+ // Resolve the source `this.<field>` to its previously-registered ScopeInfo
272
+ // and propagate it onto the destructured variables.
273
+ const thisFieldName = ScopeManager.extractThisFieldName(init);
274
+ if (thisFieldName !== undefined) {
275
+ const sourceScope = this.getThisField(thisFieldName);
276
+ if (sourceScope) {
277
+ this.attachScopeToDestructuredVars(node, sourceScope);
278
+ return;
279
+ }
280
+ }
222
281
  // Determine the actual call expression, looking inside AwaitExpressions.
223
282
  const callExpr = init.type === 'AwaitExpression' && init.argument.type === 'CallExpression'
224
283
  ? init.argument
@@ -545,6 +604,165 @@ class ScopeManager {
545
604
  this.setVarInScope(targetVarName, { defaultNs: finalNs, keyPrefix: finalKeyPrefix });
546
605
  }
547
606
  }
607
+ /**
608
+ * Returns the field name being referenced when an expression takes the form
609
+ * `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
610
+ * prefixes private fields with `#`.
611
+ *
612
+ * Returns undefined if the expression is not such an access.
613
+ */
614
+ static extractThisFieldName(init) {
615
+ let memberExpr;
616
+ if (init.type === 'MemberExpression') {
617
+ memberExpr = init;
618
+ }
619
+ else if (init.type === 'CallExpression' && init.callee.type === 'MemberExpression') {
620
+ memberExpr = init.callee;
621
+ }
622
+ if (!memberExpr)
623
+ return undefined;
624
+ if (memberExpr.object.type !== 'ThisExpression')
625
+ return undefined;
626
+ const prop = memberExpr.property;
627
+ if (prop?.type === 'Identifier')
628
+ return prop.value;
629
+ if (prop?.type === 'PrivateName')
630
+ return '#' + prop.value;
631
+ return undefined;
632
+ }
633
+ /**
634
+ * Attaches the given ScopeInfo to all destructured variables of a variable
635
+ * declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
636
+ */
637
+ attachScopeToDestructuredVars(node, info) {
638
+ if (node.id.type === 'ObjectPattern') {
639
+ for (const prop of node.id.properties) {
640
+ if (prop.type === 'AssignmentPatternProperty' && prop.key.type === 'Identifier') {
641
+ this.setVarInScope(prop.key.value, info);
642
+ }
643
+ if (prop.type === 'KeyValuePatternProperty' && prop.value.type === 'Identifier') {
644
+ this.setVarInScope(prop.value.value, info);
645
+ // Also store under the pattern key name so legacy comment-scope
646
+ // lookups by the original property name continue to work.
647
+ if (prop.key.type === 'Identifier' && (prop.key.value === 't' || prop.key.value === 'getFixedT')) {
648
+ this.scope.set(prop.value.value, { defaultNs: info.defaultNs, keyPrefix: info.keyPrefix });
649
+ }
650
+ }
651
+ }
652
+ }
653
+ else if (node.id.type === 'Identifier') {
654
+ this.setVarInScope(node.id.value, info);
655
+ }
656
+ else if (node.id.type === 'ArrayPattern') {
657
+ const firstElement = node.id.elements[0];
658
+ if (firstElement?.type === 'Identifier') {
659
+ this.setVarInScope(firstElement.value, info);
660
+ }
661
+ }
662
+ }
663
+ /**
664
+ * Registers a class field's initializer with the current class scope so that
665
+ * later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
666
+ * inside the class body inherit the namespace and keyPrefix from the field
667
+ * initializer.
668
+ *
669
+ * Recognizes the same useTranslation-like patterns supported on regular
670
+ * variable declarations (configured via `useTranslationNames`).
671
+ *
672
+ * @param fieldName - Field name (private fields are prefixed with `#`)
673
+ * @param value - The field initializer expression
674
+ */
675
+ registerClassField(fieldName, value) {
676
+ if (!value)
677
+ return;
678
+ if (this.thisFieldStack.length === 0)
679
+ return;
680
+ const callExpr = value.type === 'AwaitExpression' && value.argument.type === 'CallExpression'
681
+ ? value.argument
682
+ : value.type === 'CallExpression'
683
+ ? value
684
+ : null;
685
+ if (!callExpr)
686
+ return;
687
+ const callee = callExpr.callee;
688
+ if (callee.type !== 'Identifier')
689
+ return;
690
+ const hookConfig = this.getUseTranslationConfig(callee.value);
691
+ if (!hookConfig)
692
+ return;
693
+ const info = this.computeScopeInfoFromHookCall(callExpr, hookConfig);
694
+ if (info.defaultNs || info.keyPrefix) {
695
+ this.setThisField(fieldName, info);
696
+ }
697
+ }
698
+ /**
699
+ * Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
700
+ * given a hook configuration that describes argument positions. Mirrors the
701
+ * extraction performed by handleUseTranslationDeclarator without attaching
702
+ * the result to any variable.
703
+ */
704
+ computeScopeInfoFromHookCall(callExpr, hookConfig) {
705
+ const nsArgIndex = hookConfig.nsArg ?? 0;
706
+ const kpArgIndex = hookConfig.keyPrefixArg ?? 1;
707
+ let defaultNs;
708
+ let keyPrefix;
709
+ const first = callExpr.arguments?.[0]?.expression;
710
+ const second = callExpr.arguments?.[1]?.expression;
711
+ const third = callExpr.arguments?.[2]?.expression;
712
+ const looksLikeLanguage = (s) => /^[a-z]{2,3}([-_][A-Za-z0-9-]+)?$/i.test(s);
713
+ const isBuiltInLngNsForm = hookConfig.name === 'useTranslation' &&
714
+ first?.type === 'StringLiteral' &&
715
+ second?.type === 'StringLiteral' &&
716
+ looksLikeLanguage(first.value);
717
+ let kpArg;
718
+ if (isBuiltInLngNsForm) {
719
+ defaultNs = second.value;
720
+ kpArg = third;
721
+ }
722
+ else {
723
+ if (nsArgIndex !== -1) {
724
+ const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
725
+ if (nsNode?.type === 'StringLiteral') {
726
+ defaultNs = nsNode.value;
727
+ }
728
+ else if (nsNode?.type === 'Identifier') {
729
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
730
+ }
731
+ else if (nsNode?.type === 'MemberExpression') {
732
+ defaultNs = this.resolveSimpleMemberExpression(nsNode);
733
+ }
734
+ else if (nsNode?.type === 'ArrayExpression') {
735
+ const firstEl = nsNode.elements[0]?.expression;
736
+ if (firstEl?.type === 'StringLiteral') {
737
+ defaultNs = firstEl.value;
738
+ }
739
+ else if (firstEl?.type === 'Identifier') {
740
+ defaultNs = this.resolveSimpleStringIdentifier(firstEl.value);
741
+ }
742
+ }
743
+ }
744
+ kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
745
+ }
746
+ if (kpArg?.type === 'ObjectExpression') {
747
+ const kp = astUtils.getObjectPropValue(kpArg, 'keyPrefix', this.resolveSimpleStringIdentifier.bind(this));
748
+ if (typeof kp === 'string') {
749
+ keyPrefix = kp;
750
+ }
751
+ }
752
+ else if (kpArg?.type === 'StringLiteral') {
753
+ keyPrefix = kpArg.value;
754
+ }
755
+ else if (kpArg?.type === 'Identifier') {
756
+ keyPrefix = this.resolveSimpleStringIdentifier(kpArg.value);
757
+ }
758
+ else if (kpArg?.type === 'TemplateLiteral') {
759
+ const tpl = kpArg;
760
+ if ((tpl.expressions || []).length === 0) {
761
+ keyPrefix = tpl.quasis?.[0]?.cooked ?? undefined;
762
+ }
763
+ }
764
+ return { defaultNs, keyPrefix };
765
+ }
548
766
  }
549
767
 
550
768
  exports.ScopeManager = ScopeManager;
package/dist/esm/cli.js CHANGED
@@ -30,7 +30,7 @@ const program = new Command();
30
30
  program
31
31
  .name('i18next-cli')
32
32
  .description('A unified, high-performance i18next CLI.')
33
- .version('1.56.7'); // This string is replaced with the actual version at build time by rollup
33
+ .version('1.56.9'); // This string is replaced with the actual version at build time by rollup
34
34
  // new: global config override option
35
35
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
36
36
  program
@@ -163,7 +163,37 @@ class ASTVisitors {
163
163
  if (!node)
164
164
  return;
165
165
  let isNewScope = false;
166
+ let isNewClassScope = false;
166
167
  let paramTemporaries;
168
+ // ENTER CLASS SCOPE for class declarations / expressions and pre-register
169
+ // class field initializers so that later `this.<field>` references inside
170
+ // method bodies can inherit the namespace/keyPrefix from the field.
171
+ if (node.type === 'ClassDeclaration' ||
172
+ node.type === 'ClassExpression' ||
173
+ node.type === 'ClassDecl' ||
174
+ node.type === 'ClassExpr') {
175
+ this.scopeManager.enterClassScope();
176
+ isNewClassScope = true;
177
+ const classBody = Array.isArray(node.body) ? node.body : (node.body?.body ?? []);
178
+ for (const member of classBody) {
179
+ if (!member || typeof member !== 'object')
180
+ continue;
181
+ if (member.type === 'ClassProperty' ||
182
+ member.type === 'PrivateProperty' ||
183
+ member.type === 'PropertyDefinition' ||
184
+ member.type === 'ClassPrivateProperty') {
185
+ let fieldName;
186
+ const key = member.key;
187
+ if (key?.type === 'Identifier')
188
+ fieldName = key.value ?? key.name;
189
+ else if (key?.type === 'PrivateName')
190
+ fieldName = '#' + (key.value ?? key.name ?? key.id?.value ?? key.id?.name);
191
+ if (!fieldName)
192
+ continue;
193
+ this.scopeManager.registerClassField(fieldName, member.value);
194
+ }
195
+ }
196
+ }
167
197
  // ENTER SCOPE for functions
168
198
  // Accept many SWC/TS AST variants for function-like nodes (declarations, expressions, arrow functions)
169
199
  if (node.type === 'Function' ||
@@ -538,6 +568,10 @@ class ASTVisitors {
538
568
  }
539
569
  this.scopeManager.exitScope();
540
570
  }
571
+ // LEAVE CLASS SCOPE for classes
572
+ if (isNewClassScope) {
573
+ this.scopeManager.exitClassScope();
574
+ }
541
575
  }
542
576
  /**
543
577
  * If `node` is a call like `ARRAY.map(param => ...)` where ARRAY is a known
@@ -747,11 +747,23 @@ function buildNewTranslationsForNs(nsKeys, existingTranslations, config, locale,
747
747
  }
748
748
  }
749
749
  else {
750
+ // A key is a synthesized plural variant only when the extractor flagged it
751
+ // with `hasCount` AND its suffix matches a CLDR plural form. Relying purely
752
+ // on the presence of the separator misclassifies regular keys that happen to
753
+ // contain `_` (e.g. `abc_123`) — see issue #250. Context variants are caught
754
+ // by `isDerivedDefault` below (their synthesized default mirrors the base key).
755
+ const isVariantKey = (() => {
756
+ if (!hasCount)
757
+ return false;
758
+ const parts = key.split(pluralSeparator);
759
+ if (parts.length < 2)
760
+ return false;
761
+ return pluralForms.includes(parts[parts.length - 1]);
762
+ })();
750
763
  // Existing value exists - decide whether to preserve, sync primary, or clear other locales when requested
751
764
  if (locale === primaryLanguage && syncPrimaryWithDefaults) {
752
- // If this key looks like a plural/context variant and the default
753
- // wasn't explicitly provided in source code, preserve the existing value.
754
- const isVariantKey = key.includes(pluralSeparator) || key.includes(contextSeparator);
765
+ // If this key is a plural/context variant and the default wasn't explicitly
766
+ // provided in source code, preserve the existing value.
755
767
  if (isVariantKey && !explicitDefault) {
756
768
  valueToSet = existingValue;
757
769
  }
@@ -764,7 +776,6 @@ function buildNewTranslationsForNs(nsKeys, existingTranslations, config, locale,
764
776
  }
765
777
  else {
766
778
  // Non-primary locale behavior
767
- const isVariantKey = key.includes(pluralSeparator) || key.includes(contextSeparator);
768
779
  // A plural variant whose category exists in the current locale but not in the
769
780
  // primary language (e.g. French `_many` vs English `one`/`other`) will always be
770
781
  // absent from the primary file by CLDR design. Treat that absence as expected —
@@ -4,6 +4,11 @@ class ScopeManager {
4
4
  scopeStack = [];
5
5
  config;
6
6
  scope = new Map();
7
+ // Stack of class scopes; each entry maps a class field name (e.g. `myField`
8
+ // or `#privateField`) to the ScopeInfo derived from its initializer. Used to
9
+ // resolve `const { t } = this.field` and `const { t } = this.field()` patterns
10
+ // inside class methods.
11
+ thisFieldStack = [];
7
12
  // Track simple local constants with string literal values to resolve identifier args
8
13
  simpleConstants = new Map();
9
14
  // Track simple local constant objects with string literal property values
@@ -61,6 +66,49 @@ class ScopeManager {
61
66
  this.scope = new Map();
62
67
  this.simpleConstants.clear();
63
68
  this.simpleConstantObjects.clear();
69
+ this.thisFieldStack = [];
70
+ }
71
+ /**
72
+ * Pushes a new class scope used for tracking class field → ScopeInfo
73
+ * mappings. Should be called when entering a ClassDeclaration or
74
+ * ClassExpression.
75
+ */
76
+ enterClassScope() {
77
+ this.thisFieldStack.push(new Map());
78
+ }
79
+ /**
80
+ * Pops the current class scope. Should be called when leaving a
81
+ * ClassDeclaration or ClassExpression.
82
+ */
83
+ exitClassScope() {
84
+ this.thisFieldStack.pop();
85
+ }
86
+ /**
87
+ * Records a class field's ScopeInfo so that later `this.<field>` or
88
+ * `this.<field>()` accesses inside the class can inherit the namespace
89
+ * and keyPrefix from its initializer.
90
+ *
91
+ * @param fieldName - Field name (private fields are prefixed with `#`)
92
+ * @param info - Scope information derived from the field's initializer
93
+ */
94
+ setThisField(fieldName, info) {
95
+ if (this.thisFieldStack.length > 0) {
96
+ this.thisFieldStack[this.thisFieldStack.length - 1].set(fieldName, info);
97
+ }
98
+ }
99
+ /**
100
+ * Looks up a class field's ScopeInfo from the innermost class scope outward.
101
+ *
102
+ * @param fieldName - Field name (private fields are prefixed with `#`)
103
+ * @returns Scope information if found, undefined otherwise
104
+ */
105
+ getThisField(fieldName) {
106
+ for (let i = this.thisFieldStack.length - 1; i >= 0; i--) {
107
+ if (this.thisFieldStack[i].has(fieldName)) {
108
+ return this.thisFieldStack[i].get(fieldName);
109
+ }
110
+ }
111
+ return undefined;
64
112
  }
65
113
  /**
66
114
  * Enters a new variable scope by pushing a new scope map onto the stack.
@@ -217,6 +265,17 @@ class ScopeManager {
217
265
  }
218
266
  // continue processing; still may be a useTranslation/getFixedT call below
219
267
  }
268
+ // Handle: const { t } = this.#field OR const { t } = this.#field()
269
+ // Resolve the source `this.<field>` to its previously-registered ScopeInfo
270
+ // and propagate it onto the destructured variables.
271
+ const thisFieldName = ScopeManager.extractThisFieldName(init);
272
+ if (thisFieldName !== undefined) {
273
+ const sourceScope = this.getThisField(thisFieldName);
274
+ if (sourceScope) {
275
+ this.attachScopeToDestructuredVars(node, sourceScope);
276
+ return;
277
+ }
278
+ }
220
279
  // Determine the actual call expression, looking inside AwaitExpressions.
221
280
  const callExpr = init.type === 'AwaitExpression' && init.argument.type === 'CallExpression'
222
281
  ? init.argument
@@ -543,6 +602,165 @@ class ScopeManager {
543
602
  this.setVarInScope(targetVarName, { defaultNs: finalNs, keyPrefix: finalKeyPrefix });
544
603
  }
545
604
  }
605
+ /**
606
+ * Returns the field name being referenced when an expression takes the form
607
+ * `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
608
+ * prefixes private fields with `#`.
609
+ *
610
+ * Returns undefined if the expression is not such an access.
611
+ */
612
+ static extractThisFieldName(init) {
613
+ let memberExpr;
614
+ if (init.type === 'MemberExpression') {
615
+ memberExpr = init;
616
+ }
617
+ else if (init.type === 'CallExpression' && init.callee.type === 'MemberExpression') {
618
+ memberExpr = init.callee;
619
+ }
620
+ if (!memberExpr)
621
+ return undefined;
622
+ if (memberExpr.object.type !== 'ThisExpression')
623
+ return undefined;
624
+ const prop = memberExpr.property;
625
+ if (prop?.type === 'Identifier')
626
+ return prop.value;
627
+ if (prop?.type === 'PrivateName')
628
+ return '#' + prop.value;
629
+ return undefined;
630
+ }
631
+ /**
632
+ * Attaches the given ScopeInfo to all destructured variables of a variable
633
+ * declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
634
+ */
635
+ attachScopeToDestructuredVars(node, info) {
636
+ if (node.id.type === 'ObjectPattern') {
637
+ for (const prop of node.id.properties) {
638
+ if (prop.type === 'AssignmentPatternProperty' && prop.key.type === 'Identifier') {
639
+ this.setVarInScope(prop.key.value, info);
640
+ }
641
+ if (prop.type === 'KeyValuePatternProperty' && prop.value.type === 'Identifier') {
642
+ this.setVarInScope(prop.value.value, info);
643
+ // Also store under the pattern key name so legacy comment-scope
644
+ // lookups by the original property name continue to work.
645
+ if (prop.key.type === 'Identifier' && (prop.key.value === 't' || prop.key.value === 'getFixedT')) {
646
+ this.scope.set(prop.value.value, { defaultNs: info.defaultNs, keyPrefix: info.keyPrefix });
647
+ }
648
+ }
649
+ }
650
+ }
651
+ else if (node.id.type === 'Identifier') {
652
+ this.setVarInScope(node.id.value, info);
653
+ }
654
+ else if (node.id.type === 'ArrayPattern') {
655
+ const firstElement = node.id.elements[0];
656
+ if (firstElement?.type === 'Identifier') {
657
+ this.setVarInScope(firstElement.value, info);
658
+ }
659
+ }
660
+ }
661
+ /**
662
+ * Registers a class field's initializer with the current class scope so that
663
+ * later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
664
+ * inside the class body inherit the namespace and keyPrefix from the field
665
+ * initializer.
666
+ *
667
+ * Recognizes the same useTranslation-like patterns supported on regular
668
+ * variable declarations (configured via `useTranslationNames`).
669
+ *
670
+ * @param fieldName - Field name (private fields are prefixed with `#`)
671
+ * @param value - The field initializer expression
672
+ */
673
+ registerClassField(fieldName, value) {
674
+ if (!value)
675
+ return;
676
+ if (this.thisFieldStack.length === 0)
677
+ return;
678
+ const callExpr = value.type === 'AwaitExpression' && value.argument.type === 'CallExpression'
679
+ ? value.argument
680
+ : value.type === 'CallExpression'
681
+ ? value
682
+ : null;
683
+ if (!callExpr)
684
+ return;
685
+ const callee = callExpr.callee;
686
+ if (callee.type !== 'Identifier')
687
+ return;
688
+ const hookConfig = this.getUseTranslationConfig(callee.value);
689
+ if (!hookConfig)
690
+ return;
691
+ const info = this.computeScopeInfoFromHookCall(callExpr, hookConfig);
692
+ if (info.defaultNs || info.keyPrefix) {
693
+ this.setThisField(fieldName, info);
694
+ }
695
+ }
696
+ /**
697
+ * Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
698
+ * given a hook configuration that describes argument positions. Mirrors the
699
+ * extraction performed by handleUseTranslationDeclarator without attaching
700
+ * the result to any variable.
701
+ */
702
+ computeScopeInfoFromHookCall(callExpr, hookConfig) {
703
+ const nsArgIndex = hookConfig.nsArg ?? 0;
704
+ const kpArgIndex = hookConfig.keyPrefixArg ?? 1;
705
+ let defaultNs;
706
+ let keyPrefix;
707
+ const first = callExpr.arguments?.[0]?.expression;
708
+ const second = callExpr.arguments?.[1]?.expression;
709
+ const third = callExpr.arguments?.[2]?.expression;
710
+ const looksLikeLanguage = (s) => /^[a-z]{2,3}([-_][A-Za-z0-9-]+)?$/i.test(s);
711
+ const isBuiltInLngNsForm = hookConfig.name === 'useTranslation' &&
712
+ first?.type === 'StringLiteral' &&
713
+ second?.type === 'StringLiteral' &&
714
+ looksLikeLanguage(first.value);
715
+ let kpArg;
716
+ if (isBuiltInLngNsForm) {
717
+ defaultNs = second.value;
718
+ kpArg = third;
719
+ }
720
+ else {
721
+ if (nsArgIndex !== -1) {
722
+ const nsNode = callExpr.arguments?.[nsArgIndex]?.expression;
723
+ if (nsNode?.type === 'StringLiteral') {
724
+ defaultNs = nsNode.value;
725
+ }
726
+ else if (nsNode?.type === 'Identifier') {
727
+ defaultNs = this.resolveSimpleStringIdentifier(nsNode.value);
728
+ }
729
+ else if (nsNode?.type === 'MemberExpression') {
730
+ defaultNs = this.resolveSimpleMemberExpression(nsNode);
731
+ }
732
+ else if (nsNode?.type === 'ArrayExpression') {
733
+ const firstEl = nsNode.elements[0]?.expression;
734
+ if (firstEl?.type === 'StringLiteral') {
735
+ defaultNs = firstEl.value;
736
+ }
737
+ else if (firstEl?.type === 'Identifier') {
738
+ defaultNs = this.resolveSimpleStringIdentifier(firstEl.value);
739
+ }
740
+ }
741
+ }
742
+ kpArg = kpArgIndex === -1 ? undefined : callExpr.arguments?.[kpArgIndex]?.expression;
743
+ }
744
+ if (kpArg?.type === 'ObjectExpression') {
745
+ const kp = getObjectPropValue(kpArg, 'keyPrefix', this.resolveSimpleStringIdentifier.bind(this));
746
+ if (typeof kp === 'string') {
747
+ keyPrefix = kp;
748
+ }
749
+ }
750
+ else if (kpArg?.type === 'StringLiteral') {
751
+ keyPrefix = kpArg.value;
752
+ }
753
+ else if (kpArg?.type === 'Identifier') {
754
+ keyPrefix = this.resolveSimpleStringIdentifier(kpArg.value);
755
+ }
756
+ else if (kpArg?.type === 'TemplateLiteral') {
757
+ const tpl = kpArg;
758
+ if ((tpl.expressions || []).length === 0) {
759
+ keyPrefix = tpl.quasis?.[0]?.cooked ?? undefined;
760
+ }
761
+ }
762
+ return { defaultNs, keyPrefix };
763
+ }
546
764
  }
547
765
 
548
766
  export { ScopeManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.56.7",
3
+ "version": "1.56.9",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -85,7 +85,7 @@
85
85
  "minimatch": "^10.2.5",
86
86
  "ora": "^9.3.0",
87
87
  "react": "^19.2.5",
88
- "react-i18next": "^17.0.4",
88
+ "react-i18next": "^17.0.6",
89
89
  "yaml": "^2.8.3"
90
90
  }
91
91
  }
@@ -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;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"}
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;IAyZZ;;;;;;;;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"}
@@ -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;AA8iC9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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;AAujC9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
@@ -1,9 +1,10 @@
1
- import type { VariableDeclarator } from '@swc/core';
1
+ import type { Expression, VariableDeclarator } from '@swc/core';
2
2
  import type { ScopeInfo, I18nextToolkitConfig } from '../../types.js';
3
3
  export declare class ScopeManager {
4
4
  private scopeStack;
5
5
  private config;
6
6
  private scope;
7
+ private thisFieldStack;
7
8
  private simpleConstants;
8
9
  private simpleConstantObjects;
9
10
  private sharedConstants;
@@ -27,6 +28,33 @@ export declare class ScopeManager {
27
28
  * leak between files.
28
29
  */
29
30
  reset(): void;
31
+ /**
32
+ * Pushes a new class scope used for tracking class field → ScopeInfo
33
+ * mappings. Should be called when entering a ClassDeclaration or
34
+ * ClassExpression.
35
+ */
36
+ enterClassScope(): void;
37
+ /**
38
+ * Pops the current class scope. Should be called when leaving a
39
+ * ClassDeclaration or ClassExpression.
40
+ */
41
+ exitClassScope(): void;
42
+ /**
43
+ * Records a class field's ScopeInfo so that later `this.<field>` or
44
+ * `this.<field>()` accesses inside the class can inherit the namespace
45
+ * and keyPrefix from its initializer.
46
+ *
47
+ * @param fieldName - Field name (private fields are prefixed with `#`)
48
+ * @param info - Scope information derived from the field's initializer
49
+ */
50
+ setThisField(fieldName: string, info: ScopeInfo): void;
51
+ /**
52
+ * Looks up a class field's ScopeInfo from the innermost class scope outward.
53
+ *
54
+ * @param fieldName - Field name (private fields are prefixed with `#`)
55
+ * @returns Scope information if found, undefined otherwise
56
+ */
57
+ getThisField(fieldName: string): ScopeInfo | undefined;
30
58
  /**
31
59
  * Enters a new variable scope by pushing a new scope map onto the stack.
32
60
  * Used when entering functions to isolate variable declarations.
@@ -131,5 +159,38 @@ export declare class ScopeManager {
131
159
  * resulting scope to the newly declared variable.
132
160
  */
133
161
  private handleGetFixedTFromVariableDeclarator;
162
+ /**
163
+ * Returns the field name being referenced when an expression takes the form
164
+ * `this.<field>` or `this.<field>()`. Strips the call wrapper if present and
165
+ * prefixes private fields with `#`.
166
+ *
167
+ * Returns undefined if the expression is not such an access.
168
+ */
169
+ private static extractThisFieldName;
170
+ /**
171
+ * Attaches the given ScopeInfo to all destructured variables of a variable
172
+ * declarator (`const { t } = ...`, `const [t] = ...`, or `const t = ...`).
173
+ */
174
+ private attachScopeToDestructuredVars;
175
+ /**
176
+ * Registers a class field's initializer with the current class scope so that
177
+ * later `const { t } = this.<field>` or `const { t } = this.<field>()` calls
178
+ * inside the class body inherit the namespace and keyPrefix from the field
179
+ * initializer.
180
+ *
181
+ * Recognizes the same useTranslation-like patterns supported on regular
182
+ * variable declarations (configured via `useTranslationNames`).
183
+ *
184
+ * @param fieldName - Field name (private fields are prefixed with `#`)
185
+ * @param value - The field initializer expression
186
+ */
187
+ registerClassField(fieldName: string, value: Expression | null | undefined): void;
188
+ /**
189
+ * Computes ScopeInfo (defaultNs, keyPrefix) for a useTranslation-style call
190
+ * given a hook configuration that describes argument positions. Mirrors the
191
+ * extraction performed by handleUseTranslationDeclarator without attaching
192
+ * the result to any variable.
193
+ */
194
+ private computeScopeInfoFromHookCall;
134
195
  }
135
196
  //# sourceMappingURL=scope-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,kBAAkB,EAMnB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAG/F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;IAGlF,OAAO,CAAC,eAAe,CAAiC;IAGxD,OAAO,CAAC,qBAAqB,CAAiD;IAI9E,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,qBAAqB,CAAiD;gBAEjE,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,+BAA+B;IAgB9C;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAOrB;;;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;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAqBrC;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IA0FzD;;;;;;;;OAQG;IACH,OAAO,CAAC,+BAA+B;IA0GvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAmFtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;IAiBjC;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;;;;;;OASG;IACH,OAAO,CAAC,qCAAqC;CAoB9C"}
1
+ {"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,kBAAkB,EAMnB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAG/F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;IAMlF,OAAO,CAAC,cAAc,CAAoC;IAG1D,OAAO,CAAC,eAAe,CAAiC;IAGxD,OAAO,CAAC,qBAAqB,CAAiD;IAI9E,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,qBAAqB,CAAiD;gBAEjE,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,+BAA+B;IAgB9C;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAQrB;;;;OAIG;IACH,eAAe,IAAK,IAAI;IAIxB;;;OAGG;IACH,cAAc,IAAK,IAAI;IAIvB;;;;;;;OAOG;IACH,YAAY,CAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAMvD;;;;;OAKG;IACH,YAAY,CAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IASvD;;;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;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAqBrC;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAsGzD;;;;;;;;OAQG;IACH,OAAO,CAAC,+BAA+B;IA0GvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAmFtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;IAiBjC;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;;;;;;OASG;IACH,OAAO,CAAC,qCAAqC;IAqB7C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAgBnC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAyBrC;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAwBlF;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;CA+DrC"}