@better-i18n/cli 0.1.8 → 0.2.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.
Files changed (142) hide show
  1. package/dist/analyzer/dynamic-matcher.d.ts +53 -0
  2. package/dist/analyzer/dynamic-matcher.d.ts.map +1 -0
  3. package/dist/analyzer/dynamic-matcher.js +93 -0
  4. package/dist/analyzer/dynamic-matcher.js.map +1 -0
  5. package/dist/analyzer/index.d.ts +13 -4
  6. package/dist/analyzer/index.d.ts.map +1 -1
  7. package/dist/analyzer/index.js +165 -22
  8. package/dist/analyzer/index.js.map +1 -1
  9. package/dist/analyzer/rules/data-structure.d.ts +13 -0
  10. package/dist/analyzer/rules/data-structure.d.ts.map +1 -0
  11. package/dist/analyzer/rules/data-structure.js +264 -0
  12. package/dist/analyzer/rules/data-structure.js.map +1 -0
  13. package/dist/analyzer/rules/index.d.ts +10 -7
  14. package/dist/analyzer/rules/index.d.ts.map +1 -1
  15. package/dist/analyzer/rules/index.js +10 -7
  16. package/dist/analyzer/rules/index.js.map +1 -1
  17. package/dist/analyzer/rules/jsx-text.js +1 -1
  18. package/dist/analyzer/rules/jsx-text.js.map +1 -1
  19. package/dist/analyzer/rules/translation-function.d.ts.map +1 -1
  20. package/dist/analyzer/rules/translation-function.js +94 -6
  21. package/dist/analyzer/rules/translation-function.js.map +1 -1
  22. package/dist/analyzer/types.d.ts +28 -3
  23. package/dist/analyzer/types.d.ts.map +1 -1
  24. package/dist/commands/check.d.ts +14 -0
  25. package/dist/commands/check.d.ts.map +1 -0
  26. package/dist/commands/check.js +70 -0
  27. package/dist/commands/check.js.map +1 -0
  28. package/dist/commands/doctor.d.ts +20 -0
  29. package/dist/commands/doctor.d.ts.map +1 -0
  30. package/dist/commands/doctor.js +77 -0
  31. package/dist/commands/doctor.js.map +1 -0
  32. package/dist/commands/sync.d.ts +1 -0
  33. package/dist/commands/sync.d.ts.map +1 -1
  34. package/dist/commands/sync.js +158 -272
  35. package/dist/commands/sync.js.map +1 -1
  36. package/dist/context/detector.js +1 -1
  37. package/dist/context/detector.js.map +1 -1
  38. package/dist/context/oidc.d.ts +33 -0
  39. package/dist/context/oidc.d.ts.map +1 -0
  40. package/dist/context/oidc.js +63 -0
  41. package/dist/context/oidc.js.map +1 -0
  42. package/dist/doctor/index.d.ts +65 -0
  43. package/dist/doctor/index.d.ts.map +1 -0
  44. package/dist/doctor/index.js +252 -0
  45. package/dist/doctor/index.js.map +1 -0
  46. package/dist/doctor/project-discovery.d.ts +37 -0
  47. package/dist/doctor/project-discovery.d.ts.map +1 -0
  48. package/dist/doctor/project-discovery.js +140 -0
  49. package/dist/doctor/project-discovery.js.map +1 -0
  50. package/dist/doctor/score.d.ts +41 -0
  51. package/dist/doctor/score.d.ts.map +1 -0
  52. package/dist/doctor/score.js +107 -0
  53. package/dist/doctor/score.js.map +1 -0
  54. package/dist/index.js +35 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/reporters/doctor-eslint.d.ts +17 -0
  57. package/dist/reporters/doctor-eslint.d.ts.map +1 -0
  58. package/dist/reporters/doctor-eslint.js +139 -0
  59. package/dist/reporters/doctor-eslint.js.map +1 -0
  60. package/dist/reporters/doctor-json.d.ts +12 -0
  61. package/dist/reporters/doctor-json.d.ts.map +1 -0
  62. package/dist/reporters/doctor-json.js +21 -0
  63. package/dist/reporters/doctor-json.js.map +1 -0
  64. package/dist/reporters/doctor-report.d.ts +23 -0
  65. package/dist/reporters/doctor-report.d.ts.map +1 -0
  66. package/dist/reporters/doctor-report.js +62 -0
  67. package/dist/reporters/doctor-report.js.map +1 -0
  68. package/dist/reporters/eslint-style.js +4 -4
  69. package/dist/reporters/eslint-style.js.map +1 -1
  70. package/dist/rules/categories.d.ts +36 -0
  71. package/dist/rules/categories.d.ts.map +1 -0
  72. package/dist/rules/categories.js +80 -0
  73. package/dist/rules/categories.js.map +1 -0
  74. package/dist/rules/code/index.d.ts +9 -0
  75. package/dist/rules/code/index.d.ts.map +1 -0
  76. package/dist/rules/code/index.js +9 -0
  77. package/dist/rules/code/index.js.map +1 -0
  78. package/dist/rules/code/jsx-attribute.d.ts +12 -0
  79. package/dist/rules/code/jsx-attribute.d.ts.map +1 -0
  80. package/dist/rules/code/jsx-attribute.js +78 -0
  81. package/dist/rules/code/jsx-attribute.js.map +1 -0
  82. package/dist/rules/code/jsx-text.d.ts +12 -0
  83. package/dist/rules/code/jsx-text.d.ts.map +1 -0
  84. package/dist/rules/code/jsx-text.js +47 -0
  85. package/dist/rules/code/jsx-text.js.map +1 -0
  86. package/dist/rules/code/string-variable.d.ts +13 -0
  87. package/dist/rules/code/string-variable.d.ts.map +1 -0
  88. package/dist/rules/code/string-variable.js +185 -0
  89. package/dist/rules/code/string-variable.js.map +1 -0
  90. package/dist/rules/code/ternary-locale.d.ts +12 -0
  91. package/dist/rules/code/ternary-locale.d.ts.map +1 -0
  92. package/dist/rules/code/ternary-locale.js +53 -0
  93. package/dist/rules/code/ternary-locale.js.map +1 -0
  94. package/dist/rules/code/toast-message.d.ts +13 -0
  95. package/dist/rules/code/toast-message.d.ts.map +1 -0
  96. package/dist/rules/code/toast-message.js +101 -0
  97. package/dist/rules/code/toast-message.js.map +1 -0
  98. package/dist/rules/extraction/data-structure.d.ts +13 -0
  99. package/dist/rules/extraction/data-structure.d.ts.map +1 -0
  100. package/dist/rules/extraction/data-structure.js +212 -0
  101. package/dist/rules/extraction/data-structure.js.map +1 -0
  102. package/dist/rules/extraction/index.d.ts +6 -0
  103. package/dist/rules/extraction/index.d.ts.map +1 -0
  104. package/dist/rules/extraction/index.js +6 -0
  105. package/dist/rules/extraction/index.js.map +1 -0
  106. package/dist/rules/extraction/translation-function.d.ts +12 -0
  107. package/dist/rules/extraction/translation-function.d.ts.map +1 -0
  108. package/dist/rules/extraction/translation-function.js +153 -0
  109. package/dist/rules/extraction/translation-function.js.map +1 -0
  110. package/dist/rules/health/index.d.ts +16 -0
  111. package/dist/rules/health/index.d.ts.map +1 -0
  112. package/dist/rules/health/index.js +22 -0
  113. package/dist/rules/health/index.js.map +1 -0
  114. package/dist/rules/health/missing-translations.d.ts +13 -0
  115. package/dist/rules/health/missing-translations.d.ts.map +1 -0
  116. package/dist/rules/health/missing-translations.js +48 -0
  117. package/dist/rules/health/missing-translations.js.map +1 -0
  118. package/dist/rules/health/orphan-keys.d.ts +16 -0
  119. package/dist/rules/health/orphan-keys.d.ts.map +1 -0
  120. package/dist/rules/health/orphan-keys.js +50 -0
  121. package/dist/rules/health/orphan-keys.js.map +1 -0
  122. package/dist/rules/health/placeholder-mismatch.d.ts +32 -0
  123. package/dist/rules/health/placeholder-mismatch.d.ts.map +1 -0
  124. package/dist/rules/health/placeholder-mismatch.js +120 -0
  125. package/dist/rules/health/placeholder-mismatch.js.map +1 -0
  126. package/dist/rules/registry.d.ts +84 -0
  127. package/dist/rules/registry.d.ts.map +1 -0
  128. package/dist/rules/registry.js +11 -0
  129. package/dist/rules/registry.js.map +1 -0
  130. package/dist/utils/cdn-client.d.ts +30 -0
  131. package/dist/utils/cdn-client.d.ts.map +1 -0
  132. package/dist/utils/cdn-client.js +59 -0
  133. package/dist/utils/cdn-client.js.map +1 -0
  134. package/dist/utils/json-keys.d.ts +60 -0
  135. package/dist/utils/json-keys.d.ts.map +1 -0
  136. package/dist/utils/json-keys.js +103 -0
  137. package/dist/utils/json-keys.js.map +1 -0
  138. package/dist/utils/key-comparison.d.ts +67 -0
  139. package/dist/utils/key-comparison.d.ts.map +1 -0
  140. package/dist/utils/key-comparison.js +299 -0
  141. package/dist/utils/key-comparison.js.map +1 -0
  142. package/package.json +2 -1
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Data structure detection rule
3
+ *
4
+ * Detects translation keys stored in data structures (arrays, objects)
5
+ * Uses property name heuristics to identify translation-relevant strings
6
+ */
7
+ import ts from "typescript";
8
+ /**
9
+ * Default property names that likely contain translation keys
10
+ */
11
+ const DEFAULT_PROPERTY_NAMES = new Set([
12
+ "message",
13
+ "label",
14
+ "title",
15
+ "text",
16
+ "description",
17
+ "placeholder",
18
+ "tooltip",
19
+ "translationKey",
20
+ "i18nKey",
21
+ "successMessage",
22
+ "errorMessage",
23
+ "warningMessage",
24
+ "infoMessage",
25
+ ]);
26
+ /**
27
+ * Default configuration for data structure detection
28
+ */
29
+ const DEFAULT_CONFIG = {
30
+ enabled: true,
31
+ requireTranslationScope: true,
32
+ maxDepth: 3,
33
+ propertyNames: [],
34
+ };
35
+ /**
36
+ * Check if a string value looks like a translation key
37
+ * Filters out obvious non-translation strings
38
+ */
39
+ function looksLikeTranslationKey(value) {
40
+ // Too short (likely not meaningful)
41
+ if (value.length < 2)
42
+ return false;
43
+ // URLs
44
+ if (value.startsWith("http://") || value.startsWith("https://"))
45
+ return false;
46
+ // File paths
47
+ if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../"))
48
+ return false;
49
+ // CSS classes (common patterns)
50
+ if (value.includes(" ") && (value.includes("-") || value.includes("_"))) {
51
+ // Likely CSS like "flex items-center gap-2"
52
+ return false;
53
+ }
54
+ // Data URLs
55
+ if (value.startsWith("data:"))
56
+ return false;
57
+ // RGB/Hex colors
58
+ if (/^#[0-9a-fA-F]{3,8}$/.test(value) || /^rgb\(/.test(value))
59
+ return false;
60
+ // Numbers only
61
+ if (/^\d+$/.test(value))
62
+ return false;
63
+ // Single special characters
64
+ if (/^[^a-zA-Z0-9]+$/.test(value))
65
+ return false;
66
+ return true;
67
+ }
68
+ /**
69
+ * Extract string literals from object literal expression
70
+ */
71
+ function extractFromObjectLiteral(node, propertyNames, currentDepth, maxDepth) {
72
+ if (currentDepth > maxDepth) {
73
+ // console.log(`[DEBUG] Stopping at depth ${currentDepth} (maxDepth: ${maxDepth})`);
74
+ return [];
75
+ }
76
+ const keys = [];
77
+ for (const prop of node.properties) {
78
+ // Handle property assignments: { message: "translationKey" }
79
+ if (ts.isPropertyAssignment(prop)) {
80
+ const propName = prop.name.getText();
81
+ // console.log(`[DEBUG depth=${currentDepth}] Property: ${propName}, isArray: ${ts.isArrayLiteralExpression(prop.initializer)}`);
82
+ // Check if property name matches our heuristics
83
+ if (propertyNames.has(propName)) {
84
+ // Extract string literal value
85
+ if (ts.isStringLiteral(prop.initializer)) {
86
+ const value = prop.initializer.text;
87
+ if (looksLikeTranslationKey(value)) {
88
+ // console.log(`[DEBUG depth=${currentDepth}] Found key: ${value}`);
89
+ keys.push(value);
90
+ }
91
+ }
92
+ }
93
+ // Recursively check nested objects
94
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
95
+ const nestedKeys = extractFromObjectLiteral(prop.initializer, propertyNames, currentDepth + 1, maxDepth);
96
+ // console.log(`[DEBUG depth=${currentDepth}] Nested object returned ${nestedKeys.length} keys`);
97
+ keys.push(...nestedKeys);
98
+ }
99
+ // Recursively check nested arrays
100
+ if (ts.isArrayLiteralExpression(prop.initializer)) {
101
+ // console.log(`[DEBUG depth=${currentDepth}] Processing nested array for prop: ${propName}`);
102
+ const nestedKeys = extractFromArrayLiteral(prop.initializer, propertyNames, currentDepth + 1, maxDepth);
103
+ // console.log(`[DEBUG depth=${currentDepth}] Nested array returned ${nestedKeys.length} keys`);
104
+ keys.push(...nestedKeys);
105
+ }
106
+ }
107
+ // Handle shorthand properties: { message } (less common for translation keys)
108
+ // Skip for now as these are references, not literals
109
+ }
110
+ return keys;
111
+ }
112
+ /**
113
+ * Check if an array looks like a language selector pattern
114
+ * Examples: [{ value: "en", label: "English" }, { value: "tr", label: "Türkçe" }]
115
+ */
116
+ function isLanguageSelectorPattern(node) {
117
+ // Need at least 2 elements to be a selector
118
+ if (node.elements.length < 2)
119
+ return false;
120
+ // Check if all elements are object literals with value + label properties
121
+ const allMatchPattern = node.elements.every((element) => {
122
+ if (!ts.isObjectLiteralExpression(element))
123
+ return false;
124
+ let hasValue = false;
125
+ let hasLabel = false;
126
+ let valueIsLanguageCode = false;
127
+ for (const prop of element.properties) {
128
+ if (!ts.isPropertyAssignment(prop))
129
+ continue;
130
+ const propName = prop.name.getText();
131
+ if (propName === "value" && ts.isStringLiteral(prop.initializer)) {
132
+ hasValue = true;
133
+ // Check if value looks like ISO language code (2-5 lowercase letters, optionally with dash)
134
+ const value = prop.initializer.text;
135
+ valueIsLanguageCode = /^[a-z]{2}(-[a-z]{2,3})?$/i.test(value);
136
+ }
137
+ if (propName === "label") {
138
+ hasLabel = true;
139
+ }
140
+ }
141
+ return hasValue && hasLabel && valueIsLanguageCode;
142
+ });
143
+ return allMatchPattern;
144
+ }
145
+ /**
146
+ * Extract string literals from array literal expression
147
+ */
148
+ function extractFromArrayLiteral(node, propertyNames, currentDepth, maxDepth) {
149
+ if (currentDepth > maxDepth) {
150
+ // console.log(`[DEBUG ARRAY] Stopping at depth ${currentDepth} (maxDepth: ${maxDepth})`);
151
+ return [];
152
+ }
153
+ // Skip language selector patterns (native language names should not be translated)
154
+ if (isLanguageSelectorPattern(node)) {
155
+ return [];
156
+ }
157
+ // console.log(`[DEBUG ARRAY depth=${currentDepth}] Processing array with ${node.elements.length} elements`);
158
+ const keys = [];
159
+ for (const element of node.elements) {
160
+ // console.log(`[DEBUG ARRAY depth=${currentDepth}] Element is object: ${ts.isObjectLiteralExpression(element)}, is array: ${ts.isArrayLiteralExpression(element)}`);
161
+ // Handle object literals in arrays: [{ message: "key1" }, { message: "key2" }]
162
+ if (ts.isObjectLiteralExpression(element)) {
163
+ const nestedKeys = extractFromObjectLiteral(element, propertyNames, currentDepth + 1, maxDepth);
164
+ // console.log(`[DEBUG ARRAY depth=${currentDepth}] Object element returned ${nestedKeys.length} keys`);
165
+ keys.push(...nestedKeys);
166
+ }
167
+ // Handle nested arrays
168
+ if (ts.isArrayLiteralExpression(element)) {
169
+ keys.push(...extractFromArrayLiteral(element, propertyNames, currentDepth + 1, maxDepth));
170
+ }
171
+ }
172
+ // console.log(`[DEBUG ARRAY depth=${currentDepth}] Total keys from array: ${keys.length}`);
173
+ return keys;
174
+ }
175
+ /**
176
+ * Check data structures for translation keys
177
+ */
178
+ export function checkDataStructure(node, ctx, config) {
179
+ const cfg = { ...DEFAULT_CONFIG, ...config };
180
+ // Feature disabled
181
+ if (!cfg.enabled)
182
+ return [];
183
+ // Require translation scope and not in one
184
+ if (cfg.requireTranslationScope && !ctx.translationScope)
185
+ return [];
186
+ // Build property names set
187
+ const propertyNames = new Set([
188
+ ...DEFAULT_PROPERTY_NAMES,
189
+ ...(cfg.propertyNames || []),
190
+ ]);
191
+ // Extract keys based on node type
192
+ let extractedKeys = [];
193
+ if (ts.isObjectLiteralExpression(node)) {
194
+ extractedKeys = extractFromObjectLiteral(node, propertyNames, 0, cfg.maxDepth || 3);
195
+ }
196
+ else if (ts.isArrayLiteralExpression(node)) {
197
+ extractedKeys = extractFromArrayLiteral(node, propertyNames, 0, cfg.maxDepth || 3);
198
+ }
199
+ // No keys found
200
+ if (extractedKeys.length === 0)
201
+ return [];
202
+ // Get current namespace binding from context
203
+ const issues = [];
204
+ for (const extractedKey of extractedKeys) {
205
+ // Try to apply namespace from current scope
206
+ let key = extractedKey;
207
+ let namespace;
208
+ let bindingType = "unbound";
209
+ // First try: scope-bound namespace (existing logic)
210
+ if (ctx.namespaceMap) {
211
+ for (const binding of Object.values(ctx.namespaceMap)) {
212
+ if (binding.type === "bound-scoped" && binding.namespace) {
213
+ namespace = binding.namespace;
214
+ bindingType = "bound-scoped";
215
+ // Apply namespace prefix
216
+ if (!key.startsWith(`${namespace}.`)) {
217
+ key = `${namespace}.${extractedKey}`;
218
+ }
219
+ break;
220
+ }
221
+ }
222
+ }
223
+ // Second try: file-level namespace inference (NEW)
224
+ if (!namespace && ctx.fileNamespaces && ctx.fileNamespaces.length > 0) {
225
+ if (ctx.fileNamespaces.length === 1) {
226
+ // Single namespace in file - safe to apply
227
+ namespace = ctx.fileNamespaces[0];
228
+ bindingType = "bound-scoped";
229
+ key = `${namespace}.${extractedKey}`;
230
+ if (ctx.verbose) {
231
+ console.log(`[VERBOSE] Applied file-level namespace "${namespace}" to data structure key: ${extractedKey}`);
232
+ }
233
+ }
234
+ else {
235
+ // Multiple namespaces - ambiguous, use first one but mark as unknown-scoped
236
+ namespace = ctx.fileNamespaces[0];
237
+ bindingType = "unknown-scoped";
238
+ key = `${namespace}.${extractedKey}`;
239
+ if (ctx.verbose) {
240
+ console.log(`[VERBOSE] Ambiguous namespace (${ctx.fileNamespaces.length} found in file), using "${namespace}" for: ${extractedKey}`);
241
+ }
242
+ }
243
+ }
244
+ const pos = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
245
+ issues.push({
246
+ file: ctx.filePath,
247
+ line: pos.line + 1,
248
+ column: pos.character + 1,
249
+ text: extractedKey,
250
+ type: "string-variable",
251
+ severity: "info",
252
+ message: `Translation key in data structure: "${key}"`,
253
+ key,
254
+ bindingType,
255
+ namespace,
256
+ });
257
+ // Track stats
258
+ if (ctx.stats && ctx.stats.dataStructureKeys !== undefined) {
259
+ ctx.stats.dataStructureKeys++;
260
+ }
261
+ }
262
+ return issues;
263
+ }
264
+ //# sourceMappingURL=data-structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-structure.js","sourceRoot":"","sources":["../../../src/analyzer/rules/data-structure.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Rules index - exports all detection rules
2
+ * Rules index backward compatibility barrel
3
+ *
4
+ * Canonical rule locations are now:
5
+ * src/rules/code/ — Code detection rules (JSX text, attributes, etc.)
6
+ * src/rules/extraction/ — Key extraction rules (t() calls, data structures)
7
+ *
8
+ * This file re-exports from the new locations so existing imports
9
+ * (e.g., analyzer/index.ts) continue to work without changes.
3
10
  */
