@babelize/engine 0.0.0-stage → 0.1.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 (246) hide show
  1. package/LICENSE +202 -0
  2. package/dist/BabelizeEngine.d.ts +12 -0
  3. package/dist/BabelizeEngine.js +47 -0
  4. package/dist/analysis/analyze.d.ts +106 -0
  5. package/dist/analysis/analyze.js +323 -0
  6. package/dist/config/env.d.ts +9 -0
  7. package/dist/config/env.js +16 -0
  8. package/dist/config.d.ts +74 -0
  9. package/dist/config.js +47 -0
  10. package/dist/index.d.ts +54 -0
  11. package/dist/index.js +126 -0
  12. package/dist/injection/InjectionStrategy.d.ts +62 -0
  13. package/dist/injection/InjectionStrategy.js +2 -0
  14. package/dist/injection/StrategyFactory.d.ts +4 -0
  15. package/dist/injection/StrategyFactory.js +29 -0
  16. package/dist/injection/django/django-template-injector.d.ts +29 -0
  17. package/dist/injection/django/django-template-injector.js +216 -0
  18. package/dist/injection/html/html-injector.d.ts +11 -0
  19. package/dist/injection/html/html-injector.js +173 -0
  20. package/dist/injection/strategies/NextIntlStrategy.d.ts +25 -0
  21. package/dist/injection/strategies/NextIntlStrategy.js +141 -0
  22. package/dist/injection/strategies/ReactI18nextStrategy.d.ts +19 -0
  23. package/dist/injection/strategies/ReactI18nextStrategy.js +116 -0
  24. package/dist/injection/strategies/VanillaStrategy.d.ts +11 -0
  25. package/dist/injection/strategies/VanillaStrategy.js +73 -0
  26. package/dist/injection/strategies/VueI18nStrategy.d.ts +11 -0
  27. package/dist/injection/strategies/VueI18nStrategy.js +84 -0
  28. package/dist/local/formatter.d.ts +26 -0
  29. package/dist/local/formatter.js +105 -0
  30. package/dist/local/git.d.ts +23 -0
  31. package/dist/local/git.js +136 -0
  32. package/dist/local/hosted-provider.d.ts +68 -0
  33. package/dist/local/hosted-provider.js +215 -0
  34. package/dist/local/index.d.ts +23 -0
  35. package/dist/local/index.js +75 -0
  36. package/dist/local/provider.d.ts +56 -0
  37. package/dist/local/provider.js +119 -0
  38. package/dist/local/pseudo-provider.d.ts +18 -0
  39. package/dist/local/pseudo-provider.js +207 -0
  40. package/dist/local/report.d.ts +177 -0
  41. package/dist/local/report.js +186 -0
  42. package/dist/local/translate-core.d.ts +215 -0
  43. package/dist/local/translate-core.js +461 -0
  44. package/dist/local/translate-messages.d.ts +49 -0
  45. package/dist/local/translate-messages.js +91 -0
  46. package/dist/local/workspace-copy.d.ts +91 -0
  47. package/dist/local/workspace-copy.js +355 -0
  48. package/dist/modules/extractor/extract.d.ts +20 -0
  49. package/dist/modules/extractor/extract.js +701 -0
  50. package/dist/modules/extractor/index.d.ts +2 -0
  51. package/dist/modules/extractor/index.js +63 -0
  52. package/dist/modules/finalization/django-finalize.d.ts +13 -0
  53. package/dist/modules/finalization/django-finalize.js +275 -0
  54. package/dist/modules/finalization/finalize.d.ts +36 -0
  55. package/dist/modules/finalization/finalize.js +717 -0
  56. package/dist/modules/finalization/index.d.ts +1 -0
  57. package/dist/modules/finalization/index.js +5 -0
  58. package/dist/modules/finalization/nextjs-finalize.d.ts +37 -0
  59. package/dist/modules/finalization/nextjs-finalize.js +329 -0
  60. package/dist/modules/finalization/static-runtime.d.ts +9 -0
  61. package/dist/modules/finalization/static-runtime.js +261 -0
  62. package/dist/modules/format-injection/index.d.ts +19 -0
  63. package/dist/modules/format-injection/index.js +272 -0
  64. package/dist/modules/format-injection/inject-formats.d.ts +31 -0
  65. package/dist/modules/format-injection/inject-formats.js +208 -0
  66. package/dist/modules/glossary/glossary.d.ts +9 -0
  67. package/dist/modules/glossary/glossary.js +27 -0
  68. package/dist/modules/glossary/index.d.ts +3 -0
  69. package/dist/modules/glossary/index.js +8 -0
  70. package/dist/modules/glossary/masker.d.ts +23 -0
  71. package/dist/modules/glossary/masker.js +56 -0
  72. package/dist/modules/glossary/types.d.ts +22 -0
  73. package/dist/modules/glossary/types.js +2 -0
  74. package/dist/modules/injection/index.d.ts +1 -0
  75. package/dist/modules/injection/index.js +6 -0
  76. package/dist/modules/injection/inject.d.ts +29 -0
  77. package/dist/modules/injection/inject.js +1066 -0
  78. package/dist/modules/keygen/index.d.ts +1 -0
  79. package/dist/modules/keygen/index.js +11 -0
  80. package/dist/modules/keygen/keygen.d.ts +4 -0
  81. package/dist/modules/keygen/keygen.js +116 -0
  82. package/dist/modules/keygen/locale-data.d.ts +7 -0
  83. package/dist/modules/keygen/locale-data.js +73 -0
  84. package/dist/modules/keygen/public.d.ts +2 -0
  85. package/dist/modules/keygen/public.js +12 -0
  86. package/dist/modules/locale-builder/index.d.ts +1 -0
  87. package/dist/modules/locale-builder/index.js +7 -0
  88. package/dist/modules/locale-builder/locales.d.ts +13 -0
  89. package/dist/modules/locale-builder/locales.js +107 -0
  90. package/dist/modules/locale-builder/po.d.ts +33 -0
  91. package/dist/modules/locale-builder/po.js +131 -0
  92. package/dist/modules/lockfile/hasher.d.ts +7 -0
  93. package/dist/modules/lockfile/hasher.js +13 -0
  94. package/dist/modules/lockfile/index.d.ts +3 -0
  95. package/dist/modules/lockfile/index.js +21 -0
  96. package/dist/modules/lockfile/lockfile-manager.d.ts +90 -0
  97. package/dist/modules/lockfile/lockfile-manager.js +482 -0
  98. package/dist/modules/lockfile/schema.d.ts +154 -0
  99. package/dist/modules/lockfile/schema.js +45 -0
  100. package/dist/modules/parser/index.d.ts +2 -0
  101. package/dist/modules/parser/index.js +9 -0
  102. package/dist/modules/summary/index.d.ts +1 -0
  103. package/dist/modules/summary/index.js +7 -0
  104. package/dist/modules/summary/summary.d.ts +9 -0
  105. package/dist/modules/summary/summary.js +195 -0
  106. package/dist/modules/sync-detector/index.d.ts +2 -0
  107. package/dist/modules/sync-detector/index.js +7 -0
  108. package/dist/modules/sync-detector/reporter.d.ts +3 -0
  109. package/dist/modules/sync-detector/reporter.js +16 -0
  110. package/dist/modules/sync-detector/sync-detector.d.ts +39 -0
  111. package/dist/modules/sync-detector/sync-detector.js +374 -0
  112. package/dist/modules/translator/batch-optimizer.d.ts +12 -0
  113. package/dist/modules/translator/batch-optimizer.js +30 -0
  114. package/dist/modules/translator/client/byok.provider.d.ts +64 -0
  115. package/dist/modules/translator/client/byok.provider.js +319 -0
  116. package/dist/modules/translator/client/direct-translator.client.d.ts +12 -0
  117. package/dist/modules/translator/client/direct-translator.client.js +71 -0
  118. package/dist/modules/translator/client/gemini.provider.d.ts +1 -0
  119. package/dist/modules/translator/client/gemini.provider.js +110 -0
  120. package/dist/modules/translator/client/groq.provider.d.ts +1 -0
  121. package/dist/modules/translator/client/groq.provider.js +111 -0
  122. package/dist/modules/translator/client/request.types.d.ts +1 -0
  123. package/dist/modules/translator/client/request.types.js +2 -0
  124. package/dist/modules/translator/client/retry.d.ts +29 -0
  125. package/dist/modules/translator/client/retry.js +94 -0
  126. package/dist/modules/translator/client/test-utils/mock.client.d.ts +31 -0
  127. package/dist/modules/translator/client/test-utils/mock.client.js +59 -0
  128. package/dist/modules/translator/client/translator.interface.d.ts +1 -0
  129. package/dist/modules/translator/client/translator.interface.js +2 -0
  130. package/dist/modules/translator/language-codes/errors.d.ts +10 -0
  131. package/dist/modules/translator/language-codes/errors.js +18 -0
  132. package/dist/modules/translator/language-codes/flores-map.d.ts +1 -0
  133. package/dist/modules/translator/language-codes/flores-map.js +107 -0
  134. package/dist/modules/translator/language-codes/index.d.ts +11 -0
  135. package/dist/modules/translator/language-codes/index.js +24 -0
  136. package/dist/modules/translator/language-codes/language-mapper.d.ts +25 -0
  137. package/dist/modules/translator/language-codes/language-mapper.js +132 -0
  138. package/dist/modules/translator/language-codes/rtl-languages.d.ts +2 -0
  139. package/dist/modules/translator/language-codes/rtl-languages.js +9 -0
  140. package/dist/modules/translator/memory/memory-matcher.d.ts +8 -0
  141. package/dist/modules/translator/memory/memory-matcher.js +218 -0
  142. package/dist/modules/translator/memory/types.d.ts +22 -0
  143. package/dist/modules/translator/memory/types.js +2 -0
  144. package/dist/modules/translator/translate.d.ts +38 -0
  145. package/dist/modules/translator/translate.js +932 -0
  146. package/dist/modules/translator/translator.d.ts +5 -0
  147. package/dist/modules/translator/translator.js +46 -0
  148. package/dist/modules/vue/migrate.d.ts +13 -0
  149. package/dist/modules/vue/migrate.js +40 -0
  150. package/dist/modules/vue/script-inject.d.ts +16 -0
  151. package/dist/modules/vue/script-inject.js +115 -0
  152. package/dist/modules/vue/sfc.d.ts +11 -0
  153. package/dist/modules/vue/sfc.js +51 -0
  154. package/dist/modules/vue/template-rewrite.d.ts +25 -0
  155. package/dist/modules/vue/template-rewrite.js +76 -0
  156. package/dist/modules/vue/template-scan.d.ts +29 -0
  157. package/dist/modules/vue/template-scan.js +264 -0
  158. package/dist/modules/workspace/index.d.ts +1 -0
  159. package/dist/modules/workspace/index.js +5 -0
  160. package/dist/modules/workspace/validate.d.ts +13 -0
  161. package/dist/modules/workspace/validate.js +298 -0
  162. package/dist/orchestrator.d.ts +8 -0
  163. package/dist/orchestrator.js +616 -0
  164. package/dist/providers/default-translation-provider.d.ts +20 -0
  165. package/dist/providers/default-translation-provider.js +30 -0
  166. package/dist/providers/index.d.ts +2 -0
  167. package/dist/providers/index.js +21 -0
  168. package/dist/providers/types.d.ts +145 -0
  169. package/dist/providers/types.js +2 -0
  170. package/dist/qa/check-project.d.ts +49 -0
  171. package/dist/qa/check-project.js +150 -0
  172. package/dist/qa/locale-files.d.ts +44 -0
  173. package/dist/qa/locale-files.js +159 -0
  174. package/dist/qa/locale-qa.d.ts +61 -0
  175. package/dist/qa/locale-qa.js +325 -0
  176. package/dist/qa/review.d.ts +43 -0
  177. package/dist/qa/review.js +175 -0
  178. package/dist/runtime/config.d.ts +8 -0
  179. package/dist/runtime/config.js +36 -0
  180. package/dist/runtime/index.d.ts +3 -0
  181. package/dist/runtime/index.js +8 -0
  182. package/dist/runtime/types.d.ts +363 -0
  183. package/dist/runtime/types.js +38 -0
  184. package/dist/types.d.ts +134 -0
  185. package/dist/types.js +12 -0
  186. package/dist/utils/ast-helpers.d.ts +57 -0
  187. package/dist/utils/ast-helpers.js +608 -0
  188. package/dist/utils/cache-keys.d.ts +8 -0
  189. package/dist/utils/cache-keys.js +18 -0
  190. package/dist/utils/circuit-breaker.d.ts +43 -0
  191. package/dist/utils/circuit-breaker.js +119 -0
  192. package/dist/utils/concurrent-map.d.ts +4 -0
  193. package/dist/utils/concurrent-map.js +21 -0
  194. package/dist/utils/detect-format.d.ts +5 -0
  195. package/dist/utils/detect-format.js +125 -0
  196. package/dist/utils/dtl-mask.d.ts +25 -0
  197. package/dist/utils/dtl-mask.js +58 -0
  198. package/dist/utils/extraction-options.d.ts +23 -0
  199. package/dist/utils/extraction-options.js +23 -0
  200. package/dist/utils/file-utils.d.ts +33 -0
  201. package/dist/utils/file-utils.js +262 -0
  202. package/dist/utils/glossary-match.d.ts +9 -0
  203. package/dist/utils/glossary-match.js +25 -0
  204. package/dist/utils/html-extractor.d.ts +8 -0
  205. package/dist/utils/html-extractor.js +317 -0
  206. package/dist/utils/i18next-icu.d.ts +38 -0
  207. package/dist/utils/i18next-icu.js +159 -0
  208. package/dist/utils/icu-message.d.ts +65 -0
  209. package/dist/utils/icu-message.js +346 -0
  210. package/dist/utils/icu-spans.d.ts +10 -0
  211. package/dist/utils/icu-spans.js +126 -0
  212. package/dist/utils/jsx-message.d.ts +93 -0
  213. package/dist/utils/jsx-message.js +621 -0
  214. package/dist/utils/key-usage.d.ts +35 -0
  215. package/dist/utils/key-usage.js +247 -0
  216. package/dist/utils/logger.d.ts +24 -0
  217. package/dist/utils/logger.js +33 -0
  218. package/dist/utils/metadata.d.ts +80 -0
  219. package/dist/utils/metadata.js +255 -0
  220. package/dist/utils/module-constants.d.ts +30 -0
  221. package/dist/utils/module-constants.js +265 -0
  222. package/dist/utils/not-injected.d.ts +6 -0
  223. package/dist/utils/not-injected.js +36 -0
  224. package/dist/utils/placeholder-protection.d.ts +57 -0
  225. package/dist/utils/placeholder-protection.js +136 -0
  226. package/dist/utils/pseudo-markers.d.ts +9 -0
  227. package/dist/utils/pseudo-markers.js +16 -0
  228. package/dist/utils/py-extractor.d.ts +14 -0
  229. package/dist/utils/py-extractor.js +285 -0
  230. package/dist/utils/string-utils.d.ts +52 -0
  231. package/dist/utils/string-utils.js +270 -0
  232. package/dist/utils/translation-quality.d.ts +34 -0
  233. package/dist/utils/translation-quality.js +156 -0
  234. package/dist/utils/translation-sanitizer.d.ts +10 -0
  235. package/dist/utils/translation-sanitizer.js +57 -0
  236. package/dist/utils/translator-caller.d.ts +32 -0
  237. package/dist/utils/translator-caller.js +217 -0
  238. package/dist/utils/translator-load-balancer.d.ts +73 -0
  239. package/dist/utils/translator-load-balancer.js +293 -0
  240. package/dist/utils/ui-copy.d.ts +32 -0
  241. package/dist/utils/ui-copy.js +126 -0
  242. package/dist/utils/workspace.d.ts +14 -0
  243. package/dist/utils/workspace.js +89 -0
  244. package/package.json +64 -4
  245. package/schemas/translate-report.schema.json +297 -0
  246. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ export { generateKeys, keysToNestedLocale, mergeLocaleData, createKeyMapping, flattenLocaleData, unflattenLocaleData, setNestedValue, } from './public';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setNestedValue = exports.unflattenLocaleData = exports.flattenLocaleData = exports.createKeyMapping = exports.mergeLocaleData = exports.keysToNestedLocale = exports.generateKeys = void 0;
