@lingo.dev/compiler 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 (300) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +192 -0
  3. package/build/_virtual/rolldown_runtime.cjs +29 -0
  4. package/build/_virtual/rolldown_runtime.mjs +7 -0
  5. package/build/index.cjs +0 -0
  6. package/build/index.d.cts +2 -0
  7. package/build/index.d.mts +2 -0
  8. package/build/index.mjs +1 -0
  9. package/build/metadata/manager.cjs +131 -0
  10. package/build/metadata/manager.mjs +123 -0
  11. package/build/metadata/manager.mjs.map +1 -0
  12. package/build/plugin/build-translator.cjs +198 -0
  13. package/build/plugin/build-translator.mjs +196 -0
  14. package/build/plugin/build-translator.mjs.map +1 -0
  15. package/build/plugin/cleanup.cjs +20 -0
  16. package/build/plugin/cleanup.mjs +20 -0
  17. package/build/plugin/cleanup.mjs.map +1 -0
  18. package/build/plugin/next-compiler-loader.cjs +41 -0
  19. package/build/plugin/next-compiler-loader.d.cts +12 -0
  20. package/build/plugin/next-compiler-loader.d.cts.map +1 -0
  21. package/build/plugin/next-compiler-loader.d.mts +13 -0
  22. package/build/plugin/next-compiler-loader.d.mts.map +1 -0
  23. package/build/plugin/next-compiler-loader.mjs +42 -0
  24. package/build/plugin/next-compiler-loader.mjs.map +1 -0
  25. package/build/plugin/next-config-loader.cjs +13 -0
  26. package/build/plugin/next-config-loader.d.cts +8 -0
  27. package/build/plugin/next-config-loader.d.cts.map +1 -0
  28. package/build/plugin/next-config-loader.d.mts +9 -0
  29. package/build/plugin/next-config-loader.d.mts.map +1 -0
  30. package/build/plugin/next-config-loader.mjs +14 -0
  31. package/build/plugin/next-config-loader.mjs.map +1 -0
  32. package/build/plugin/next-locale-client-loader.cjs +9 -0
  33. package/build/plugin/next-locale-client-loader.d.cts +8 -0
  34. package/build/plugin/next-locale-client-loader.d.cts.map +1 -0
  35. package/build/plugin/next-locale-client-loader.d.mts +9 -0
  36. package/build/plugin/next-locale-client-loader.d.mts.map +1 -0
  37. package/build/plugin/next-locale-client-loader.mjs +10 -0
  38. package/build/plugin/next-locale-client-loader.mjs.map +1 -0
  39. package/build/plugin/next-locale-server-loader.cjs +9 -0
  40. package/build/plugin/next-locale-server-loader.d.cts +8 -0
  41. package/build/plugin/next-locale-server-loader.d.cts.map +1 -0
  42. package/build/plugin/next-locale-server-loader.d.mts +9 -0
  43. package/build/plugin/next-locale-server-loader.d.mts.map +1 -0
  44. package/build/plugin/next-locale-server-loader.mjs +10 -0
  45. package/build/plugin/next-locale-server-loader.mjs.map +1 -0
  46. package/build/plugin/next.cjs +220 -0
  47. package/build/plugin/next.d.cts +9 -0
  48. package/build/plugin/next.d.cts.map +1 -0
  49. package/build/plugin/next.d.mts +9 -0
  50. package/build/plugin/next.d.mts.map +1 -0
  51. package/build/plugin/next.mjs +222 -0
  52. package/build/plugin/next.mjs.map +1 -0
  53. package/build/plugin/transform/babel-compat.cjs +13 -0
  54. package/build/plugin/transform/babel-compat.mjs +10 -0
  55. package/build/plugin/transform/babel-compat.mjs.map +1 -0
  56. package/build/plugin/transform/index.cjs +44 -0
  57. package/build/plugin/transform/index.mjs +42 -0
  58. package/build/plugin/transform/index.mjs.map +1 -0
  59. package/build/plugin/transform/metadata.cjs +142 -0
  60. package/build/plugin/transform/metadata.mjs +141 -0
  61. package/build/plugin/transform/metadata.mjs.map +1 -0
  62. package/build/plugin/transform/parse-override.cjs +145 -0
  63. package/build/plugin/transform/parse-override.mjs +144 -0
  64. package/build/plugin/transform/parse-override.mjs.map +1 -0
  65. package/build/plugin/transform/process-file.cjs +391 -0
  66. package/build/plugin/transform/process-file.mjs +390 -0
  67. package/build/plugin/transform/process-file.mjs.map +1 -0
  68. package/build/plugin/transform/use-i18n.cjs +8 -0
  69. package/build/plugin/transform/use-i18n.mjs +7 -0
  70. package/build/plugin/transform/use-i18n.mjs.map +1 -0
  71. package/build/plugin/transform/utils.cjs +205 -0
  72. package/build/plugin/transform/utils.mjs +192 -0
  73. package/build/plugin/transform/utils.mjs.map +1 -0
  74. package/build/plugin/unplugin.cjs +188 -0
  75. package/build/plugin/unplugin.d.cts +8 -0
  76. package/build/plugin/unplugin.d.cts.map +1 -0
  77. package/build/plugin/unplugin.d.mts +8 -0
  78. package/build/plugin/unplugin.d.mts.map +1 -0
  79. package/build/plugin/unplugin.mjs +186 -0
  80. package/build/plugin/unplugin.mjs.map +1 -0
  81. package/build/plugin/vite.cjs +28 -0
  82. package/build/plugin/vite.d.cts +9 -0
  83. package/build/plugin/vite.d.cts.map +1 -0
  84. package/build/plugin/vite.d.mts +9 -0
  85. package/build/plugin/vite.d.mts.map +1 -0
  86. package/build/plugin/vite.mjs +29 -0
  87. package/build/plugin/vite.mjs.map +1 -0
  88. package/build/plugin/webpack.cjs +27 -0
  89. package/build/plugin/webpack.d.cts +8 -0
  90. package/build/plugin/webpack.d.cts.map +1 -0
  91. package/build/plugin/webpack.d.mts +8 -0
  92. package/build/plugin/webpack.d.mts.map +1 -0
  93. package/build/plugin/webpack.mjs +28 -0
  94. package/build/plugin/webpack.mjs.map +1 -0
  95. package/build/react/client/index.cjs +9 -0
  96. package/build/react/client/index.d.cts +5 -0
  97. package/build/react/client/index.d.mts +5 -0
  98. package/build/react/client/index.mjs +6 -0
  99. package/build/react/client/useTranslation.cjs +71 -0
  100. package/build/react/client/useTranslation.d.cts +42 -0
  101. package/build/react/client/useTranslation.d.cts.map +1 -0
  102. package/build/react/client/useTranslation.d.mts +42 -0
  103. package/build/react/client/useTranslation.d.mts.map +1 -0
  104. package/build/react/client/useTranslation.mjs +71 -0
  105. package/build/react/client/useTranslation.mjs.map +1 -0
  106. package/build/react/next/client.cjs +25 -0
  107. package/build/react/next/client.d.cts +9 -0
  108. package/build/react/next/client.d.cts.map +1 -0
  109. package/build/react/next/client.d.mts +9 -0
  110. package/build/react/next/client.d.mts.map +1 -0
  111. package/build/react/next/client.mjs +24 -0
  112. package/build/react/next/client.mjs.map +1 -0
  113. package/build/react/next/cookie-locale-resolver.cjs +29 -0
  114. package/build/react/next/cookie-locale-resolver.d.cts +33 -0
  115. package/build/react/next/cookie-locale-resolver.d.cts.map +1 -0
  116. package/build/react/next/cookie-locale-resolver.d.mts +33 -0
  117. package/build/react/next/cookie-locale-resolver.d.mts.map +1 -0
  118. package/build/react/next/cookie-locale-resolver.mjs +29 -0
  119. package/build/react/next/cookie-locale-resolver.mjs.map +1 -0
  120. package/build/react/next/server.cjs +21 -0
  121. package/build/react/next/server.d.cts +13 -0
  122. package/build/react/next/server.d.cts.map +1 -0
  123. package/build/react/next/server.d.mts +14 -0
  124. package/build/react/next/server.d.mts.map +1 -0
  125. package/build/react/next/server.mjs +20 -0
  126. package/build/react/next/server.mjs.map +1 -0
  127. package/build/react/server/ServerLingoProvider.cjs +19 -0
  128. package/build/react/server/ServerLingoProvider.d.cts +12 -0
  129. package/build/react/server/ServerLingoProvider.d.cts.map +1 -0
  130. package/build/react/server/ServerLingoProvider.d.mts +12 -0
  131. package/build/react/server/ServerLingoProvider.d.mts.map +1 -0
  132. package/build/react/server/ServerLingoProvider.mjs +19 -0
  133. package/build/react/server/ServerLingoProvider.mjs.map +1 -0
  134. package/build/react/server/index.cjs +7 -0
  135. package/build/react/server/index.d.cts +4 -0
  136. package/build/react/server/index.d.mts +4 -0
  137. package/build/react/server/index.mjs +5 -0
  138. package/build/react/server/useTranslation.cjs +60 -0
  139. package/build/react/server/useTranslation.d.cts +36 -0
  140. package/build/react/server/useTranslation.d.cts.map +1 -0
  141. package/build/react/server/useTranslation.d.mts +36 -0
  142. package/build/react/server/useTranslation.d.mts.map +1 -0
  143. package/build/react/server/useTranslation.mjs +60 -0
  144. package/build/react/server/useTranslation.mjs.map +1 -0
  145. package/build/react/server-only/index.cjs +42 -0
  146. package/build/react/server-only/index.d.cts +38 -0
  147. package/build/react/server-only/index.d.cts.map +1 -0
  148. package/build/react/server-only/index.d.mts +38 -0
  149. package/build/react/server-only/index.d.mts.map +1 -0
  150. package/build/react/server-only/index.mjs +42 -0
  151. package/build/react/server-only/index.mjs.map +1 -0
  152. package/build/react/server-only/translations.cjs +85 -0
  153. package/build/react/server-only/translations.mjs +85 -0
  154. package/build/react/server-only/translations.mjs.map +1 -0
  155. package/build/react/shared/LingoContext.cjs +14 -0
  156. package/build/react/shared/LingoContext.d.cts +41 -0
  157. package/build/react/shared/LingoContext.d.cts.map +1 -0
  158. package/build/react/shared/LingoContext.d.mts +41 -0
  159. package/build/react/shared/LingoContext.d.mts.map +1 -0
  160. package/build/react/shared/LingoContext.mjs +13 -0
  161. package/build/react/shared/LingoContext.mjs.map +1 -0
  162. package/build/react/shared/LingoProvider.cjs +274 -0
  163. package/build/react/shared/LingoProvider.d.cts +76 -0
  164. package/build/react/shared/LingoProvider.d.cts.map +1 -0
  165. package/build/react/shared/LingoProvider.d.mts +76 -0
  166. package/build/react/shared/LingoProvider.d.mts.map +1 -0
  167. package/build/react/shared/LingoProvider.mjs +274 -0
  168. package/build/react/shared/LingoProvider.mjs.map +1 -0
  169. package/build/react/shared/LocaleSwitcher.cjs +61 -0
  170. package/build/react/shared/LocaleSwitcher.d.cts +71 -0
  171. package/build/react/shared/LocaleSwitcher.d.cts.map +1 -0
  172. package/build/react/shared/LocaleSwitcher.d.mts +71 -0
  173. package/build/react/shared/LocaleSwitcher.d.mts.map +1 -0
  174. package/build/react/shared/LocaleSwitcher.mjs +61 -0
  175. package/build/react/shared/LocaleSwitcher.mjs.map +1 -0
  176. package/build/react/shared/render-rich-text.cjs +55 -0
  177. package/build/react/shared/render-rich-text.d.cts +17 -0
  178. package/build/react/shared/render-rich-text.d.cts.map +1 -0
  179. package/build/react/shared/render-rich-text.d.mts +17 -0
  180. package/build/react/shared/render-rich-text.d.mts.map +1 -0
  181. package/build/react/shared/render-rich-text.mjs +54 -0
  182. package/build/react/shared/render-rich-text.mjs.map +1 -0
  183. package/build/react/shared/utils.cjs +34 -0
  184. package/build/react/shared/utils.mjs +35 -0
  185. package/build/react/shared/utils.mjs.map +1 -0
  186. package/build/react/types.d.cts +16 -0
  187. package/build/react/types.d.cts.map +1 -0
  188. package/build/react/types.d.mts +16 -0
  189. package/build/react/types.d.mts.map +1 -0
  190. package/build/translation-server/logger.cjs +37 -0
  191. package/build/translation-server/logger.mjs +37 -0
  192. package/build/translation-server/logger.mjs.map +1 -0
  193. package/build/translation-server/translation-server.cjs +547 -0
  194. package/build/translation-server/translation-server.mjs +544 -0
  195. package/build/translation-server/translation-server.mjs.map +1 -0
  196. package/build/translation-server/ws-events.cjs +15 -0
  197. package/build/translation-server/ws-events.mjs +15 -0
  198. package/build/translation-server/ws-events.mjs.map +1 -0
  199. package/build/translators/api.cjs +12 -0
  200. package/build/translators/api.mjs +12 -0
  201. package/build/translators/api.mjs.map +1 -0
  202. package/build/translators/cache-factory.cjs +26 -0
  203. package/build/translators/cache-factory.mjs +27 -0
  204. package/build/translators/cache-factory.mjs.map +1 -0
  205. package/build/translators/lingo/model-factory.cjs +179 -0
  206. package/build/translators/lingo/model-factory.mjs +174 -0
  207. package/build/translators/lingo/model-factory.mjs.map +1 -0
  208. package/build/translators/lingo/prompt.cjs +43 -0
  209. package/build/translators/lingo/prompt.mjs +43 -0
  210. package/build/translators/lingo/prompt.mjs.map +1 -0
  211. package/build/translators/lingo/service.cjs +152 -0
  212. package/build/translators/lingo/service.mjs +152 -0
  213. package/build/translators/lingo/service.mjs.map +1 -0
  214. package/build/translators/lingo/shots.cjs +28 -0
  215. package/build/translators/lingo/shots.mjs +28 -0
  216. package/build/translators/lingo/shots.mjs.map +1 -0
  217. package/build/translators/local-cache.cjs +115 -0
  218. package/build/translators/local-cache.mjs +113 -0
  219. package/build/translators/local-cache.mjs.map +1 -0
  220. package/build/translators/parse-xml.cjs +109 -0
  221. package/build/translators/parse-xml.mjs +108 -0
  222. package/build/translators/parse-xml.mjs.map +1 -0
  223. package/build/translators/pluralization/icu-validator.cjs +36 -0
  224. package/build/translators/pluralization/icu-validator.mjs +36 -0
  225. package/build/translators/pluralization/icu-validator.mjs.map +1 -0
  226. package/build/translators/pluralization/pattern-detector.cjs +25 -0
  227. package/build/translators/pluralization/pattern-detector.mjs +25 -0
  228. package/build/translators/pluralization/pattern-detector.mjs.map +1 -0
  229. package/build/translators/pluralization/prompt.cjs +98 -0
  230. package/build/translators/pluralization/prompt.mjs +98 -0
  231. package/build/translators/pluralization/prompt.mjs.map +1 -0
  232. package/build/translators/pluralization/service.cjs +247 -0
  233. package/build/translators/pluralization/service.mjs +247 -0
  234. package/build/translators/pluralization/service.mjs.map +1 -0
  235. package/build/translators/pluralization/shots.cjs +53 -0
  236. package/build/translators/pluralization/shots.mjs +53 -0
  237. package/build/translators/pluralization/shots.mjs.map +1 -0
  238. package/build/translators/pluralization/types.d.cts +17 -0
  239. package/build/translators/pluralization/types.d.cts.map +1 -0
  240. package/build/translators/pluralization/types.d.mts +17 -0
  241. package/build/translators/pluralization/types.d.mts.map +1 -0
  242. package/build/translators/pseudotranslator/index.cjs +129 -0
  243. package/build/translators/pseudotranslator/index.mjs +129 -0
  244. package/build/translators/pseudotranslator/index.mjs.map +1 -0
  245. package/build/translators/translation-service.cjs +182 -0
  246. package/build/translators/translation-service.mjs +183 -0
  247. package/build/translators/translation-service.mjs.map +1 -0
  248. package/build/translators/translator-factory.cjs +49 -0
  249. package/build/translators/translator-factory.mjs +50 -0
  250. package/build/translators/translator-factory.mjs.map +1 -0
  251. package/build/types.d.cts +161 -0
  252. package/build/types.d.cts.map +1 -0
  253. package/build/types.d.mts +161 -0
  254. package/build/types.d.mts.map +1 -0
  255. package/build/utils/config-factory.cjs +58 -0
  256. package/build/utils/config-factory.mjs +58 -0
  257. package/build/utils/config-factory.mjs.map +1 -0
  258. package/build/utils/hash.cjs +17 -0
  259. package/build/utils/hash.mjs +16 -0
  260. package/build/utils/hash.mjs.map +1 -0
  261. package/build/utils/is-valid-locale.cjs +14 -0
  262. package/build/utils/is-valid-locale.mjs +14 -0
  263. package/build/utils/is-valid-locale.mjs.map +1 -0
  264. package/build/utils/logger.cjs +51 -0
  265. package/build/utils/logger.mjs +50 -0
  266. package/build/utils/logger.mjs.map +1 -0
  267. package/build/utils/path-helpers.cjs +49 -0
  268. package/build/utils/path-helpers.mjs +47 -0
  269. package/build/utils/path-helpers.mjs.map +1 -0
  270. package/build/utils/timeout.cjs +42 -0
  271. package/build/utils/timeout.mjs +41 -0
  272. package/build/utils/timeout.mjs.map +1 -0
  273. package/build/virtual/code-generator.cjs +54 -0
  274. package/build/virtual/code-generator.mjs +53 -0
  275. package/build/virtual/code-generator.mjs.map +1 -0
  276. package/build/virtual/config.cjs +10 -0
  277. package/build/virtual/config.d.cts +9 -0
  278. package/build/virtual/config.d.cts.map +1 -0
  279. package/build/virtual/config.d.mts +9 -0
  280. package/build/virtual/config.d.mts.map +1 -0
  281. package/build/virtual/config.mjs +8 -0
  282. package/build/virtual/config.mjs.map +1 -0
  283. package/build/virtual/locale/client.cjs +23 -0
  284. package/build/virtual/locale/client.d.cts +19 -0
  285. package/build/virtual/locale/client.d.cts.map +1 -0
  286. package/build/virtual/locale/client.d.mts +19 -0
  287. package/build/virtual/locale/client.d.mts.map +1 -0
  288. package/build/virtual/locale/client.mjs +22 -0
  289. package/build/virtual/locale/client.mjs.map +1 -0
  290. package/build/virtual/locale/server.cjs +13 -0
  291. package/build/virtual/locale/server.d.cts +13 -0
  292. package/build/virtual/locale/server.d.cts.map +1 -0
  293. package/build/virtual/locale/server.d.mts +13 -0
  294. package/build/virtual/locale/server.d.mts.map +1 -0
  295. package/build/virtual/locale/server.mjs +13 -0
  296. package/build/virtual/locale/server.mjs.map +1 -0
  297. package/build/widget/lingo-dev-widget.cjs +228 -0
  298. package/build/widget/lingo-dev-widget.mjs +229 -0
  299. package/build/widget/lingo-dev-widget.mjs.map +1 -0
  300. package/package.json +189 -0