4
- export * from "./jsx-attribute.js";
5
- export * from "./jsx-text.js";
6
- export * from "./string-variable.js";
7
- export * from "./ternary-locale.js";
8
- export * from "./toast-message.js";
9
- export * from "./translation-function.js";
11
+ export * from "../../rules/code/index.js";
12
+ export * from "../../rules/extraction/index.js";
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC"}
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Rules index - exports all detection rules
2
+ * Rules index backward compatibility barrel
3
+ *
4
+ * Canonical rule locations are now:
5
+ * src/rules/code/ — Code detection rules (JSX text, attributes, etc.)
6
+ * src/rules/extraction/ — Key extraction rules (t() calls, data structures)
7
+ *
8
+ * This file re-exports from the new locations so existing imports
9
+ * (e.g., analyzer/index.ts) continue to work without changes.
3
10
  */
4
- export * from "./jsx-attribute.js";
5
- export * from "./jsx-text.js";
6
- export * from "./string-variable.js";
7
- export * from "./ternary-locale.js";
8
- export * from "./toast-message.js";
9
- export * from "./translation-function.js";
11
+ export * from "../../rules/code/index.js";
12
+ export * from "../../rules/extraction/index.js";
10
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC"}
@@ -9,7 +9,7 @@ import { generateKeyFromContext, truncate } from "../../utils/text.js";
9
9
  */