4
+ var public_1 = require("./public");
5
+ Object.defineProperty(exports, "generateKeys", { enumerable: true, get: function () { return public_1.generateKeys; } });
6
+ Object.defineProperty(exports, "keysToNestedLocale", { enumerable: true, get: function () { return public_1.keysToNestedLocale; } });
7
+ Object.defineProperty(exports, "mergeLocaleData", { enumerable: true, get: function () { return public_1.mergeLocaleData; } });
8
+ Object.defineProperty(exports, "createKeyMapping", { enumerable: true, get: function () { return public_1.createKeyMapping; } });
9
+ Object.defineProperty(exports, "flattenLocaleData", { enumerable: true, get: function () { return public_1.flattenLocaleData; } });
10
+ Object.defineProperty(exports, "unflattenLocaleData", { enumerable: true, get: function () { return public_1.unflattenLocaleData; } });
11
+ Object.defineProperty(exports, "setNestedValue", { enumerable: true, get: function () { return public_1.setNestedValue; } });
@@ -0,0 +1,4 @@
1
+ import type { ExtractedString, KeyGenerationResult, LocaleData } from '../../runtime/types';
2
+ export declare function generateKeys(extractedStrings: ExtractedString[], existingKeys?: LocaleData): {
3
+ keyGeneration: KeyGenerationResult;
4
+ };
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateKeys = generateKeys;
4
+ const string_utils_1 = require("../../utils/string-utils");
5
+ const jsx_message_1 = require("../../utils/jsx-message");
6
+ function generateKeys(extractedStrings, existingKeys = {}) {
7
+ const keys = [];
8
+ const duplicates = [];
9
+ const usedKeys = new Set();
10
+ collectExistingKeys(existingKeys, '', usedKeys);
11
+ const existingValues = new Map();
12
+ collectExistingValues(existingKeys, '', existingValues);
13
+ // Existing keys already given to a string this run (prefer an unclaimed one).
14
+ const claimed = new Set();
15
+ /**
16
+ * A string re-extracted on a later run (e.g. one the injector couldn't wire
17
+ * up, so the literal is still in the code) must get the key it already has,
18
+ * not a new `_2` copy. Reuse an existing key with the same base name and
19
+ * identical source text; otherwise mint a unique one.
20
+ */
21
+ const keyFor = (baseFullKey, text) => {
22
+ const candidates = [baseFullKey];
23
+ for (let n = 2; existingValues.has(`${baseFullKey}_${n}`); n++)
24
+ candidates.push(`${baseFullKey}_${n}`);
25
+ const matching = candidates.filter((k) => existingValues.get(k) === text);
26
+ const pick = matching.find((k) => !claimed.has(k)) ?? matching[0];
27
+ if (pick) {
28
+ claimed.add(pick);
29
+ return { key: pick, reused: true };
30
+ }
31
+ return { key: (0, string_utils_1.generateUniqueKey)(baseFullKey, usedKeys), reused: false };
32
+ };
33
+ // Generate locale-appropriate plural categories.
34
+ // Always use all 6 CLDR categories since target locale may be unknown at extraction time.
35
+ // The translation engine will only generate entries for categories the target locale needs.
36
+ const pluralCategories = ['zero', 'one', 'two', 'few', 'many', 'other'];
37
+ for (const extracted of extractedStrings) {
38
+ const namespace = (0, string_utils_1.inferNamespace)(extracted.file);
39
+ // A sentence message is named from its words: "Welcome back, {user}" → welcomeBack.
40
+ const truncatedText = (0, string_utils_1.truncateForKey)(extracted.icuMessage ? (0, jsx_message_1.messageKeyText)(extracted.text) : extracted.text, 5);
41
+ const baseKeyName = (0, string_utils_1.toCamelCase)(truncatedText);
42
+ const baseFullKey = `${namespace}.${baseKeyName}`;
43
+ // Check if this is a plural string - generate base key + 6 CLDR plural-category keys
44
+ // ICU sentence messages carry their own plural forms ({count, plural, …}).
45
+ if (!extracted.icuMessage && (0, string_utils_1.isLikelyPlural)(extracted.text)) {
46
+ // Generate the unsuffixed base key - this is what gets mapped to extractionId for code injection.
47
+ // i18next callers use the base key (e.g. t('items.count', { count })) and resolve suffixed
48
+ // variants (_one, _other, etc.) internally.
49
+ const { key: uniqueBaseKey, reused: baseReused } = keyFor(baseFullKey, extracted.text);
50
+ if (!baseReused && uniqueBaseKey !== baseFullKey)
51
+ duplicates.push({ original: baseFullKey, renamed: uniqueBaseKey });
52
+ usedKeys.add(uniqueBaseKey);
53
+ keys.push({
54
+ key: uniqueBaseKey,
55
+ namespace,
56
+ value: extracted.text,
57
+ extractionId: extracted.id,
58
+ parentContext: extracted.parentContext,
59
+ extractionContext: extracted.context,
60
+ });
61
+ // Generate the 6 CLDR plural-category keys as suffixed variants.
62
+ // Each gets a distinct extractionId so createKeyMapping keeps all 6 entries.
63
+ for (const category of pluralCategories) {
64
+ const pluralKey = `${uniqueBaseKey}_${category}`;
65
+ const uniquePluralKey = baseReused && existingValues.has(pluralKey) ? pluralKey : (0, string_utils_1.generateUniqueKey)(pluralKey, usedKeys);
66
+ if (uniquePluralKey !== pluralKey)
67
+ duplicates.push({ original: pluralKey, renamed: uniquePluralKey });
68
+ usedKeys.add(uniquePluralKey);
69
+ keys.push({
70
+ key: uniquePluralKey,
71
+ namespace,
72
+ value: extracted.text,
73
+ extractionId: `${extracted.id}_${category}`,
74
+ isPlural: true,
75
+ pluralCategory: category,
76
+ parentContext: extracted.parentContext,
77
+ extractionContext: extracted.context,
78
+ });
79
+ }
80
+ }
81
+ else {
82
+ const { key: uniqueKey, reused } = keyFor(baseFullKey, extracted.text);
83
+ if (!reused && uniqueKey !== baseFullKey)
84
+ duplicates.push({ original: baseFullKey, renamed: uniqueKey });
85
+ usedKeys.add(uniqueKey);
86
+ keys.push({
87
+ key: uniqueKey,
88
+ namespace,
89
+ value: extracted.text,
90
+ extractionId: extracted.id,
91
+ parentContext: extracted.parentContext,
92
+ extractionContext: extracted.context,
93
+ });
94
+ }
95
+ }
96
+ const keyGeneration = { keys, duplicates };
97
+ return { keyGeneration };
98
+ }
99
+ function collectExistingValues(data, prefix, out) {
100
+ for (const [key, value] of Object.entries(data)) {
101
+ const fullKey = prefix ? `${prefix}.${key}` : key;
102
+ if (typeof value === 'string')
103
+ out.set(fullKey, value);
104
+ else if (typeof value === 'object' && value !== null)
105
+ collectExistingValues(value, fullKey, out);
106
+ }
107
+ }
108
+ function collectExistingKeys(data, prefix, keys) {
109
+ for (const [key, value] of Object.entries(data)) {
110
+ const fullKey = prefix ? `${prefix}.${key}` : key;
111
+ if (typeof value === 'string')
112
+ keys.add(fullKey);
113
+ else if (typeof value === 'object' && value !== null)
114
+ collectExistingKeys(value, fullKey, keys);
115
+ }
116
+ }
@@ -0,0 +1,7 @@
1
+ import type { GeneratedKey, LocaleData } from '../../runtime/types';
2
+ export declare function keysToNestedLocale(keys: GeneratedKey[]): LocaleData;
3
+ export declare function setNestedValue(obj: LocaleData, key: string, value: string): void;
4
+ export declare function mergeLocaleData(existing: LocaleData, newData: LocaleData): LocaleData;
5
+ export declare function createKeyMapping(keys: GeneratedKey[]): Map<string, string>;
6
+ export declare function flattenLocaleData(data: LocaleData, prefix?: string): Record<string, string>;
7
+ export declare function unflattenLocaleData(flat: Record<string, string>): LocaleData;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.keysToNestedLocale = keysToNestedLocale;
4
+ exports.setNestedValue = setNestedValue;
5
+ exports.mergeLocaleData = mergeLocaleData;
6
+ exports.createKeyMapping = createKeyMapping;
7
+ exports.flattenLocaleData = flattenLocaleData;
8
+ exports.unflattenLocaleData = unflattenLocaleData;
9
+ function keysToNestedLocale(keys) {
10
+ const result = {};
11
+ for (const { key, value } of keys)
12
+ setNestedValue(result, key, value);
13
+ return result;
14
+ }
15
+ function setNestedValue(obj, key, value) {
16
+ const parts = key.split('.');
17
+ let current = obj;
18
+ for (let i = 0; i < parts.length - 1; i++) {
19
+ const part = parts[i];
20
+ if (!(part in current)) {
21
+ current[part] = {};
22
+ }
23
+ else if (typeof current[part] === 'string') {
24
+ // Key conflict: a flat key (e.g. "homepage") and nested key (e.g. "homepage.title")
25
+ // both exist. This is a data model error in the generated keys.
26
+ throw new Error(`Key conflict in locale data: "${key}" — intermediate key "${part}" is already a string value and cannot be an object path`);
27
+ }
28
+ current = current[part];
29
+ }
30
+ current[parts[parts.length - 1]] = value;
31
+ }
32
+ function mergeLocaleData(existing, newData) {
33
+ const result = JSON.parse(JSON.stringify(existing));
34
+ function merge(target, source) {
35
+ for (const [key, value] of Object.entries(source)) {
36
+ if (!(key in target)) {
37
+ target[key] = value;
38
+ }
39
+ else if (typeof target[key] === 'object' &&
40
+ typeof value === 'object' &&
41
+ target[key] !== null &&
42
+ value !== null) {
43
+ merge(target[key], value);
44
+ }
45
+ }
46
+ }
47
+ merge(result, newData);
48
+ return result;
49
+ }
50
+ function createKeyMapping(keys) {
51
+ const mapping = new Map();
52
+ for (const { key, extractionId } of keys)
53
+ mapping.set(extractionId, key);
54
+ return mapping;
55
+ }
56
+ function flattenLocaleData(data, prefix = '') {
57
+ const result = {};
58
+ for (const [key, value] of Object.entries(data)) {
59
+ const fullKey = prefix ? `${prefix}.${key}` : key;
60
+ if (typeof value === 'string')
61
+ result[fullKey] = value;
62
+ else if (typeof value === 'object' && value !== null)
63
+ Object.assign(result, flattenLocaleData(value, fullKey));
64
+ }
65
+ return result;
66
+ }
67
+ function unflattenLocaleData(flat) {
68
+ const result = {};
69
+ for (const [key, value] of Object.entries(flat)) {
70
+ setNestedValue(result, key, value);
71
+ }
72
+ return result;
73
+ }
@@ -0,0 +1,2 @@
1
+ export { generateKeys } from './keygen';
2
+ export { keysToNestedLocale, mergeLocaleData, createKeyMapping, flattenLocaleData, unflattenLocaleData, setNestedValue } from './locale-data';
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setNestedValue = exports.unflattenLocaleData = exports.flattenLocaleData = exports.createKeyMapping = exports.mergeLocaleData = exports.keysToNestedLocale = exports.generateKeys = void 0;
4
+ var keygen_1 = require("./keygen");
5
+ Object.defineProperty(exports, "generateKeys", { enumerable: true, get: function () { return keygen_1.generateKeys; } });
6
+ var locale_data_1 = require("./locale-data");
7
+ Object.defineProperty(exports, "keysToNestedLocale", { enumerable: true, get: function () { return locale_data_1.keysToNestedLocale; } });
8
+ Object.defineProperty(exports, "mergeLocaleData", { enumerable: true, get: function () { return locale_data_1.mergeLocaleData; } });
9
+ Object.defineProperty(exports, "createKeyMapping", { enumerable: true, get: function () { return locale_data_1.createKeyMapping; } });
10
+ Object.defineProperty(exports, "flattenLocaleData", { enumerable: true, get: function () { return locale_data_1.flattenLocaleData; } });
11
+ Object.defineProperty(exports, "unflattenLocaleData", { enumerable: true, get: function () { return locale_data_1.unflattenLocaleData; } });
12
+ Object.defineProperty(exports, "setNestedValue", { enumerable: true, get: function () { return locale_data_1.setNestedValue; } });
@@ -0,0 +1 @@
1
+ export { handleBaseLocale, readLocaleFile, checkExistingTargetLocales } from './locales';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkExistingTargetLocales = exports.readLocaleFile = exports.handleBaseLocale = void 0;
4
+ var locales_1 = require("./locales");
5
+ Object.defineProperty(exports, "handleBaseLocale", { enumerable: true, get: function () { return locales_1.handleBaseLocale; } });
6
+ Object.defineProperty(exports, "readLocaleFile", { enumerable: true, get: function () { return locales_1.readLocaleFile; } });
7
+ Object.defineProperty(exports, "checkExistingTargetLocales", { enumerable: true, get: function () { return locales_1.checkExistingTargetLocales; } });
@@ -0,0 +1,13 @@
1
+ import type { GeneratedKey, LocaleData, LocaleFile, WorkspaceInfo } from '../../runtime/types';
2
+ export declare function handleBaseLocale(workspace: WorkspaceInfo, generatedKeys: GeneratedKey[], sourceLocale?: string, dryRun?: boolean): Promise<{
3
+ localeHandling: {
4
+ sourceLocale: LocaleFile;
5
+ newKeysCount: number;
6
+ existingKeysCount: number;
7
+ };
8
+ }>;
9
+ export declare function readLocaleFile(workspace: WorkspaceInfo, locale: string): Promise<LocaleData | null>;
10
+ export declare function checkExistingTargetLocales(workspace: WorkspaceInfo, targetLocales: string[]): Promise<{
11
+ existing: string[];
12
+ missing: string[];
13
+ }>;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleBaseLocale = handleBaseLocale;
4
+ exports.readLocaleFile = readLocaleFile;
5
+ exports.checkExistingTargetLocales = checkExistingTargetLocales;
6
+ const file_utils_1 = require("../../utils/file-utils");
7
+ const keygen_1 = require("../keygen");
8
+ const language_codes_1 = require("../translator/language-codes");
9
+ function assertSafeLocale(locale) {
10
+ // Allow common locale identifiers only (examples: en, en-US, pt_BR, zh-Hant).
11
+ // Disallow path separators and other special characters to prevent path traversal.
12
+ const localePattern = /^[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*$/;
13
+ if (!localePattern.test(locale)) {
14
+ throw new Error(`Invalid locale: ${locale}`);
15
+ }
16
+ }
17
+ async function handleBaseLocale(workspace, generatedKeys, sourceLocale = 'en', dryRun = false) {
18
+ assertSafeLocale(sourceLocale);
19
+ const localePaths = (0, file_utils_1.localeFilePath)(workspace.path, workspace.publicDir, workspace.localeFormat, sourceLocale);
20
+ const localesDir = localePaths.dir;
21
+ const localeFilePathTarget = localePaths.file;
22
+ const relativeLocaleFilePath = localePaths.relativeFile;
23
+ if (!dryRun)
24
+ await (0, file_utils_1.ensureDir)(localesDir);
25
+ const exists = await (0, file_utils_1.pathExists)(localeFilePathTarget);
26
+ let existingData = {};
27
+ let existingKeysCount = 0;
28
+ if (exists) {
29
+ if (workspace.localeFormat !== 'json') {
30
+ throw new Error(`Locale format '${workspace.localeFormat}' not yet supported for base locale handling`);
31
+ }
32
+ existingData = (await (0, file_utils_1.readJsonFile)(localeFilePathTarget)) || {};
33
+ existingKeysCount = countKeys(existingData);
34
+ }
35
+ const newData = (0, keygen_1.keysToNestedLocale)(generatedKeys);
36
+ const mergedData = (0, keygen_1.mergeLocaleData)(existingData, newData);
37
+ const mergedKeysCount = countKeys(mergedData);
38
+ const newKeysCount = mergedKeysCount - existingKeysCount;
39
+ const MAX_KEYS_PER_RUN = 10000;
40
+ if (mergedKeysCount > MAX_KEYS_PER_RUN) {
41
+ throw new Error(`Project exceeds maximum keys per run (Found: ${mergedKeysCount}, Limit: ${MAX_KEYS_PER_RUN}). Please reduce project size or split into multiple runs.`);
42
+ }
43
+ // Add _meta with direction and language info.
44
+ // Spread mergedData first, then override _meta so the computed dir/language
45
+ // always takes precedence over any stale _meta already present in the file.
46
+ const existingMeta = typeof mergedData._meta === 'object' && mergedData._meta !== null
47
+ ? mergedData._meta
48
+ : {};
49
+ const dataWithMeta = {
50
+ ...mergedData,
51
+ _meta: {
52
+ ...existingMeta,
53
+ dir: (0, language_codes_1.isRTL)(sourceLocale) ? 'rtl' : 'ltr',
54
+ language: sourceLocale,
55
+ },
56
+ };
57
+ if (!dryRun)
58
+ await (0, file_utils_1.writeJsonFile)(localeFilePathTarget, dataWithMeta, true);
59
+ const sourceLocaleFile = {
60
+ locale: sourceLocale,
61
+ path: relativeLocaleFilePath,
62
+ data: dataWithMeta,
63
+ isNew: !exists,
64
+ isRTL: (0, language_codes_1.isRTL)(sourceLocale),
65
+ };
66
+ return {
67
+ localeHandling: {
68
+ sourceLocale: sourceLocaleFile,
69
+ newKeysCount,
70
+ existingKeysCount,
71
+ },
72
+ };
73
+ }
74
+ function countKeys(data) {
75
+ let count = 0;
76
+ function traverse(obj) {
77
+ for (const value of Object.values(obj)) {
78
+ if (typeof value === 'string')
79
+ count++;
80
+ else if (typeof value === 'object' && value !== null)
81
+ traverse(value);
82
+ }
83
+ }
84
+ traverse(data);
85
+ return count;
86
+ }
87
+ async function readLocaleFile(workspace, locale) {
88
+ assertSafeLocale(locale);
89
+ if (workspace.localeFormat !== 'json') {
90
+ throw new Error(`Locale format '${workspace.localeFormat}' reading not yet implemented`);
91
+ }
92
+ const { file } = (0, file_utils_1.localeFilePath)(workspace.path, workspace.publicDir, workspace.localeFormat, locale);
93
+ return (0, file_utils_1.readJsonFile)(file);
94
+ }
95
+ async function checkExistingTargetLocales(workspace, targetLocales) {
96
+ const existing = [];
97
+ const missing = [];
98
+ for (const locale of targetLocales) {
99
+ assertSafeLocale(locale);
100
+ const { file } = (0, file_utils_1.localeFilePath)(workspace.path, workspace.publicDir, workspace.localeFormat, locale);
101
+ if (await (0, file_utils_1.pathExists)(file))
102
+ existing.push(locale);
103
+ else
104
+ missing.push(locale);
105
+ }
106
+ return { existing, missing };
107
+ }
@@ -0,0 +1,33 @@
1
+ import type { TranslationTable } from 'gettext-parser';
2
+ /**
3
+ * Read a .po file content and return key-value pairs (msgid → msgstr).
4
+ * For untranslated entries, msgstr will be an empty string.
5
+ */
6
+ export declare function readPoFile(content: string): Record<string, string>;
7
+ /**
8
+ * Read a .po file and return the full gettext-parser translation table
9
+ * (preserves comments, msgctxt, plural forms, etc.)
10
+ */
11
+ export declare function readPoFileRaw(content: string): TranslationTable;
12
+ /**
13
+ * Write a .po file from key-value pairs.
14
+ * Uses a gettext-parser translation table as the base for preserving
15
+ * comments, msgctxt, and header metadata.
16
+ */
17
+ export declare function writePoFile(translations: Record<string, string>, options?: {
18
+ context?: string;
19
+ pluralForms?: string;
20
+ baseContent?: string;
21
+ }): string;
22
+ /**
23
+ * Compile a .po file to .mo binary format.
24
+ */
25
+ export declare function compileMo(poContent: string): Buffer;
26
+ /**
27
+ * Build a gettext-parser table from flat translation entries.
28
+ * Useful when generating a fresh .po file from extracted keys.
29
+ */
30
+ export declare function buildPoTable(translations: Record<string, string>, options?: {
31
+ sourceLanguage?: string;
32
+ pluralForms?: string;
33
+ }): TranslationTable;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readPoFile = readPoFile;
7
+ exports.readPoFileRaw = readPoFileRaw;
8
+ exports.writePoFile = writePoFile;
9
+ exports.compileMo = compileMo;
10
+ exports.buildPoTable = buildPoTable;
11
+ const gettext_parser_1 = __importDefault(require("gettext-parser"));
12
+ /**
13
+ * Read a .po file content and return key-value pairs (msgid → msgstr).
14
+ * For untranslated entries, msgstr will be an empty string.
15
+ */
16
+ function readPoFile(content) {
17
+ const parsed = gettext_parser_1.default.po.parse(content);
18
+ const result = {};
19
+ for (const context of Object.values(parsed.translations)) {
20
+ for (const [msgid, entry] of Object.entries(context)) {
21
+ if (!msgid)
22
+ continue; // skip header entry
23
+ const msgstr = entry.msgstr?.[0] || '';
24
+ result[msgid] = msgstr;
25
+ }
26
+ }
27
+ return result;
28
+ }
29
+ /**
30
+ * Read a .po file and return the full gettext-parser translation table
31
+ * (preserves comments, msgctxt, plural forms, etc.)
32
+ */
33
+ function readPoFileRaw(content) {
34
+ return gettext_parser_1.default.po.parse(content);
35
+ }
36
+ /**
37
+ * Write a .po file from key-value pairs.
38
+ * Uses a gettext-parser translation table as the base for preserving
39
+ * comments, msgctxt, and header metadata.
40
+ */
41
+ function writePoFile(translations, options) {
42
+ const ctx = options?.context || '';
43
+ // Build the gettext-parser table structure
44
+ const table = {
45
+ charset: 'utf-8',
46
+ headers: {
47
+ 'content-type': 'text/plain; charset=utf-8',
48
+ 'plural-forms': options?.pluralForms || 'nplurals=2; plural=(n!=1);',
49
+ },
50
+ translations: {
51
+ [ctx]: {},
52
+ },
53
+ };
54
+ // If base content is provided, merge existing metadata
55
+ if (options?.baseContent) {
56
+ const base = gettext_parser_1.default.po.parse(options.baseContent);
57
+ table.headers = { ...base.headers, ...table.headers };
58
+ if (base.charset)
59
+ table.charset = base.charset;
60
+ // Preserve existing entries for context
61
+ if (base.translations[ctx]) {
62
+ for (const [msgid, entry] of Object.entries(base.translations[ctx])) {
63
+ if (!msgid)
64
+ continue;
65
+ table.translations[ctx][msgid] = entry;
66
+ }
67
+ }
68
+ }
69
+ // Apply translations
70
+ for (const [msgid, msgstr] of Object.entries(translations)) {
71
+ if (!msgid)
72
+ continue;
73
+ if (table.translations[ctx][msgid]) {
74
+ table.translations[ctx][msgid].msgstr = [msgstr];
75
+ }
76
+ else {
77
+ table.translations[ctx][msgid] = {
78
+ msgid,
79
+ msgstr: [msgstr],
80
+ };
81
+ }
82
+ }
83
+ const compiled = gettext_parser_1.default.po.compile(table, {
84
+ foldLength: 0,
85
+ sort: false,
86
+ escapeCharacters: true,
87
+ });
88
+ return compiled.toString('utf-8');
89
+ }
90
+ /**
91
+ * Compile a .po file to .mo binary format.
92
+ */
93
+ function compileMo(poContent) {
94
+ const parsed = gettext_parser_1.default.po.parse(poContent);
95
+ return gettext_parser_1.default.mo.compile(parsed);
96
+ }
97
+ /**
98
+ * Build a gettext-parser table from flat translation entries.
99
+ * Useful when generating a fresh .po file from extracted keys.
100
+ */
101
+ function buildPoTable(translations, options) {
102
+ const ctx = '';
103
+ const headers = {
104
+ 'content-type': 'text/plain; charset=utf-8',
105
+ 'plural-forms': options?.pluralForms || 'nplurals=2; plural=(n!=1);',
106
+ };
107
+ if (options?.sourceLanguage) {
108
+ headers['language'] = options.sourceLanguage;
109
+ }
110
+ const table = {
111
+ charset: 'utf-8',
112
+ headers,
113
+ translations: {
114
+ [ctx]: {},
115
+ },
116
+ };
117
+ // Add header entry
118
+ table.translations[ctx][''] = {
119
+ msgid: '',
120
+ msgstr: [Object.entries(headers).map(([k, v]) => `${k}: ${v}`).join('\n')],
121
+ };
122
+ for (const [msgid, msgstr] of Object.entries(translations)) {
123
+ if (!msgid)
124
+ continue;
125
+ table.translations[ctx][msgid] = {
126
+ msgid,
127
+ msgstr: [msgstr],
128
+ };
129
+ }
130
+ return table;
131
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Compute a SHA-256 hex digest of the given source string.
3
+ *
4
+ * The hash is case-sensitive and whitespace-sensitive by design,
5
+ * so "Hello" and "hello" and " Hello" all produce different hashes.
6
+ */
7
+ export declare function hashSourceString(text: string): string;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hashSourceString = hashSourceString;
4
+ const crypto_1 = require("crypto");
5
+ /**
6
+ * Compute a SHA-256 hex digest of the given source string.
7
+ *
8
+ * The hash is case-sensitive and whitespace-sensitive by design,
9
+ * so "Hello" and "hello" and " Hello" all produce different hashes.
10
+ */
11
+ function hashSourceString(text) {
12
+ return (0, crypto_1.createHash)('sha256').update(text, 'utf8').digest('hex');
13
+ }
@@ -0,0 +1,3 @@
1
+ export { hashSourceString } from './hasher';
2
+ export { type LockfileData, type LockfileEntry, type LockfilePartition, type LockfileStats, type PartitionedKey, createEmptyLockfile, } from './schema';
3
+ export { buildKeysToTranslateByTargetLocale, clearLockfile, removeLocaleFromLockfile, collectCachedTranslations, computeLockfileStats, getLockfilePath, loadLockfile, partitionKeys, saveLockfile, updateLockfile, lockfileChanged, dropFailedTranslations, isStalePseudoEntry, type LockfileReadOptions, } from './lockfile-manager';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isStalePseudoEntry = exports.dropFailedTranslations = exports.lockfileChanged = exports.updateLockfile = exports.saveLockfile = exports.partitionKeys = exports.loadLockfile = exports.getLockfilePath = exports.computeLockfileStats = exports.collectCachedTranslations = exports.removeLocaleFromLockfile = exports.clearLockfile = exports.buildKeysToTranslateByTargetLocale = exports.createEmptyLockfile = exports.hashSourceString = void 0;
4
+ var hasher_1 = require("./hasher");
5
+ Object.defineProperty(exports, "hashSourceString", { enumerable: true, get: function () { return hasher_1.hashSourceString; } });
6
+ var schema_1 = require("./schema");
7
+ Object.defineProperty(exports, "createEmptyLockfile", { enumerable: true, get: function () { return schema_1.createEmptyLockfile; } });
8
+ var lockfile_manager_1 = require("./lockfile-manager");
9
+ Object.defineProperty(exports, "buildKeysToTranslateByTargetLocale", { enumerable: true, get: function () { return lockfile_manager_1.buildKeysToTranslateByTargetLocale; } });
10
+ Object.defineProperty(exports, "clearLockfile", { enumerable: true, get: function () { return lockfile_manager_1.clearLockfile; } });
11
+ Object.defineProperty(exports, "removeLocaleFromLockfile", { enumerable: true, get: function () { return lockfile_manager_1.removeLocaleFromLockfile; } });
12
+ Object.defineProperty(exports, "collectCachedTranslations", { enumerable: true, get: function () { return lockfile_manager_1.collectCachedTranslations; } });
13
+ Object.defineProperty(exports, "computeLockfileStats", { enumerable: true, get: function () { return lockfile_manager_1.computeLockfileStats; } });
14
+ Object.defineProperty(exports, "getLockfilePath", { enumerable: true, get: function () { return lockfile_manager_1.getLockfilePath; } });
15
+ Object.defineProperty(exports, "loadLockfile", { enumerable: true, get: function () { return lockfile_manager_1.loadLockfile; } });
16
+ Object.defineProperty(exports, "partitionKeys", { enumerable: true, get: function () { return lockfile_manager_1.partitionKeys; } });
17
+ Object.defineProperty(exports, "saveLockfile", { enumerable: true, get: function () { return lockfile_manager_1.saveLockfile; } });
18
+ Object.defineProperty(exports, "updateLockfile", { enumerable: true, get: function () { return lockfile_manager_1.updateLockfile; } });
19
+ Object.defineProperty(exports, "lockfileChanged", { enumerable: true, get: function () { return lockfile_manager_1.lockfileChanged; } });
20
+ Object.defineProperty(exports, "dropFailedTranslations", { enumerable: true, get: function () { return lockfile_manager_1.dropFailedTranslations; } });
21
+ Object.defineProperty(exports, "isStalePseudoEntry", { enumerable: true, get: function () { return lockfile_manager_1.isStalePseudoEntry; } });