@@ -0,0 +1,152 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_api = require('../api.cjs');
3
+ const require_prompt = require('./prompt.cjs');
4
+ const require_parse_xml = require('../parse-xml.cjs');
5
+ const require_shots = require('./shots.cjs');
6
+ const require_model_factory = require('./model-factory.cjs');
7
+ const require_timeout = require('../../utils/timeout.cjs');
8
+ let ai = require("ai");
9
+ let lingo_dev_sdk = require("lingo.dev/sdk");
10
+
11
+ //#region src/translators/lingo/service.ts
12
+ /**
13
+ * Lingo translator using AI models
14
+ */
15
+ var Service = class {
16
+ validatedKeys;
17
+ constructor(config, logger) {
18
+ this.config = config;
19
+ this.logger = logger;
20
+ this.logger.info("Validating API keys for translation...");
21
+ this.validatedKeys = require_model_factory.validateAndGetApiKeys(config.models);
22
+ this.logger.info("✅ API keys validated successfully");
23
+ }
24
+ /**
25
+ * Translate multiple entries
26
+ */
27
+ async translate(locale, entriesMap) {
28
+ this.logger.debug(`[TRACE-LINGO] translate() called for ${locale} with ${Object.keys(entriesMap).length} entries`);
29
+ const sourceDictionary = require_api.dictionaryFrom(this.config.sourceLocale, Object.fromEntries(Object.entries(entriesMap).map(([hash, entry]) => [hash, entry.text])));
30
+ this.logger.debug(`[TRACE-LINGO] Created source dictionary with ${Object.keys(sourceDictionary.entries).length} entries`);
31
+ return (await this.translateDictionary(sourceDictionary, locale)).entries || {};
32
+ }
33
+ /**
34
+ * Translate a complete dictionary
35
+ */
36
+ async translateDictionary(sourceDictionary, targetLocale) {
37
+ this.logger.debug(`[TRACE-LINGO] Chunking dictionary with ${Object.keys(sourceDictionary.entries).length} entries`);
38
+ const chunks = this.chunkDictionary(sourceDictionary);
39
+ this.logger.debug(`[TRACE-LINGO] Split into ${chunks.length} chunks`);
40
+ const translatedChunks = [];
41
+ for (let i = 0; i < chunks.length; i++) {
42
+ const chunk = chunks[i];
43
+ this.logger.debug(`[TRACE-LINGO] Translating chunk ${i + 1}/${chunks.length} with ${Object.keys(chunk.entries).length} entries`);
44
+ const chunkStartTime = performance.now();
45
+ const translatedChunk = await this.translateChunk(chunk, targetLocale);
46
+ const chunkEndTime = performance.now();
47
+ this.logger.debug(`[TRACE-LINGO] Chunk ${i + 1}/${chunks.length} completed in ${(chunkEndTime - chunkStartTime).toFixed(2)}ms`);
48
+ translatedChunks.push(translatedChunk);
49
+ }
50
+ this.logger.debug(`[TRACE-LINGO] All chunks translated, merging results`);
51
+ const result = this.mergeDictionaries(translatedChunks);
52
+ this.logger.debug(`[TRACE-LINGO] Merge completed, final dictionary has ${Object.keys(result.entries).length} entries`);
53
+ return result;
54
+ }
55
+ /**
56
+ * Translate a single chunk
57
+ */
58
+ async translateChunk(sourceDictionary, targetLocale) {
59
+ if (this.config.models === "lingo.dev") return this.translateWithLingoDotDev(sourceDictionary, targetLocale);
60
+ else return this.translateWithLLM(sourceDictionary, targetLocale);
61
+ }
62
+ /**
63
+ * Translate using Lingo.dev Engine
64
+ * Times out after 60 seconds to prevent indefinite hangs
65
+ */
66
+ async translateWithLingoDotDev(sourceDictionary, targetLocale) {
67
+ const apiKey = this.validatedKeys["lingo.dev"];
68
+ if (!apiKey) throw new Error("Internal error: Lingo.dev API key not found after validation. Please restart the service.");
69
+ this.logger.info(`Using Lingo.dev Engine to localize from "${this.config.sourceLocale}" to "${targetLocale}"`);
70
+ const engine = new lingo_dev_sdk.LingoDotDevEngine({ apiKey });
71
+ try {
72
+ return await require_timeout.withTimeout(engine.localizeObject(sourceDictionary, {
73
+ sourceLocale: this.config.sourceLocale,
74
+ targetLocale
75
+ }), require_timeout.DEFAULT_TIMEOUTS.AI_API, `Lingo.dev API translation to ${targetLocale}`);
76
+ } catch (error) {
77
+ this.logger.error(`translateWithLingoDotDev() failed:`, error);
78
+ throw new Error(`Lingo.dev translation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
79
+ }
80
+ }
81
+ /**
82
+ * Translate using generic LLM
83
+ * Times out after 60 seconds to prevent indefinite hangs
84
+ */
85
+ async translateWithLLM(sourceDictionary, targetLocale) {
86
+ const localeModel = require_model_factory.getLocaleModel(this.config.models, this.config.sourceLocale, targetLocale);
87
+ if (!localeModel) throw new Error(`No model configured for translation from ${this.config.sourceLocale} to ${targetLocale}`);
88
+ this.logger.info(`Using LLM ("${localeModel.provider}":"${localeModel.name}") to translate from "${this.config.sourceLocale}" to "${targetLocale}"`);
89
+ const aiModel = require_model_factory.createAiModel(localeModel, this.validatedKeys);
90
+ try {
91
+ return require_parse_xml.parseXmlFromResponseText((await require_timeout.withTimeout((0, ai.generateText)({
92
+ model: aiModel,
93
+ messages: [
94
+ {
95
+ role: "system",
96
+ content: require_prompt.getSystemPrompt({
97
+ sourceLocale: this.config.sourceLocale,
98
+ targetLocale,
99
+ prompt: this.config.prompt
100
+ })
101
+ },
102
+ ...require_shots.shots.flatMap((shotsTuple) => [{
103
+ role: "user",
104
+ content: require_parse_xml.obj2xml(shotsTuple[0])
105
+ }, {
106
+ role: "assistant",
107
+ content: require_parse_xml.obj2xml(shotsTuple[1])
108
+ }]),
109
+ {
110
+ role: "user",
111
+ content: require_parse_xml.obj2xml(sourceDictionary)
112
+ }
113
+ ]
114
+ }), require_timeout.DEFAULT_TIMEOUTS.AI_API, `${localeModel.provider} LLM translation to ${targetLocale}`)).text);
115
+ } catch (error) {
116
+ throw new Error(`LLM translation failed with ${localeModel.provider}: ${error instanceof Error ? error.message : "Unknown error"}`);
117
+ }
118
+ }
119
+ /**
120
+ * Split dictionary into chunks for processing
121
+ */
122
+ chunkDictionary(dictionary) {
123
+ const MAX_ENTRIES_PER_CHUNK = 100;
124
+ const { entries, ...rest } = dictionary;
125
+ const chunks = [];
126
+ const entryPairs = Object.entries(entries);
127
+ for (let i = 0; i < entryPairs.length; i += MAX_ENTRIES_PER_CHUNK) {
128
+ const chunkEntries = entryPairs.slice(i, i + MAX_ENTRIES_PER_CHUNK);
129
+ chunks.push({
130
+ ...rest,
131
+ entries: Object.fromEntries(chunkEntries)
132
+ });
133
+ }
134
+ return chunks;
135
+ }
136
+ /**
137
+ * Merge multiple dictionaries into one
138
+ */
139
+ mergeDictionaries(dictionaries) {
140
+ if (dictionaries.length === 0) return require_api.dictionaryFrom(this.config.sourceLocale, {});
141
+ const mergedEntries = {};
142
+ for (const dict of dictionaries) Object.assign(mergedEntries, dict.entries);
143
+ return {
144
+ version: dictionaries[0].version,
145
+ locale: dictionaries[0].locale,
146
+ entries: mergedEntries
147
+ };
148
+ }
149
+ };
150
+
151
+ //#endregion
152
+ exports.Service = Service;
@@ -0,0 +1,152 @@
1
+ import { dictionaryFrom } from "../api.mjs";
2
+ import { getSystemPrompt } from "./prompt.mjs";
3
+ import { obj2xml, parseXmlFromResponseText } from "../parse-xml.mjs";
4
+ import { shots } from "./shots.mjs";
5
+ import { createAiModel, getLocaleModel, validateAndGetApiKeys } from "./model-factory.mjs";
6
+ import { DEFAULT_TIMEOUTS, withTimeout } from "../../utils/timeout.mjs";
7
+ import { generateText } from "ai";
8
+ import { LingoDotDevEngine } from "lingo.dev/sdk";
9
+
10
+ //#region src/translators/lingo/service.ts
11
+ /**
12
+ * Lingo translator using AI models
13
+ */
14
+ var Service = class {
15
+ validatedKeys;
16
+ constructor(config, logger) {
17
+ this.config = config;
18
+ this.logger = logger;
19
+ this.logger.info("Validating API keys for translation...");
20
+ this.validatedKeys = validateAndGetApiKeys(config.models);
21
+ this.logger.info("✅ API keys validated successfully");
22
+ }
23
+ /**
24
+ * Translate multiple entries
25
+ */
26
+ async translate(locale, entriesMap) {
27
+ this.logger.debug(`[TRACE-LINGO] translate() called for ${locale} with ${Object.keys(entriesMap).length} entries`);
28
+ const sourceDictionary = dictionaryFrom(this.config.sourceLocale, Object.fromEntries(Object.entries(entriesMap).map(([hash, entry]) => [hash, entry.text])));
29
+ this.logger.debug(`[TRACE-LINGO] Created source dictionary with ${Object.keys(sourceDictionary.entries).length} entries`);
30
+ return (await this.translateDictionary(sourceDictionary, locale)).entries || {};
31
+ }
32
+ /**
33
+ * Translate a complete dictionary
34
+ */
35
+ async translateDictionary(sourceDictionary, targetLocale) {
36
+ this.logger.debug(`[TRACE-LINGO] Chunking dictionary with ${Object.keys(sourceDictionary.entries).length} entries`);
37
+ const chunks = this.chunkDictionary(sourceDictionary);
38
+ this.logger.debug(`[TRACE-LINGO] Split into ${chunks.length} chunks`);
39
+ const translatedChunks = [];
40
+ for (let i = 0; i < chunks.length; i++) {
41
+ const chunk = chunks[i];
42
+ this.logger.debug(`[TRACE-LINGO] Translating chunk ${i + 1}/${chunks.length} with ${Object.keys(chunk.entries).length} entries`);
43
+ const chunkStartTime = performance.now();
44
+ const translatedChunk = await this.translateChunk(chunk, targetLocale);
45
+ const chunkEndTime = performance.now();
46
+ this.logger.debug(`[TRACE-LINGO] Chunk ${i + 1}/${chunks.length} completed in ${(chunkEndTime - chunkStartTime).toFixed(2)}ms`);
47
+ translatedChunks.push(translatedChunk);
48
+ }
49
+ this.logger.debug(`[TRACE-LINGO] All chunks translated, merging results`);
50
+ const result = this.mergeDictionaries(translatedChunks);
51
+ this.logger.debug(`[TRACE-LINGO] Merge completed, final dictionary has ${Object.keys(result.entries).length} entries`);
52
+ return result;
53
+ }
54
+ /**
55
+ * Translate a single chunk
56
+ */
57
+ async translateChunk(sourceDictionary, targetLocale) {
58
+ if (this.config.models === "lingo.dev") return this.translateWithLingoDotDev(sourceDictionary, targetLocale);
59
+ else return this.translateWithLLM(sourceDictionary, targetLocale);
60
+ }
61
+ /**
62
+ * Translate using Lingo.dev Engine
63
+ * Times out after 60 seconds to prevent indefinite hangs
64
+ */
65
+ async translateWithLingoDotDev(sourceDictionary, targetLocale) {
66
+ const apiKey = this.validatedKeys["lingo.dev"];
67
+ if (!apiKey) throw new Error("Internal error: Lingo.dev API key not found after validation. Please restart the service.");
68
+ this.logger.info(`Using Lingo.dev Engine to localize from "${this.config.sourceLocale}" to "${targetLocale}"`);
69
+ const engine = new LingoDotDevEngine({ apiKey });
70
+ try {
71
+ return await withTimeout(engine.localizeObject(sourceDictionary, {
72
+ sourceLocale: this.config.sourceLocale,
73
+ targetLocale
74
+ }), DEFAULT_TIMEOUTS.AI_API, `Lingo.dev API translation to ${targetLocale}`);
75
+ } catch (error) {
76
+ this.logger.error(`translateWithLingoDotDev() failed:`, error);
77
+ throw new Error(`Lingo.dev translation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
78
+ }
79
+ }
80
+ /**
81
+ * Translate using generic LLM
82
+ * Times out after 60 seconds to prevent indefinite hangs
83
+ */
84
+ async translateWithLLM(sourceDictionary, targetLocale) {
85
+ const localeModel = getLocaleModel(this.config.models, this.config.sourceLocale, targetLocale);
86
+ if (!localeModel) throw new Error(`No model configured for translation from ${this.config.sourceLocale} to ${targetLocale}`);
87
+ this.logger.info(`Using LLM ("${localeModel.provider}":"${localeModel.name}") to translate from "${this.config.sourceLocale}" to "${targetLocale}"`);
88
+ const aiModel = createAiModel(localeModel, this.validatedKeys);
89
+ try {
90
+ return parseXmlFromResponseText((await withTimeout(generateText({
91
+ model: aiModel,
92
+ messages: [
93
+ {
94
+ role: "system",
95
+ content: getSystemPrompt({
96
+ sourceLocale: this.config.sourceLocale,
97
+ targetLocale,
98
+ prompt: this.config.prompt
99
+ })
100
+ },
101
+ ...shots.flatMap((shotsTuple) => [{
102
+ role: "user",
103
+ content: obj2xml(shotsTuple[0])
104
+ }, {
105
+ role: "assistant",
106
+ content: obj2xml(shotsTuple[1])
107
+ }]),
108
+ {
109
+ role: "user",
110
+ content: obj2xml(sourceDictionary)
111
+ }
112
+ ]
113
+ }), DEFAULT_TIMEOUTS.AI_API, `${localeModel.provider} LLM translation to ${targetLocale}`)).text);
114
+ } catch (error) {
115
+ throw new Error(`LLM translation failed with ${localeModel.provider}: ${error instanceof Error ? error.message : "Unknown error"}`);
116
+ }
117
+ }
118
+ /**
119
+ * Split dictionary into chunks for processing
120
+ */
121
+ chunkDictionary(dictionary) {
122
+ const MAX_ENTRIES_PER_CHUNK = 100;
123
+ const { entries, ...rest } = dictionary;
124
+ const chunks = [];
125
+ const entryPairs = Object.entries(entries);
126
+ for (let i = 0; i < entryPairs.length; i += MAX_ENTRIES_PER_CHUNK) {
127
+ const chunkEntries = entryPairs.slice(i, i + MAX_ENTRIES_PER_CHUNK);
128
+ chunks.push({
129
+ ...rest,
130
+ entries: Object.fromEntries(chunkEntries)
131
+ });
132
+ }
133
+ return chunks;
134
+ }
135
+ /**
136
+ * Merge multiple dictionaries into one
137
+ */
138
+ mergeDictionaries(dictionaries) {
139
+ if (dictionaries.length === 0) return dictionaryFrom(this.config.sourceLocale, {});
140
+ const mergedEntries = {};
141
+ for (const dict of dictionaries) Object.assign(mergedEntries, dict.entries);
142
+ return {
143
+ version: dictionaries[0].version,
144
+ locale: dictionaries[0].locale,
145
+ entries: mergedEntries
146
+ };
147
+ }
148
+ };
149
+
150
+ //#endregion
151
+ export { Service };
152
+ //# sourceMappingURL=service.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.mjs","names":["config: LingoTranslatorConfig","logger: Logger","sourceDictionary: DictionarySchema","translatedChunks: DictionarySchema[]","chunks: DictionarySchema[]","mergedEntries: Record<string, string>"],"sources":["../../../src/translators/lingo/service.ts"],"sourcesContent":["import { generateText } from \"ai\";\nimport { LingoDotDevEngine } from \"lingo.dev/sdk\";\nimport {\n dictionaryFrom,\n type DictionarySchema,\n type TranslatableEntry,\n type Translator,\n} from \"../api\";\nimport { getSystemPrompt } from \"./prompt\";\nimport { obj2xml, parseXmlFromResponseText } from \"../parse-xml\";\nimport { shots } from \"./shots\";\nimport {\n createAiModel,\n getLocaleModel,\n validateAndGetApiKeys,\n type ValidatedApiKeys,\n} from \"./model-factory\";\nimport { Logger } from \"../../utils/logger\";\nimport { DEFAULT_TIMEOUTS, withTimeout } from \"../../utils/timeout\";\nimport type { LocaleCode } from \"lingo.dev/spec\";\n\n/**\n * Lingo Translator configuration\n */\nexport interface LingoTranslatorConfig {\n models: \"lingo.dev\" | Record<string, string>;\n sourceLocale: LocaleCode;\n prompt?: string;\n}\n\n/**\n * Lingo translator using AI models\n */\nexport class Service implements Translator<LingoTranslatorConfig> {\n private readonly validatedKeys: ValidatedApiKeys;\n\n constructor(\n readonly config: LingoTranslatorConfig,\n private logger: Logger,\n ) {\n this.logger.info(\"Validating API keys for translation...\");\n this.validatedKeys = validateAndGetApiKeys(config.models);\n this.logger.info(\"✅ API keys validated successfully\");\n }\n\n /**\n * Translate multiple entries\n */\n async translate(\n locale: LocaleCode,\n entriesMap: Record<string, TranslatableEntry>,\n ): Promise<Record<string, string>> {\n this.logger.debug(\n `[TRACE-LINGO] translate() called for ${locale} with ${Object.keys(entriesMap).length} entries`,\n );\n\n const sourceDictionary: DictionarySchema = dictionaryFrom(\n this.config.sourceLocale,\n Object.fromEntries(\n Object.entries(entriesMap).map(([hash, entry]) => [hash, entry.text]),\n ),\n );\n\n this.logger.debug(\n `[TRACE-LINGO] Created source dictionary with ${Object.keys(sourceDictionary.entries).length} entries`,\n );\n const translated = await this.translateDictionary(sourceDictionary, locale);\n\n return translated.entries || {};\n }\n\n /**\n * Translate a complete dictionary\n */\n private async translateDictionary(\n sourceDictionary: DictionarySchema,\n targetLocale: string,\n ): Promise<DictionarySchema> {\n this.logger.debug(\n `[TRACE-LINGO] Chunking dictionary with ${Object.keys(sourceDictionary.entries).length} entries`,\n );\n const chunks = this.chunkDictionary(sourceDictionary);\n this.logger.debug(`[TRACE-LINGO] Split into ${chunks.length} chunks`);\n\n const translatedChunks: DictionarySchema[] = [];\n\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n this.logger.debug(\n `[TRACE-LINGO] Translating chunk ${i + 1}/${chunks.length} with ${Object.keys(chunk.entries).length} entries`,\n );\n const chunkStartTime = performance.now();\n\n const translatedChunk = await this.translateChunk(chunk, targetLocale);\n\n const chunkEndTime = performance.now();\n this.logger.debug(\n `[TRACE-LINGO] Chunk ${i + 1}/${chunks.length} completed in ${(chunkEndTime - chunkStartTime).toFixed(2)}ms`,\n );\n\n translatedChunks.push(translatedChunk);\n }\n\n this.logger.debug(`[TRACE-LINGO] All chunks translated, merging results`);\n const result = this.mergeDictionaries(translatedChunks);\n this.logger.debug(\n `[TRACE-LINGO] Merge completed, final dictionary has ${Object.keys(result.entries).length} entries`,\n );\n\n return result;\n }\n\n /**\n * Translate a single chunk\n */\n private async translateChunk(\n sourceDictionary: DictionarySchema,\n targetLocale: string,\n ): Promise<DictionarySchema> {\n if (this.config.models === \"lingo.dev\") {\n return this.translateWithLingoDotDev(sourceDictionary, targetLocale);\n } else {\n return this.translateWithLLM(sourceDictionary, targetLocale);\n }\n }\n\n /**\n * Translate using Lingo.dev Engine\n * Times out after 60 seconds to prevent indefinite hangs\n */\n private async translateWithLingoDotDev(\n sourceDictionary: DictionarySchema,\n targetLocale: string,\n ): Promise<DictionarySchema> {\n const apiKey = this.validatedKeys[\"lingo.dev\"];\n if (!apiKey) {\n throw new Error(\n \"Internal error: Lingo.dev API key not found after validation. Please restart the service.\",\n );\n }\n\n this.logger.info(\n `Using Lingo.dev Engine to localize from \"${this.config.sourceLocale}\" to \"${targetLocale}\"`,\n );\n\n const engine = new LingoDotDevEngine({ apiKey });\n\n try {\n const result = await withTimeout(\n engine.localizeObject(sourceDictionary, {\n sourceLocale: this.config.sourceLocale,\n targetLocale: targetLocale,\n }),\n DEFAULT_TIMEOUTS.AI_API,\n `Lingo.dev API translation to ${targetLocale}`,\n );\n\n return result as DictionarySchema;\n } catch (error) {\n this.logger.error(`translateWithLingoDotDev() failed:`, error);\n throw new Error(\n `Lingo.dev translation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n /**\n * Translate using generic LLM\n * Times out after 60 seconds to prevent indefinite hangs\n */\n private async translateWithLLM(\n sourceDictionary: DictionarySchema,\n targetLocale: string,\n ): Promise<DictionarySchema> {\n const localeModel = getLocaleModel(\n this.config.models as Record<string, string>,\n this.config.sourceLocale,\n targetLocale,\n );\n\n if (!localeModel) {\n throw new Error(\n `No model configured for translation from ${this.config.sourceLocale} to ${targetLocale}`,\n );\n }\n\n this.logger.info(\n `Using LLM (\"${localeModel.provider}\":\"${localeModel.name}\") to translate from \"${this.config.sourceLocale}\" to \"${targetLocale}\"`,\n );\n\n const aiModel = createAiModel(localeModel, this.validatedKeys);\n\n try {\n const response = await withTimeout(\n generateText({\n model: aiModel,\n messages: [\n {\n role: \"system\",\n content: getSystemPrompt({\n sourceLocale: this.config.sourceLocale,\n targetLocale,\n prompt: this.config.prompt,\n }),\n },\n // Add few-shot examples\n ...shots.flatMap((shotsTuple) => [\n {\n role: \"user\" as const,\n content: obj2xml(shotsTuple[0]),\n },\n {\n role: \"assistant\" as const,\n content: obj2xml(shotsTuple[1]),\n },\n ]),\n {\n role: \"user\",\n content: obj2xml(sourceDictionary),\n },\n ],\n }),\n DEFAULT_TIMEOUTS.AI_API,\n `${localeModel.provider} LLM translation to ${targetLocale}`,\n );\n\n return parseXmlFromResponseText<DictionarySchema>(response.text);\n } catch (error) {\n throw new Error(\n `LLM translation failed with ${localeModel.provider}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n /**\n * Split dictionary into chunks for processing\n */\n private chunkDictionary(dictionary: DictionarySchema): DictionarySchema[] {\n const MAX_ENTRIES_PER_CHUNK = 100;\n const { entries, ...rest } = dictionary;\n const chunks: DictionarySchema[] = [];\n\n const entryPairs = Object.entries(entries);\n\n // Split entries into chunks of MAX_ENTRIES_PER_CHUNK\n for (let i = 0; i < entryPairs.length; i += MAX_ENTRIES_PER_CHUNK) {\n const chunkEntries = entryPairs.slice(i, i + MAX_ENTRIES_PER_CHUNK);\n chunks.push({\n ...rest,\n entries: Object.fromEntries(chunkEntries),\n });\n }\n\n return chunks;\n }\n\n /**\n * Merge multiple dictionaries into one\n */\n private mergeDictionaries(\n dictionaries: DictionarySchema[],\n ): DictionarySchema {\n if (dictionaries.length === 0) {\n return dictionaryFrom(this.config.sourceLocale, {});\n }\n\n // Merge all entries from all dictionaries\n const mergedEntries: Record<string, string> = {};\n for (const dict of dictionaries) {\n Object.assign(mergedEntries, dict.entries);\n }\n\n return {\n version: dictionaries[0].version,\n locale: dictionaries[0].locale,\n entries: mergedEntries,\n };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+
2
+ //#region src/translators/lingo/shots.ts
3
+ /**
4
+ * Few-shot examples for LLM translation
5
+ * These help the LLM understand the expected format and behavior
6
+ */
7
+ const shots = [[{
8
+ version: .1,
9
+ locale: "en",
10
+ entries: {
11
+ "1z2x3c4v": "Dashboard",
12
+ "5t6y7u8i": "Settings",
13
+ "9o0p1q2r": "Logout",
14
+ "9k0l1m2n": "© 2025 Lingo.dev. All rights reserved."
15
+ }
16
+ }, {
17
+ version: .1,
18
+ locale: "es",
19
+ entries: {
20
+ "1z2x3c4v": "Panel de control",
21
+ "5t6y7u8i": "Configuración",
22
+ "9o0p1q2r": "Cerrar sesión",
23
+ "9k0l1m2n": "© 2025 Lingo.dev. Todos los derechos reservados."
24
+ }
25
+ }]];
26
+
27
+ //#endregion
28
+ exports.shots = shots;
@@ -0,0 +1,28 @@
1
+ //#region src/translators/lingo/shots.ts
2
+ /**
3
+ * Few-shot examples for LLM translation
4
+ * These help the LLM understand the expected format and behavior
5
+ */
6
+ const shots = [[{
7
+ version: .1,
8
+ locale: "en",
9
+ entries: {
10
+ "1z2x3c4v": "Dashboard",
11
+ "5t6y7u8i": "Settings",
12
+ "9o0p1q2r": "Logout",
13
+ "9k0l1m2n": "© 2025 Lingo.dev. All rights reserved."
14
+ }
15
+ }, {
16
+ version: .1,
17
+ locale: "es",
18
+ entries: {
19
+ "1z2x3c4v": "Panel de control",
20
+ "5t6y7u8i": "Configuración",
21
+ "9o0p1q2r": "Cerrar sesión",
22
+ "9k0l1m2n": "© 2025 Lingo.dev. Todos los derechos reservados."
23
+ }
24
+ }]];
25
+
26
+ //#endregion
27
+ export { shots };
28
+ //# sourceMappingURL=shots.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shots.mjs","names":["shots: [DictionarySchema, DictionarySchema][]"],"sources":["../../../src/translators/lingo/shots.ts"],"sourcesContent":["import type { DictionarySchema } from \"../api\";\n\n/**\n * Few-shot examples for LLM translation\n * These help the LLM understand the expected format and behavior\n */\nexport const shots: [DictionarySchema, DictionarySchema][] = [\n [\n {\n version: 0.1,\n locale: \"en\",\n entries: {\n \"1z2x3c4v\": \"Dashboard\",\n \"5t6y7u8i\": \"Settings\",\n \"9o0p1q2r\": \"Logout\",\n \"9k0l1m2n\": \"© 2025 Lingo.dev. All rights reserved.\",\n },\n },\n {\n version: 0.1,\n locale: \"es\",\n entries: {\n \"1z2x3c4v\": \"Panel de control\",\n \"5t6y7u8i\": \"Configuración\",\n \"9o0p1q2r\": \"Cerrar sesión\",\n \"9k0l1m2n\": \"© 2025 Lingo.dev. Todos los derechos reservados.\",\n },\n },\n ],\n];\n"],"mappings":";;;;;AAMA,MAAaA,QAAgD,CAC3D,CACE;CACE,SAAS;CACT,QAAQ;CACR,SAAS;EACP,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ,YAAY;EACb;CACF,EACD;CACE,SAAS;CACT,QAAQ;CACR,SAAS;EACP,YAAY;EACZ,YAAY;EACZ,YAAY;EACZ,YAAY;EACb;CACF,CACF,CACF"}
@@ -0,0 +1,115 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_api = require('./api.cjs');
3
+ const require_timeout = require('../utils/timeout.cjs');
4
+ let fs_promises = require("fs/promises");
5
+ fs_promises = require_rolldown_runtime.__toESM(fs_promises);
6
+ let path = require("path");
7
+ path = require_rolldown_runtime.__toESM(path);
8
+
9
+ //#region src/translators/local-cache.ts
10
+ /**
11
+ * Local disk-based translation cache implementation
12
+ */
13
+ /**
14
+ * Local file system cache for translations
15
+ * Stores translations as JSON files in .lingo/cache/
16
+ */
17
+ var LocalTranslationCache = class {
18
+ config;
19
+ constructor(config, logger) {
20
+ this.logger = logger;
21
+ this.config = config;
22
+ }
23
+ getCachePath(locale) {
24
+ return path.join(this.config.cacheDir, `${locale}.json`);
25
+ }
26
+ /**
27
+ * Read dictionary file from disk
28
+ * Times out after 10 seconds to prevent indefinite hangs
29
+ */
30
+ async getDictionary(locale) {
31
+ try {
32
+ const cachePath = this.getCachePath(locale);
33
+ const content = await require_timeout.withTimeout(fs_promises.readFile(cachePath, "utf-8"), require_timeout.DEFAULT_TIMEOUTS.FILE_IO, `Read cache for ${locale}`);
34
+ return JSON.parse(content);
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+ /**
40
+ * Write dictionary file to disk
41
+ * Times out after 10 seconds to prevent indefinite hangs
42
+ */
43
+ async setDictionary(locale, dictionary) {
44
+ try {
45
+ const cachePath = this.getCachePath(locale);
46
+ const cacheDir = path.dirname(cachePath);
47
+ await require_timeout.withTimeout(fs_promises.mkdir(cacheDir, { recursive: true }), require_timeout.DEFAULT_TIMEOUTS.FILE_IO, `Create cache directory for ${locale}`);
48
+ await require_timeout.withTimeout(fs_promises.writeFile(cachePath, JSON.stringify(dictionary, null, 2), "utf-8"), require_timeout.DEFAULT_TIMEOUTS.FILE_IO, `Write cache for ${locale}`);
49
+ } catch (error) {
50
+ this.logger.error(`Failed to write cache for locale ${locale}:`, error);
51
+ throw error;
52
+ }
53
+ }
54
+ /**
55
+ * Get cached translations for a locale
56
+ */
57
+ async get(locale, hashes) {
58
+ const dictionary = await this.getDictionary(locale);
59
+ if (!dictionary) return {};
60
+ if (hashes) return hashes.reduce((acc, hash) => ({
61
+ ...acc,
62
+ [hash]: dictionary.entries[hash]
63
+ }), {});
64
+ return dictionary.entries || {};
65
+ }
66
+ /**
67
+ * Update cache with new translations (merge)
68
+ */
69
+ async update(locale, translations) {
70
+ const merged = {
71
+ ...await this.get(locale),
72
+ ...translations
73
+ };
74
+ await this.set(locale, merged);
75
+ }
76
+ /**
77
+ * Replace entire cache for a locale
78
+ */
79
+ async set(locale, translations) {
80
+ await this.setDictionary(locale, require_api.dictionaryFrom(locale, translations));
81
+ }
82
+ /**
83
+ * Check if cache exists for a locale
84
+ */
85
+ async has(locale) {
86
+ try {
87
+ const cachePath = this.getCachePath(locale);
88
+ await fs_promises.access(cachePath);
89
+ return true;
90
+ } catch {
91
+ return false;
92
+ }
93
+ }
94
+ /**
95
+ * Clear cache for a specific locale
96
+ */
97
+ async clear(locale) {
98
+ try {
99
+ const cachePath = this.getCachePath(locale);
100
+ await fs_promises.unlink(cachePath);
101
+ } catch {}
102
+ }
103
+ /**
104
+ * Clear all cached translations
105
+ */
106
+ async clearAll() {
107
+ try {
108
+ const files = await fs_promises.readdir(this.config.cacheDir);
109
+ await Promise.all(files.filter((file) => file.endsWith(".json")).map((file) => fs_promises.unlink(path.join(this.config.cacheDir, file))));
110
+ } catch {}
111
+ }
112
+ };
113
+
114
+ //#endregion
115
+ exports.LocalTranslationCache = LocalTranslationCache;
@@ -0,0 +1,113 @@
1
+ import { dictionaryFrom } from "./api.mjs";
2
+ import { DEFAULT_TIMEOUTS, withTimeout } from "../utils/timeout.mjs";
3
+ import * as fs from "fs/promises";
4
+ import * as path$1 from "path";
5
+
6
+ //#region src/translators/local-cache.ts
7
+ /**
8
+ * Local disk-based translation cache implementation
9
+ */
10
+ /**
11
+ * Local file system cache for translations
12
+ * Stores translations as JSON files in .lingo/cache/
13
+ */
14
+ var LocalTranslationCache = class {
15
+ config;
16
+ constructor(config, logger) {
17
+ this.logger = logger;
18
+ this.config = config;
19
+ }
20
+ getCachePath(locale) {
21
+ return path$1.join(this.config.cacheDir, `${locale}.json`);
22
+ }
23
+ /**
24
+ * Read dictionary file from disk
25
+ * Times out after 10 seconds to prevent indefinite hangs
26
+ */
27
+ async getDictionary(locale) {
28
+ try {
29
+ const cachePath = this.getCachePath(locale);
30
+ const content = await withTimeout(fs.readFile(cachePath, "utf-8"), DEFAULT_TIMEOUTS.FILE_IO, `Read cache for ${locale}`);
31
+ return JSON.parse(content);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ /**
37
+ * Write dictionary file to disk
38
+ * Times out after 10 seconds to prevent indefinite hangs
39
+ */
40
+ async setDictionary(locale, dictionary) {
41
+ try {
42
+ const cachePath = this.getCachePath(locale);
43
+ const cacheDir = path$1.dirname(cachePath);
44
+ await withTimeout(fs.mkdir(cacheDir, { recursive: true }), DEFAULT_TIMEOUTS.FILE_IO, `Create cache directory for ${locale}`);
45
+ await withTimeout(fs.writeFile(cachePath, JSON.stringify(dictionary, null, 2), "utf-8"), DEFAULT_TIMEOUTS.FILE_IO, `Write cache for ${locale}`);
46
+ } catch (error) {
47
+ this.logger.error(`Failed to write cache for locale ${locale}:`, error);
48
+ throw error;
49
+ }
50
+ }
51
+ /**
52
+ * Get cached translations for a locale
53
+ */
54
+ async get(locale, hashes) {
55
+ const dictionary = await this.getDictionary(locale);
56
+ if (!dictionary) return {};
57
+ if (hashes) return hashes.reduce((acc, hash) => ({
58
+ ...acc,
59
+ [hash]: dictionary.entries[hash]
60
+ }), {});
61
+ return dictionary.entries || {};
62
+ }
63
+ /**
64
+ * Update cache with new translations (merge)
65
+ */
66
+ async update(locale, translations) {
67
+ const merged = {
68
+ ...await this.get(locale),
69
+ ...translations
70
+ };
71
+ await this.set(locale, merged);
72
+ }
73
+ /**
74
+ * Replace entire cache for a locale
75
+ */
76
+ async set(locale, translations) {
77
+ await this.setDictionary(locale, dictionaryFrom(locale, translations));
78
+ }
79
+ /**
80
+ * Check if cache exists for a locale
81
+ */
82
+ async has(locale) {
83
+ try {
84
+ const cachePath = this.getCachePath(locale);
85
+ await fs.access(cachePath);
86
+ return true;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Clear cache for a specific locale
93
+ */
94
+ async clear(locale) {
95
+ try {
96
+ const cachePath = this.getCachePath(locale);
97
+ await fs.unlink(cachePath);
98
+ } catch {}
99
+ }
100
+ /**
101
+ * Clear all cached translations
102
+ */
103
+ async clearAll() {
104
+ try {
105
+ const files = await fs.readdir(this.config.cacheDir);
106
+ await Promise.all(files.filter((file) => file.endsWith(".json")).map((file) => fs.unlink(path$1.join(this.config.cacheDir, file))));
107
+ } catch {}
108
+ }
109
+ };
110
+
111
+ //#endregion
112
+ export { LocalTranslationCache };
113
+ //# sourceMappingURL=local-cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-cache.mjs","names":["logger: Logger","path"],"sources":["../../src/translators/local-cache.ts"],"sourcesContent":["/**\n * Local disk-based translation cache implementation\n */\n\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type { LocalCacheConfig, TranslationCache } from \"./cache\";\nimport { dictionaryFrom, type DictionarySchema } from \"./api\";\nimport { DEFAULT_TIMEOUTS, withTimeout } from \"../utils/timeout\";\nimport type { Logger } from \"../utils/logger\";\nimport type { LocaleCode } from \"lingo.dev/spec\";\n\n/**\n * Local file system cache for translations\n * Stores translations as JSON files in .lingo/cache/\n */\nexport class LocalTranslationCache implements TranslationCache {\n private config: LocalCacheConfig;\n\n constructor(\n config: LocalCacheConfig,\n private logger: Logger,\n ) {\n this.config = config;\n }\n\n private getCachePath(locale: LocaleCode): string {\n return path.join(this.config.cacheDir, `${locale}.json`);\n }\n\n /**\n * Read dictionary file from disk\n * Times out after 10 seconds to prevent indefinite hangs\n */\n async getDictionary(locale: LocaleCode): Promise<DictionarySchema | null> {\n try {\n const cachePath = this.getCachePath(locale);\n const content = await withTimeout(\n fs.readFile(cachePath, \"utf-8\"),\n DEFAULT_TIMEOUTS.FILE_IO,\n `Read cache for ${locale}`,\n );\n return JSON.parse(content);\n } catch {\n return null;\n }\n }\n\n /**\n * Write dictionary file to disk\n * Times out after 10 seconds to prevent indefinite hangs\n */\n private async setDictionary(\n locale: LocaleCode,\n dictionary: DictionarySchema,\n ): Promise<void> {\n try {\n const cachePath = this.getCachePath(locale);\n const cacheDir = path.dirname(cachePath);\n\n // Ensure cache directory exists\n await withTimeout(\n fs.mkdir(cacheDir, { recursive: true }),\n DEFAULT_TIMEOUTS.FILE_IO,\n `Create cache directory for ${locale}`,\n );\n\n // Write cache file\n await withTimeout(\n fs.writeFile(cachePath, JSON.stringify(dictionary, null, 2), \"utf-8\"),\n DEFAULT_TIMEOUTS.FILE_IO,\n `Write cache for ${locale}`,\n );\n } catch (error) {\n this.logger.error(`Failed to write cache for locale ${locale}:`, error);\n throw error;\n }\n }\n\n /**\n * Get cached translations for a locale\n */\n async get(\n locale: LocaleCode,\n hashes?: string[],\n ): Promise<Record<string, string>> {\n const dictionary = await this.getDictionary(locale);\n if (!dictionary) {\n return {};\n }\n if (hashes) {\n return hashes.reduce(\n (acc, hash) => ({ ...acc, [hash]: dictionary.entries[hash] }),\n {},\n );\n }\n return dictionary.entries || {};\n }\n\n /**\n * Update cache with new translations (merge)\n */\n async update(\n locale: LocaleCode,\n translations: Record<string, string>,\n ): Promise<void> {\n const existing = await this.get(locale);\n\n const merged = { ...existing, ...translations };\n\n await this.set(locale, merged);\n }\n\n /**\n * Replace entire cache for a locale\n */\n async set(\n locale: LocaleCode,\n translations: Record<string, string>,\n ): Promise<void> {\n await this.setDictionary(locale, dictionaryFrom(locale, translations));\n }\n\n /**\n * Check if cache exists for a locale\n */\n async has(locale: LocaleCode): Promise<boolean> {\n try {\n const cachePath = this.getCachePath(locale);\n await fs.access(cachePath);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Clear cache for a specific locale\n */\n async clear(locale: LocaleCode): Promise<void> {\n try {\n const cachePath = this.getCachePath(locale);\n await fs.unlink(cachePath);\n } catch {\n // Ignore errors if file doesn't exist\n }\n }\n\n /**\n * Clear all cached translations\n */\n async clearAll(): Promise<void> {\n try {\n const files = await fs.readdir(this.config.cacheDir);\n\n await Promise.all(\n files\n .filter((file) => file.endsWith(\".json\"))\n .map((file) => fs.unlink(path.join(this.config.cacheDir, file))),\n );\n } catch {\n // Ignore errors if directory doesn't exist\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAa,wBAAb,MAA+D;CAC7D,AAAQ;CAER,YACE,QACA,AAAQA,QACR;EADQ;AAER,OAAK,SAAS;;CAGhB,AAAQ,aAAa,QAA4B;AAC/C,SAAOC,OAAK,KAAK,KAAK,OAAO,UAAU,GAAG,OAAO,OAAO;;;;;;CAO1D,MAAM,cAAc,QAAsD;AACxE,MAAI;GACF,MAAM,YAAY,KAAK,aAAa,OAAO;GAC3C,MAAM,UAAU,MAAM,YACpB,GAAG,SAAS,WAAW,QAAQ,EAC/B,iBAAiB,SACjB,kBAAkB,SACnB;AACD,UAAO,KAAK,MAAM,QAAQ;UACpB;AACN,UAAO;;;;;;;CAQX,MAAc,cACZ,QACA,YACe;AACf,MAAI;GACF,MAAM,YAAY,KAAK,aAAa,OAAO;GAC3C,MAAM,WAAWA,OAAK,QAAQ,UAAU;AAGxC,SAAM,YACJ,GAAG,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC,EACvC,iBAAiB,SACjB,8BAA8B,SAC/B;AAGD,SAAM,YACJ,GAAG,UAAU,WAAW,KAAK,UAAU,YAAY,MAAM,EAAE,EAAE,QAAQ,EACrE,iBAAiB,SACjB,mBAAmB,SACpB;WACM,OAAO;AACd,QAAK,OAAO,MAAM,oCAAoC,OAAO,IAAI,MAAM;AACvE,SAAM;;;;;;CAOV,MAAM,IACJ,QACA,QACiC;EACjC,MAAM,aAAa,MAAM,KAAK,cAAc,OAAO;AACnD,MAAI,CAAC,WACH,QAAO,EAAE;AAEX,MAAI,OACF,QAAO,OAAO,QACX,KAAK,UAAU;GAAE,GAAG;IAAM,OAAO,WAAW,QAAQ;GAAO,GAC5D,EAAE,CACH;AAEH,SAAO,WAAW,WAAW,EAAE;;;;;CAMjC,MAAM,OACJ,QACA,cACe;EAGf,MAAM,SAAS;GAAE,GAFA,MAAM,KAAK,IAAI,OAAO;GAET,GAAG;GAAc;AAE/C,QAAM,KAAK,IAAI,QAAQ,OAAO;;;;;CAMhC,MAAM,IACJ,QACA,cACe;AACf,QAAM,KAAK,cAAc,QAAQ,eAAe,QAAQ,aAAa,CAAC;;;;;CAMxE,MAAM,IAAI,QAAsC;AAC9C,MAAI;GACF,MAAM,YAAY,KAAK,aAAa,OAAO;AAC3C,SAAM,GAAG,OAAO,UAAU;AAC1B,UAAO;UACD;AACN,UAAO;;;;;;CAOX,MAAM,MAAM,QAAmC;AAC7C,MAAI;GACF,MAAM,YAAY,KAAK,aAAa,OAAO;AAC3C,SAAM,GAAG,OAAO,UAAU;UACpB;;;;;CAQV,MAAM,WAA0B;AAC9B,MAAI;GACF,MAAM,QAAQ,MAAM,GAAG,QAAQ,KAAK,OAAO,SAAS;AAEpD,SAAM,QAAQ,IACZ,MACG,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,CACxC,KAAK,SAAS,GAAG,OAAOA,OAAK,KAAK,KAAK,OAAO,UAAU,KAAK,CAAC,CAAC,CACnE;UACK"}