10
10
  const IGNORE_PATTERNS = [
11
11
  /^[\s\n\r\t]+$/, // Whitespace only
12
- /^[→←↑↓★•·\-–—\/\\|,;:.!?()[\]{}]+$/, // Symbols only
12
+ /^[→←↑↓★•·\-–—/\\|,;:.!?()[\]{}]+$/, // Symbols only
13
13
  /^\d+[+%KkMm]?$/, // Numbers with optional suffix
14
14
  /^[A-Z_]+$/, // SCREAMING_CASE
15
15
  /^https?:\/\//, // URLs
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-text.js","sourceRoot":"","sources":["../../../src/analyzer/rules/jsx-text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGvE;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,eAAe,EAAE,kBAAkB;IACnC,oCAAoC,EAAE,eAAe;IACrD,gBAAgB,EAAE,+BAA+B;IACjD,WAAW,EAAE,iBAAiB;IAC9B,cAAc,EAAE,OAAO;IACvB,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE,yCAAyC;IACtD,YAAY,EAAE,yCAAyC;IACvD,UAAU,EAAE,mCAAmC;CAChD,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAgB,EAAE,GAAgB;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAE9B,2BAA2B;IAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,wBAAwB;IACxB,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IAED,eAAe;IACf,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC;QAClB,MAAM,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC;QACzB,IAAI;QACJ,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,oBAAoB,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG;QAClD,YAAY,EAAE,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC;KACzD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"jsx-text.js","sourceRoot":"","sources":["../../../src/analyzer/rules/jsx-text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGvE;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,eAAe,EAAE,kBAAkB;IACnC,mCAAmC,EAAE,eAAe;IACpD,gBAAgB,EAAE,+BAA+B;IACjD,WAAW,EAAE,iBAAiB;IAC9B,cAAc,EAAE,OAAO;IACvB,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE,yCAAyC;IACtD,YAAY,EAAE,yCAAyC;IACvD,UAAU,EAAE,mCAAmC;CAChD,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAgB,EAAE,GAAgB;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAE9B,2BAA2B;IAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,wBAAwB;IACxB,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IAED,eAAe;IACf,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE1E,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC;QAClB,MAAM,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC;QACzB,IAAI;QACJ,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,oBAAoB,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG;QAClD,YAAY,EAAE,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC;KACzD,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"translation-function.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/translation-function.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAOtD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,EAAE,CAAC,cAAc,EACvB,GAAG,EAAE,WAAW,GACf,KAAK,GAAG,IAAI,CAmDd"}
1
+ {"version":3,"file":"translation-function.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/translation-function.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAgBtD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,EAAE,CAAC,cAAc,EACvB,GAAG,EAAE,WAAW,GACf,KAAK,GAAG,IAAI,CA8Gd"}
@@ -8,6 +8,14 @@ import ts from "typescript";
8
8
  * Translation function names to detect
9
9
  */
10
10
  const TRANSLATION_FUNCTIONS = new Set(["t", "useTranslation"]);
11
+ /**
12
+ * Check if identifier looks like a translator variable
13
+ * Common patterns: t, tUser, tAuth, tCommon, etc.
14
+ */
15
+ function looksLikeTranslator(name) {
16
+ // Single 't' or starts with 't' followed by uppercase (tUser, tAuth, etc.)
17
+ return name === "t" || /^t[A-Z]/.test(name);
18
+ }
11
19
  /**
12
20
  * Check for translation function calls
13
21
  */
@@ -16,12 +24,31 @@ export function checkTranslationFunction(node, ctx) {
16
24
  if (!bindingId)
17
25
  return null;
18
26
  // Check if this identifier is bound to a translation namespace
19
- const binding = ctx.namespaceMap?.[bindingId];
20
- // If not bound and not a known global/default translation function, skip
27
+ // Use let instead of const so we can create a synthetic binding if pattern matches
28
+ let binding = ctx.namespaceMap?.[bindingId];
29
+ // If not bound and not a known global/default translation function, check if it looks like a translator
21
30
  if (!binding && !TRANSLATION_FUNCTIONS.has(bindingId)) {
22
- if (ctx.stats)
23
- ctx.stats.unboundTranslators++;
24
- return null;
31
+ // Fallback: if it looks like a translator variable (tUser, tAuth, etc.), assume it's valid
32
+ // This helps catch cases where binding detection failed but the pattern is clear
33
+ if (looksLikeTranslator(bindingId)) {
34
+ if (ctx.verbose) {
35
+ const pos = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
36
+ console.log(`[VERBOSE] Accepting translator by pattern: ${bindingId} at ${ctx.filePath}:${pos.line + 1}`);
37
+ }
38
+ // Create a synthetic "unknown-scoped" binding for this translator
39
+ // We don't know the namespace, so mark it as unknown-scoped for fuzzy matching later
40
+ binding = { type: "unknown-scoped", dynamic: false };
41
+ }
42
+ else {
43
+ if (ctx.stats)
44
+ ctx.stats.unboundTranslators++;
45
+ // Log unbound translator in verbose mode for debugging
46
+ if (ctx.verbose) {
47
+ const pos = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
48
+ console.log(`[VERBOSE] Unbound translator (not a recognized pattern): ${bindingId} at ${ctx.filePath}:${pos.line + 1}`);
49
+ }
50
+ return null;
51
+ }
25
52
  }
26
53
  // Get the first argument (translation key)
27
54
  const args = node.arguments;
@@ -52,11 +79,72 @@ export function checkTranslationFunction(node, ctx) {
52
79
  namespace: binding?.namespace,
53
80
  };
54
81
  }
55
- // Handle template literal or dynamic keys
82
+ // Handle template literal: t(`plans.${planKey}.name`)
83
+ if (ts.isTemplateExpression(firstArg) || ts.isNoSubstitutionTemplateLiteral(firstArg)) {
84
+ const pattern = extractTemplatePattern(firstArg);
85
+ const pos = ctx.sourceFile.getLineAndCharacterOfPosition(firstArg.getStart());
86
+ // Apply namespace prefix if bound
87
+ let fullPattern = pattern;
88
+ if (binding?.type === "bound-scoped" && binding.namespace) {
89
+ const prefix = binding.namespace;
90
+ if (!pattern.startsWith(`${prefix}.`)) {
91
+ fullPattern = `${prefix}.${pattern}`;
92
+ }
93
+ }
94
+ if (ctx.stats)
95
+ ctx.stats.dynamicKeys++;
96
+ return {
97
+ file: ctx.filePath,
98
+ line: pos.line + 1,
99
+ column: pos.character + 1,
100
+ text: pattern,
101
+ type: "string-variable",
102
+ severity: "info",
103
+ message: `Dynamic translation key pattern: "${fullPattern}"`,
104
+ key: fullPattern, // Store the pattern as the key for now
105
+ pattern: fullPattern,
106
+ isDynamic: true,
107
+ bindingType: binding?.type || "unbound",
108
+ namespace: binding?.namespace,
109
+ };
110
+ }
111
+ // Other dynamic keys (computed, variables, etc.)
56
112
  if (ctx.stats)
57
113
  ctx.stats.dynamicKeys++;
58
114
  return null;
59
115
  }
116
+ /**
117
+ * Extract pattern from template literal
118
+ * Examples:
119
+ * `plans.${planKey}.name` -> 'plans.${planKey}.name'
120
+ * `${namespace}.title` -> '${namespace}.title'
121
+ */
122
+ function extractTemplatePattern(node) {
123
+ // NoSubstitutionTemplateLiteral is just a plain string (no ${})
124
+ if (ts.isNoSubstitutionTemplateLiteral(node)) {
125
+ return node.text;
126
+ }
127
+ // TemplateExpression has head, templateSpans
128
+ if (!ts.isTemplateExpression(node)) {
129
+ return "";
130
+ }
131
+ let pattern = node.head.text;
132
+ for (const span of node.templateSpans) {
133
+ // Add placeholder for the expression
134
+ const expr = span.expression;
135
+ let placeholder = "${x}"; // Generic placeholder
136
+ // Try to use the actual variable name if it's an identifier
137
+ if (ts.isIdentifier(expr)) {
138
+ placeholder = `\${${expr.text}}`;
139
+ }
140
+ else if (ts.isPropertyAccessExpression(expr)) {
141
+ // Handle cases like ${item.key}
142
+ placeholder = `\${${expr.getText()}}`;
143
+ }
144
+ pattern += placeholder + span.literal.text;
145
+ }
146
+ return pattern;
147
+ }
60
148
  /**
61
149
  * Extract the binding identifier from a call expression.
62
150
  * Handles: t(), t.raw(), t.rich(), t.has()
@@ -1 +1 @@
1
- {"version":3,"file":"translation-function.js","sourceRoot":"","sources":["../../../src/analyzer/rules/translation-function.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"translation-function.js","sourceRoot":"","sources":["../../../src/analyzer/rules/translation-function.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,8 @@ export interface Issue {
13
13
  key?: string;
14
14
  bindingType?: NamespaceBindingType;
15
15
  namespace?: string;
16
+ isDynamic?: boolean;
17
+ pattern?: string;
16
18
  }
17
19
  export type NamespaceBindingType = "bound-scoped" | "root-scoped" | "unknown-scoped" | "unbound";
18
20
  export interface NamespaceBinding {
@@ -25,12 +27,27 @@ export interface ScanStats {
25
27
  dynamicNamespaces: number;
26
28
  unboundTranslators: number;
27
29
  rootScopedTranslators: number;
30
+ dataStructureKeys?: number;
31
+ dataStructureScopes?: number;
32
+ }
33
+ /**
34
+ * Represents a dynamic key access pattern detected in code
35
+ */
36
+ export interface DynamicPattern {
37
+ pattern: string;
38
+ file: string;
39
+ line: number;
40
+ namespace?: string;
41
+ bindingType?: NamespaceBindingType;
28
42
  }
29
43
  export interface RuleContext {
30
44
  filePath: string;
31
45
  sourceFile: import("typescript").SourceFile;
32
46
  namespaceMap?: Record<string, NamespaceBinding>;
33
47
  stats?: ScanStats;
48
+ verbose?: boolean;
49
+ translationScope?: boolean;
50
+ fileNamespaces?: string[];
34
51
  }
35
52
  export interface ScanOptions {
36
53
  dir?: string;
@@ -48,6 +65,12 @@ export interface ProjectContext {
48
65
  cdnBaseUrl?: string;
49
66
  lint?: LintConfig;
50
67
  }
68
+ export interface DataStructureConfig {
69
+ enabled?: boolean;
70
+ requireTranslationScope?: boolean;
71
+ maxDepth?: number;
72
+ propertyNames?: string[];
73
+ }
51
74
  export interface LintConfig {
52
75
  include?: string[];
53
76
  exclude?: string[];
@@ -55,16 +78,18 @@ export interface LintConfig {
55
78
  rules?: Record<string, "error" | "warning" | "off">;
56
79
  ignorePatterns?: RegExp[];
57
80
  translationFunctions?: string[];
81
+ dataStructureDetection?: DataStructureConfig;
58
82
  }
59
83
  export interface ScanResult {
60
84
  project?: ProjectContext;
61
85
  files: number;
62
86
  issues: Issue[];
63
87
  duration: number;
64
- localKeys?: any;
88
+ localKeys?: Record<string, string[]>;
89
+ dynamicPatterns?: DynamicPattern[];
65
90
  comparison?: {
66
- localKeys: any;
67
- remoteKeys: any;
91
+ localKeys: Record<string, string[]>;
92
+ remoteKeys: Record<string, string[]>;
68
93
  missingKeys: Record<string, string[]>;
69
94
  unusedKeys: Record<string, string[]>;
70
95
  coverage: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analyzer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAC5F,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,YAAY,EAAE,UAAU,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,GAAG,CAAC;QACf,UAAU,EAAE,GAAG,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACtC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,QAAQ,EAAE;YACR,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analyzer/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Check command - Interactive translation key checker
3
+ *
4
+ * Provides user-friendly interface for checking missing and unused keys
5
+ */
6
+ export interface CheckOptions {
7
+ dir?: string;
8
+ format?: "eslint" | "json";
9
+ verbose?: boolean;
10
+ }
11
+ export declare function checkCommand(options: CheckOptions): Promise<void>;
12
+ export declare function checkMissingCommand(options: CheckOptions): Promise<void>;
13
+ export declare function checkUnusedCommand(options: CheckOptions): Promise<void>;
14
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,iBAwCvD;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,YAAY,iBAc9D;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,iBAc7D"}