ai-i18n-tools 1.0.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 (260) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/dist/api/openrouter.d.ts +115 -0
  4. package/dist/api/openrouter.d.ts.map +1 -0
  5. package/dist/api/openrouter.js +399 -0
  6. package/dist/api/openrouter.js.map +1 -0
  7. package/dist/cli/doc-translate.d.ts +90 -0
  8. package/dist/cli/doc-translate.d.ts.map +1 -0
  9. package/dist/cli/doc-translate.js +1153 -0
  10. package/dist/cli/doc-translate.js.map +1 -0
  11. package/dist/cli/export-ui-xliff.d.ts +32 -0
  12. package/dist/cli/export-ui-xliff.d.ts.map +1 -0
  13. package/dist/cli/export-ui-xliff.js +153 -0
  14. package/dist/cli/export-ui-xliff.js.map +1 -0
  15. package/dist/cli/extract-strings.d.ts +12 -0
  16. package/dist/cli/extract-strings.d.ts.map +1 -0
  17. package/dist/cli/extract-strings.js +80 -0
  18. package/dist/cli/extract-strings.js.map +1 -0
  19. package/dist/cli/file-utils.d.ts +10 -0
  20. package/dist/cli/file-utils.d.ts.map +1 -0
  21. package/dist/cli/file-utils.js +77 -0
  22. package/dist/cli/file-utils.js.map +1 -0
  23. package/dist/cli/format.d.ts +21 -0
  24. package/dist/cli/format.d.ts.map +1 -0
  25. package/dist/cli/format.js +75 -0
  26. package/dist/cli/format.js.map +1 -0
  27. package/dist/cli/helpers.d.ts +27 -0
  28. package/dist/cli/helpers.d.ts.map +1 -0
  29. package/dist/cli/helpers.js +84 -0
  30. package/dist/cli/helpers.js.map +1 -0
  31. package/dist/cli/index.d.ts +3 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/index.js +772 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/cli/log-output.d.ts +13 -0
  36. package/dist/cli/log-output.d.ts.map +1 -0
  37. package/dist/cli/log-output.js +75 -0
  38. package/dist/cli/log-output.js.map +1 -0
  39. package/dist/cli/translate-svg.d.ts +7 -0
  40. package/dist/cli/translate-svg.d.ts.map +1 -0
  41. package/dist/cli/translate-svg.js +167 -0
  42. package/dist/cli/translate-svg.js.map +1 -0
  43. package/dist/cli/translate-ui-strings.d.ts +27 -0
  44. package/dist/cli/translate-ui-strings.d.ts.map +1 -0
  45. package/dist/cli/translate-ui-strings.js +357 -0
  46. package/dist/cli/translate-ui-strings.js.map +1 -0
  47. package/dist/core/cache-tracking-keys.d.ts +12 -0
  48. package/dist/core/cache-tracking-keys.d.ts.map +1 -0
  49. package/dist/core/cache-tracking-keys.js +20 -0
  50. package/dist/core/cache-tracking-keys.js.map +1 -0
  51. package/dist/core/cache.d.ts +153 -0
  52. package/dist/core/cache.d.ts.map +1 -0
  53. package/dist/core/cache.js +546 -0
  54. package/dist/core/cache.js.map +1 -0
  55. package/dist/core/config.d.ts +58 -0
  56. package/dist/core/config.d.ts.map +1 -0
  57. package/dist/core/config.js +392 -0
  58. package/dist/core/config.js.map +1 -0
  59. package/dist/core/doc-file-tracking.d.ts +8 -0
  60. package/dist/core/doc-file-tracking.d.ts.map +1 -0
  61. package/dist/core/doc-file-tracking.js +27 -0
  62. package/dist/core/doc-file-tracking.js.map +1 -0
  63. package/dist/core/errors.d.ts +19 -0
  64. package/dist/core/errors.d.ts.map +1 -0
  65. package/dist/core/errors.js +23 -0
  66. package/dist/core/errors.js.map +1 -0
  67. package/dist/core/locale-utils.d.ts +20 -0
  68. package/dist/core/locale-utils.d.ts.map +1 -0
  69. package/dist/core/locale-utils.js +75 -0
  70. package/dist/core/locale-utils.js.map +1 -0
  71. package/dist/core/output-paths.d.ts +22 -0
  72. package/dist/core/output-paths.d.ts.map +1 -0
  73. package/dist/core/output-paths.js +130 -0
  74. package/dist/core/output-paths.js.map +1 -0
  75. package/dist/core/prompt-builder.d.ts +62 -0
  76. package/dist/core/prompt-builder.d.ts.map +1 -0
  77. package/dist/core/prompt-builder.js +232 -0
  78. package/dist/core/prompt-builder.js.map +1 -0
  79. package/dist/core/prompts.d.ts +27 -0
  80. package/dist/core/prompts.d.ts.map +1 -0
  81. package/dist/core/prompts.js +57 -0
  82. package/dist/core/prompts.js.map +1 -0
  83. package/dist/core/svg-asset-paths.d.ts +40 -0
  84. package/dist/core/svg-asset-paths.d.ts.map +1 -0
  85. package/dist/core/svg-asset-paths.js +107 -0
  86. package/dist/core/svg-asset-paths.js.map +1 -0
  87. package/dist/core/types.d.ts +388 -0
  88. package/dist/core/types.d.ts.map +1 -0
  89. package/dist/core/types.js +265 -0
  90. package/dist/core/types.js.map +1 -0
  91. package/dist/core/ui-languages.d.ts +66 -0
  92. package/dist/core/ui-languages.d.ts.map +1 -0
  93. package/dist/core/ui-languages.js +277 -0
  94. package/dist/core/ui-languages.js.map +1 -0
  95. package/dist/core/user-edited-model.d.ts +3 -0
  96. package/dist/core/user-edited-model.d.ts.map +1 -0
  97. package/dist/core/user-edited-model.js +3 -0
  98. package/dist/core/user-edited-model.js.map +1 -0
  99. package/dist/edit-cache-app/app.js +1326 -0
  100. package/dist/edit-cache-app/index.html +287 -0
  101. package/dist/edit-cache-app/styles.css +664 -0
  102. package/dist/extractors/base-extractor.d.ts +15 -0
  103. package/dist/extractors/base-extractor.d.ts.map +1 -0
  104. package/dist/extractors/base-extractor.js +23 -0
  105. package/dist/extractors/base-extractor.js.map +1 -0
  106. package/dist/extractors/classify-segment.d.ts +6 -0
  107. package/dist/extractors/classify-segment.d.ts.map +1 -0
  108. package/dist/extractors/classify-segment.js +20 -0
  109. package/dist/extractors/classify-segment.js.map +1 -0
  110. package/dist/extractors/json-extractor.d.ts +16 -0
  111. package/dist/extractors/json-extractor.d.ts.map +1 -0
  112. package/dist/extractors/json-extractor.js +128 -0
  113. package/dist/extractors/json-extractor.js.map +1 -0
  114. package/dist/extractors/markdown-extractor.d.ts +15 -0
  115. package/dist/extractors/markdown-extractor.d.ts.map +1 -0
  116. package/dist/extractors/markdown-extractor.js +205 -0
  117. package/dist/extractors/markdown-extractor.js.map +1 -0
  118. package/dist/extractors/svg-extractor.d.ts +19 -0
  119. package/dist/extractors/svg-extractor.d.ts.map +1 -0
  120. package/dist/extractors/svg-extractor.js +132 -0
  121. package/dist/extractors/svg-extractor.js.map +1 -0
  122. package/dist/extractors/ui-string-extractor.d.ts +40 -0
  123. package/dist/extractors/ui-string-extractor.d.ts.map +1 -0
  124. package/dist/extractors/ui-string-extractor.js +146 -0
  125. package/dist/extractors/ui-string-extractor.js.map +1 -0
  126. package/dist/extractors/ui-string-locations.d.ts +23 -0
  127. package/dist/extractors/ui-string-locations.d.ts.map +1 -0
  128. package/dist/extractors/ui-string-locations.js +138 -0
  129. package/dist/extractors/ui-string-locations.js.map +1 -0
  130. package/dist/glossary/glossary.d.ts +34 -0
  131. package/dist/glossary/glossary.d.ts.map +1 -0
  132. package/dist/glossary/glossary.js +260 -0
  133. package/dist/glossary/glossary.js.map +1 -0
  134. package/dist/glossary/matcher.d.ts +10 -0
  135. package/dist/glossary/matcher.d.ts.map +1 -0
  136. package/dist/glossary/matcher.js +12 -0
  137. package/dist/glossary/matcher.js.map +1 -0
  138. package/dist/index.d.ts +44 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +44 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/processors/admonition-placeholders.d.ts +8 -0
  143. package/dist/processors/admonition-placeholders.d.ts.map +1 -0
  144. package/dist/processors/admonition-placeholders.js +59 -0
  145. package/dist/processors/admonition-placeholders.js.map +1 -0
  146. package/dist/processors/anchor-placeholders.d.ts +8 -0
  147. package/dist/processors/anchor-placeholders.d.ts.map +1 -0
  148. package/dist/processors/anchor-placeholders.js +37 -0
  149. package/dist/processors/anchor-placeholders.js.map +1 -0
  150. package/dist/processors/batch-processor.d.ts +10 -0
  151. package/dist/processors/batch-processor.d.ts.map +1 -0
  152. package/dist/processors/batch-processor.js +33 -0
  153. package/dist/processors/batch-processor.js.map +1 -0
  154. package/dist/processors/bold-code-placeholders.d.ts +14 -0
  155. package/dist/processors/bold-code-placeholders.d.ts.map +1 -0
  156. package/dist/processors/bold-code-placeholders.js +116 -0
  157. package/dist/processors/bold-code-placeholders.js.map +1 -0
  158. package/dist/processors/doc-postprocess.d.ts +51 -0
  159. package/dist/processors/doc-postprocess.d.ts.map +1 -0
  160. package/dist/processors/doc-postprocess.js +215 -0
  161. package/dist/processors/doc-postprocess.js.map +1 -0
  162. package/dist/processors/emphasis-placeholders.d.ts +6 -0
  163. package/dist/processors/emphasis-placeholders.d.ts.map +1 -0
  164. package/dist/processors/emphasis-placeholders.js +262 -0
  165. package/dist/processors/emphasis-placeholders.js.map +1 -0
  166. package/dist/processors/flat-link-rewrite.d.ts +32 -0
  167. package/dist/processors/flat-link-rewrite.d.ts.map +1 -0
  168. package/dist/processors/flat-link-rewrite.js +90 -0
  169. package/dist/processors/flat-link-rewrite.js.map +1 -0
  170. package/dist/processors/glossary-force-placeholders.d.ts +12 -0
  171. package/dist/processors/glossary-force-placeholders.d.ts.map +1 -0
  172. package/dist/processors/glossary-force-placeholders.js +58 -0
  173. package/dist/processors/glossary-force-placeholders.js.map +1 -0
  174. package/dist/processors/inline-code-placeholders.d.ts +11 -0
  175. package/dist/processors/inline-code-placeholders.d.ts.map +1 -0
  176. package/dist/processors/inline-code-placeholders.js +87 -0
  177. package/dist/processors/inline-code-placeholders.js.map +1 -0
  178. package/dist/processors/placeholder-handler.d.ts +38 -0
  179. package/dist/processors/placeholder-handler.d.ts.map +1 -0
  180. package/dist/processors/placeholder-handler.js +55 -0
  181. package/dist/processors/placeholder-handler.js.map +1 -0
  182. package/dist/processors/translation-placeholder-leaks.d.ts +2 -0
  183. package/dist/processors/translation-placeholder-leaks.d.ts.map +1 -0
  184. package/dist/processors/translation-placeholder-leaks.js +9 -0
  185. package/dist/processors/translation-placeholder-leaks.js.map +1 -0
  186. package/dist/processors/url-placeholders.d.ts +10 -0
  187. package/dist/processors/url-placeholders.d.ts.map +1 -0
  188. package/dist/processors/url-placeholders.js +29 -0
  189. package/dist/processors/url-placeholders.js.map +1 -0
  190. package/dist/processors/validator.d.ts +23 -0
  191. package/dist/processors/validator.d.ts.map +1 -0
  192. package/dist/processors/validator.js +186 -0
  193. package/dist/processors/validator.js.map +1 -0
  194. package/dist/runtime/i18next-helpers.d.ts +146 -0
  195. package/dist/runtime/i18next-helpers.d.ts.map +1 -0
  196. package/dist/runtime/i18next-helpers.js +192 -0
  197. package/dist/runtime/i18next-helpers.js.map +1 -0
  198. package/dist/runtime/index.d.ts +4 -0
  199. package/dist/runtime/index.d.ts.map +1 -0
  200. package/dist/runtime/index.js +4 -0
  201. package/dist/runtime/index.js.map +1 -0
  202. package/dist/runtime/template.d.ts +21 -0
  203. package/dist/runtime/template.d.ts.map +1 -0
  204. package/dist/runtime/template.js +28 -0
  205. package/dist/runtime/template.js.map +1 -0
  206. package/dist/runtime/ui-language-display.d.ts +16 -0
  207. package/dist/runtime/ui-language-display.d.ts.map +1 -0
  208. package/dist/runtime/ui-language-display.js +26 -0
  209. package/dist/runtime/ui-language-display.js.map +1 -0
  210. package/dist/server/translation-editor.d.ts +25 -0
  211. package/dist/server/translation-editor.d.ts.map +1 -0
  212. package/dist/server/translation-editor.js +583 -0
  213. package/dist/server/translation-editor.js.map +1 -0
  214. package/dist/utils/concurrency.d.ts +31 -0
  215. package/dist/utils/concurrency.d.ts.map +1 -0
  216. package/dist/utils/concurrency.js +103 -0
  217. package/dist/utils/concurrency.js.map +1 -0
  218. package/dist/utils/hash.d.ts +5 -0
  219. package/dist/utils/hash.d.ts.map +1 -0
  220. package/dist/utils/hash.js +9 -0
  221. package/dist/utils/hash.js.map +1 -0
  222. package/dist/utils/ignore-parser.d.ts +7 -0
  223. package/dist/utils/ignore-parser.d.ts.map +1 -0
  224. package/dist/utils/ignore-parser.js +26 -0
  225. package/dist/utils/ignore-parser.js.map +1 -0
  226. package/dist/utils/logger.d.ts +45 -0
  227. package/dist/utils/logger.d.ts.map +1 -0
  228. package/dist/utils/logger.js +158 -0
  229. package/dist/utils/logger.js.map +1 -0
  230. package/docs/GETTING_STARTED.md +697 -0
  231. package/docs/PACKAGE_OVERVIEW.md +427 -0
  232. package/docs/ai-i18n-tools-context.md +481 -0
  233. package/package.json +117 -0
  234. package/translated-docs/README.de.md +157 -0
  235. package/translated-docs/README.es.md +157 -0
  236. package/translated-docs/README.fr.md +157 -0
  237. package/translated-docs/README.hi.md +157 -0
  238. package/translated-docs/README.ja.md +157 -0
  239. package/translated-docs/README.ko.md +157 -0
  240. package/translated-docs/README.pt-BR.md +157 -0
  241. package/translated-docs/README.zh-CN.md +157 -0
  242. package/translated-docs/README.zh-TW.md +157 -0
  243. package/translated-docs/docs/GETTING_STARTED.de.md +682 -0
  244. package/translated-docs/docs/GETTING_STARTED.es.md +682 -0
  245. package/translated-docs/docs/GETTING_STARTED.fr.md +682 -0
  246. package/translated-docs/docs/GETTING_STARTED.hi.md +682 -0
  247. package/translated-docs/docs/GETTING_STARTED.ja.md +682 -0
  248. package/translated-docs/docs/GETTING_STARTED.ko.md +682 -0
  249. package/translated-docs/docs/GETTING_STARTED.pt-BR.md +682 -0
  250. package/translated-docs/docs/GETTING_STARTED.zh-CN.md +682 -0
  251. package/translated-docs/docs/GETTING_STARTED.zh-TW.md +682 -0
  252. package/translated-docs/docs/PACKAGE_OVERVIEW.de.md +428 -0
  253. package/translated-docs/docs/PACKAGE_OVERVIEW.es.md +428 -0
  254. package/translated-docs/docs/PACKAGE_OVERVIEW.fr.md +428 -0
  255. package/translated-docs/docs/PACKAGE_OVERVIEW.hi.md +428 -0
  256. package/translated-docs/docs/PACKAGE_OVERVIEW.ja.md +428 -0
  257. package/translated-docs/docs/PACKAGE_OVERVIEW.ko.md +428 -0
  258. package/translated-docs/docs/PACKAGE_OVERVIEW.pt-BR.md +428 -0
  259. package/translated-docs/docs/PACKAGE_OVERVIEW.zh-CN.md +428 -0
  260. package/translated-docs/docs/PACKAGE_OVERVIEW.zh-TW.md +428 -0
@@ -0,0 +1,428 @@
1
+ # ai-i18n-tools: Descripción del Paquete
2
+
3
+ Este documento describe la arquitectura interna de `ai-i18n-tools`, cómo se ensamblan los diferentes componentes y cómo se implementan los dos flujos de trabajo principales.
4
+
5
+ Para instrucciones de uso práctico, consulte [GETTING_STARTED.md](GETTING_STARTED.es.md).
6
+
7
+ <small>**Leer en otros idiomas:** </small>
8
+
9
+ <small id="lang-list">[en-GB](../../docs/PACKAGE_OVERVIEW.md) · [de](./PACKAGE_OVERVIEW.de.md) · [es](./PACKAGE_OVERVIEW.es.md) · [fr](./PACKAGE_OVERVIEW.fr.md) · [hi](./PACKAGE_OVERVIEW.hi.md) · [ja](./PACKAGE_OVERVIEW.ja.md) · [ko](./PACKAGE_OVERVIEW.ko.md) · [pt-BR](./PACKAGE_OVERVIEW.pt-BR.md) · [zh-CN](./PACKAGE_OVERVIEW.zh-CN.md) · [zh-TW](./PACKAGE_OVERVIEW.zh-TW.md)</small>
10
+
11
+ ---
12
+
13
+ <!-- INICIO doctoc generado TOC por favor mantenga el comentario aquí para permitir la actualización automática -->
14
+ <!-- NO EDITAR ESTA SECCIÓN, EN SU LUGAR REEJECUTAR doctoc PARA ACTUALIZAR -->
15
+ **Tabla de Contenidos**
16
+
17
+ - [Descripción de la arquitectura](#architecture-overview)
18
+ - [Árbol de código fuente](#source-tree)
19
+ - [Flujo de trabajo 1 - Internos de la traducción de UI](#workflow-1---ui-translation-internals)
20
+ - [`UIStringExtractor`](#uistringextractor)
21
+ - [`strings.json`](#stringsjson)
22
+ - [Archivos de localización plana](#flat-locale-files)
23
+ - [Prompts de traducción de UI](#ui-translation-prompts)
24
+ - [Flujo de trabajo 2 - Internos de la traducción de documentos](#workflow-2---document-translation-internals)
25
+ - [Extractores](#extractors)
26
+ - [Protección de marcadores de posición](#placeholder-protection)
27
+ - [Cache (`TranslationCache`)](#cache-translationcache)
28
+ - [Resolución de la ruta de salida](#output-path-resolution)
29
+ - [Reescritura de enlaces planos](#flat-link-rewriting)
30
+ - [Infraestructura compartida](#shared-infrastructure)
31
+ - [`OpenRouterClient`](#openrouterclient)
32
+ - [Carga de configuración](#config-loading)
33
+ - [Registrador](#logger)
34
+ - [API de ayudantes en tiempo de ejecución](#runtime-helpers-api)
35
+ - [Ayudantes RTL](#rtl-helpers)
36
+ - [Fábricas de configuración de i18next](#i18next-setup-factories)
37
+ - [Ayudantes de visualización](#display-helpers)
38
+ - [Ayudantes de cadenas](#string-helpers)
39
+ - [API programática](#programmatic-api)
40
+ - [Puntos de extensión](#extension-points)
41
+ - [Nombres de funciones personalizadas (extracción de UI)](#custom-function-names-ui-extraction)
42
+ - [Extractores personalizados](#custom-extractors)
43
+ - [Rutas de salida personalizadas](#custom-output-paths)
44
+
45
+ <!-- FIN doctoc generado TOC por favor mantenga el comentario aquí para permitir la actualización automática -->
46
+
47
+ ---
48
+
49
+ ## Descripción de la arquitectura
50
+
51
+ ```
52
+ ai-i18n-tools
53
+ ├── CLI (src/cli/) - commands: init, extract, translate-docs, translate-svg, translate-ui, sync, status, …
54
+ ├── Core (src/core/) - config, types, cache, prompts, output paths, UI languages
55
+ ├── Extractors (src/extractors/) - segment extraction from JS/TS, markdown, JSON, SVG
56
+ ├── Processors (src/processors/) - placeholders, batching, validation, link rewriting
57
+ ├── API (src/api/) - OpenRouter HTTP client
58
+ ├── Glossary (src/glossary/) - glossary loading and term matching
59
+ ├── Runtime (src/runtime/) - i18next helpers, display helpers (no i18next import)
60
+ ├── Server (src/server/) - local Express web editor for cache / glossary
61
+ └── Utils (src/utils/) - logger, hash, ignore parser
62
+ ```
63
+
64
+ Todo lo que los consumidores pueden necesitar programáticamente se vuelve a exportar desde `src/index.ts`.
65
+
66
+ ---
67
+
68
+ ## Árbol de código fuente
69
+
70
+ ```
71
+ src/
72
+ ├── index.ts Public API re-exports
73
+ │
74
+ ├── cli/
75
+ │ ├── index.ts CLI entry point (commander)
76
+ │ ├── extract-strings.ts `extract` command implementation
77
+ │ ├── translate-ui-strings.ts `translate-ui` command implementation
78
+ │ ├── doc-translate.ts `translate-docs` command (documentation files only)
79
+ │ ├── translate-svg.ts `translate-svg` command (standalone assets from `config.svg`)
80
+ │ ├── helpers.ts Shared CLI utilities
81
+ │ └── file-utils.ts File collection helpers
82
+ │
83
+ ├── core/
84
+ │ ├── types.ts Zod schemas + TypeScript types for all config shapes
85
+ │ ├── config.ts Config loading, merging, validation, init templates
86
+ │ ├── cache.ts SQLite translation cache (node:sqlite)
87
+ │ ├── prompt-builder.ts LLM prompt construction for docs and UI strings
88
+ │ ├── output-paths.ts Docusaurus / flat output path resolution
89
+ │ ├── ui-languages.ts ui-languages.json loading and locale resolution
90
+ │ ├── locale-utils.ts BCP-47 normalization and locale list parsing
91
+ │ └── errors.ts Typed error classes
92
+ │
93
+ ├── extractors/
94
+ │ ├── base-extractor.ts Abstract base class for all extractors
95
+ │ ├── ui-string-extractor.ts JS/TS source scanner (i18next-scanner)
96
+ │ ├── classify-segment.ts Heuristic segment type classification
97
+ │ ├── markdown-extractor.ts Markdown / MDX segment extraction
98
+ │ ├── json-extractor.ts JSON label file extraction
99
+ │ └── svg-extractor.ts SVG text extraction
100
+ │
101
+ ├── processors/
102
+ │ ├── placeholder-handler.ts Chain: admonitions → anchors → URLs
103
+ │ ├── url-placeholders.ts Markdown URL protection/restore
104
+ │ ├── admonition-placeholders.ts Docusaurus admonition protection/restore
105
+ │ ├── anchor-placeholders.ts HTML anchor / heading ID protection/restore
106
+ │ ├── batch-processor.ts Segment → batch grouping (count + char limits)
107
+ │ ├── validator.ts Post-translation structural checks
108
+ │ └── flat-link-rewrite.ts Relative link rewriting for flat output
109
+ │
110
+ ├── api/
111
+ │ └── openrouter.ts OpenRouter HTTP client with model fallback chain
112
+ │
113
+ ├── glossary/
114
+ │ ├── glossary.ts Glossary loading (CSV + auto-build from strings.json)
115
+ │ └── matcher.ts Term hint extraction for prompts
116
+ │
117
+ ├── runtime/
118
+ │ ├── index.ts Runtime re-exports
119
+ │ ├── template.ts interpolateTemplate, flipUiArrowsForRtl
120
+ │ ├── ui-language-display.ts getUILanguageLabel, getUILanguageLabelNative
121
+ │ └── i18next-helpers.ts RTL detection, i18next setup factories
122
+ │
123
+ ├── server/
124
+ │ └── translation-editor.ts Express app for cache / strings.json / glossary editor
125
+ │
126
+ └── utils/
127
+ ├── logger.ts Leveled logger with ANSI support
128
+ ├── hash.ts Segment hash (SHA-256 first 16 hex)
129
+ └── ignore-parser.ts .translate-ignore file parser
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Flujo de trabajo 1 - Internos de la traducción de UI
135
+
136
+ ```
137
+ source files (JS/TS)
138
+ │
139
+ ▼ UIStringExtractor (i18next-scanner Parser)
140
+ strings.json ─────────────────── master catalog
141
+ │ { hash: { source, translated, models?, locations? } }
142
+ ▼
143
+ OpenRouterClient.translateUIBatch()
144
+ │ sends JSON array of source strings, receives JSON array of translations (+ model id per batch)
145
+ ▼
146
+ de.json, pt-BR.json … ─────────── per-locale flat maps: source → translation (no model metadata)
147
+ ```
148
+
149
+ ### `UIStringExtractor`
150
+
151
+ Utiliza `i18next-scanner`'s `Parser.parseFuncFromString` para encontrar llamadas a `t("literal")` e `i18n.t("literal")` en cualquier archivo JS/TS. Los nombres de funciones y las extensiones de archivo son configurables, y la extracción también puede incluir la `description` del proyecto `package.json` cuando `reactExtractor.includePackageDescription` está habilitado. Los hashes de segmento son **los primeros 8 caracteres hexadecimales MD5** de la cadena de origen recortada; estos se convierten en las claves en `strings.json`.
152
+
153
+ ### `strings.json`
154
+
155
+ El catálogo maestro tiene la forma:
156
+
157
+ ```json
158
+ {
159
+ "<md5-8>": {
160
+ "source": "The English string",
161
+ "translated": {
162
+ "de": "Der deutsche Text",
163
+ "pt-BR": "O texto em português"
164
+ },
165
+ "models": {
166
+ "de": "anthropic/claude-3.5-haiku",
167
+ "pt-BR": "openai/gpt-4o"
168
+ },
169
+ "locations": [{ "file": "src/app/page.tsx", "line": 51 }]
170
+ }
171
+ }
172
+ ```
173
+
174
+ `models` (opcional): por configuración regional, qué modelo produjo esa traducción después de la última ejecución exitosa de `translate-ui` para esa configuración regional (o `user-edited` si el texto se guardó desde la interfaz web `editor`). `locations` (opcional): dónde encontró `extract` la cadena.
175
+
176
+ `extract` añade nuevas claves y conserva los datos existentes de `translated` / `models` para las claves que aún están presentes en el análisis. `translate-ui` rellena las entradas `translated` que faltan, actualiza `models` para las configuraciones regionales que traduce, y escribe archivos planos por configuración regional.
177
+
178
+ ### Archivos de localización plana
179
+
180
+ Cada configuración regional de destino obtiene un archivo JSON plano (`de.json`) que asocia la cadena original con su traducción (sin el campo `models`):
181
+
182
+ ```json
183
+ {
184
+ "The English string": "Der deutsche Text",
185
+ "Save": "Speichern"
186
+ }
187
+ ```
188
+
189
+ i18next carga estos como paquetes de recursos y busca traducciones por la cadena de origen (modelo clave-como-predeterminado).
190
+
191
+ ### Prompts de traducción de UI
192
+
193
+ `buildUIPromptMessages` construye mensajes del sistema + del usuario que:
194
+ - Identifican los idiomas de origen y destino (por nombre de visualización de `localeDisplayNames` o `ui-languages.json`).
195
+ - Envía un array JSON de cadenas y solicita un array JSON de traducciones a cambio.
196
+ - Incluye pistas de glosario cuando están disponibles.
197
+
198
+ `OpenRouterClient.translateUIBatch` intenta cada modelo en orden, pasando al siguiente ante errores de análisis o de red. La CLI construye esa lista a partir de `openrouter.translationModels` (o valores predeterminados heredados); para `translate-ui`, si está definido, `ui.preferredModel` se añade al principio (eliminando duplicados respecto al resto).
199
+
200
+ ---
201
+
202
+ ## Flujo de trabajo 2 - Internos de la traducción de documentos
203
+
204
+ ```
205
+ markdown/MDX/JSON files (`translate-docs`)
206
+ │
207
+ ▼ MarkdownExtractor / JsonExtractor
208
+ segments[] ─────────────────── typed segments with hash + content
209
+ │
210
+ ▼ PlaceholderHandler
211
+ protected text ──────────────── URLs, admonitions, anchors replaced with tokens
212
+ │
213
+ ▼ splitTranslatableIntoBatches
214
+ batches[] ───────────────────── grouped by count + char limit
215
+ │
216
+ ▼ TranslationCache lookup
217
+ cache hit → skip, miss → OpenRouterClient.translateDocumentBatch
218
+ │
219
+ ▼ PlaceholderHandler.restoreAfterTranslation
220
+ final text ──────────────────── placeholders restored
221
+ │
222
+ ▼ resolveDocumentationOutputPath
223
+ output file ─────────────────── Docusaurus layout or flat layout
224
+ ```
225
+
226
+ ### Extractores
227
+
228
+ Todos los extractores extienden `BaseExtractor` e implementan `extract(content, filepath): Segment[]`.
229
+
230
+ - `MarkdownExtractor`: divide el markdown en segmentos tipificados: `frontmatter`, `heading`, `paragraph`, `code`, `admonition`. Los segmentos no traducibles (bloques de código, HTML sin procesar) se conservan textualmente.
231
+ - `JsonExtractor`: extrae valores de cadena de los archivos JSON de etiquetas de Docusaurus.
232
+ - `SvgExtractor`: extrae el contenido de `<text>`, `<title>` y `<desc>` del SVG (usado por `translate-svg` para recursos bajo `config.svg`, no por `translate-docs`).
233
+
234
+ ### Protección de marcadores de posición
235
+
236
+ Antes de la traducción, la sintaxis sensible se reemplaza con tokens opacos para prevenir la corrupción de LLM:
237
+
238
+ 1. **Marcadores de admonición** (`:::note`, `:::`) - restaurados con el texto original exacto.
239
+ 2. **Anclas de documento** (HTML `<a id="…">`, encabezado de Docusaurus `{#…}`) - preservados textualmente.
240
+ 3. **URLs de Markdown** (`](url)`, `src="../…"`) - restaurados de un mapa después de la traducción.
241
+
242
+ ### Caché (`TranslationCache`)
243
+
244
+ La base de datos SQLite (a través de `node:sqlite`) almacena filas indexadas por `(source_hash, locale)` con `translated_text`, `model`, `filepath`, `last_hit_at` y campos relacionados. El hash es SHA-256 de los primeros 16 caracteres hexadecimales del contenido normalizado (espacios en blanco colapsados).
245
+
246
+ En cada ejecución, los segmentos se buscan por hash × locale. Solo los fallos de caché van al LLM. Después de la traducción, `last_hit_at` se restablece para las filas de segmento en el ámbito de traducción actual que no fueron alcanzadas. `cleanup` ejecuta `sync --force-update` primero, luego elimina filas de segmento obsoletas (null `last_hit_at` / filepath vacío), poda claves de `file_tracking` cuando la ruta de origen resuelta falta en el disco (`doc-block:…`, `svg-assets:…`, etc.), y elimina filas de traducción cuya metadata filepath apunta a un archivo faltante; primero hace una copia de seguridad de `cache.db` a menos que se pase `--no-backup`.
247
+
248
+ El comando `translate-docs` también utiliza **seguimiento de archivos** para que las fuentes sin cambios con salidas existentes puedan omitir todo el trabajo. `--force-update` vuelve a ejecutar el procesamiento de archivos mientras sigue utilizando la caché de segmentos; `--force` borra el seguimiento de archivos y omite las lecturas de caché de segmentos para la traducción de API. Consulta [Getting Started](GETTING_STARTED.es.md#cache-behaviour-and-translate-docs-flags) para la tabla completa de flags.
249
+
250
+ **Formato de solicitud por lotes:** `translate-docs --prompt-format` selecciona el formato XML (`<seg>` / `<t>`) o formato de matriz/objeto JSON únicamente para `OpenRouterClient.translateDocumentBatch`; la extracción, los marcadores de posición y la validación no cambian. Consulte [Formato de solicitud por lotes](GETTING_STARTED.es.md#batch-prompt-format).
251
+
252
+ ### Resolución de la ruta de salida
253
+
254
+ `resolveDocumentationOutputPath(config, cwd, locale, relPath, kind)` mapea una ruta relativa a la fuente a la ruta de salida:
255
+
256
+ - Estilo `nested` (por defecto): `{outputDir}/{locale}/{relPath}` para markdown.
257
+ - Estilo `docusaurus`: bajo `docsRoot`, las salidas usan `{outputDir}/{locale}/docusaurus-plugin-content-docs/current/{relativeToDocsRoot}`; las rutas fuera de `docsRoot` vuelven al diseño anidado.
258
+ - Estilo `flat`: `{outputDir}/{stem}.{locale}{extension}`. Cuando `flatPreserveRelativeDir` es `true`, los subdirectorios de origen se mantienen bajo `outputDir`.
259
+ - **Plantilla personalizada** `pathTemplate`: cualquier diseño para markdown usando `{outputDir}`, `{locale}`, `{LOCALE}`, `{relPath}`, `{stem}`, `{basename}`, `{extension}`, `{docsRoot}`, `{relativeToDocsRoot}`.
260
+ - **Plantilla personalizada** `jsonPathTemplate`: diseño personalizado separado para archivos JSON de etiquetas, usando los mismos marcadores de posición.
261
+ - `linkRewriteDocsRoot` ayuda al reescritor de enlaces planos a calcular los prefijos correctos cuando la salida traducida está ubicada en otro lugar distinto de la raíz del proyecto predeterminada.
262
+
263
+ ### Reescritura de enlaces planos
264
+
265
+ Cuando `markdownOutput.style === "flat"`, los archivos markdown traducidos se colocan junto a la fuente con sufijos de locale. Los enlaces relativos entre páginas se reescriben para que `[Guide](../guide.md)` en `readme.de.md` apunte a `guide.de.md`. Controlado por `rewriteRelativeLinks` (habilitado automáticamente para el estilo plano sin una `pathTemplate` personalizada).
266
+
267
+ ---
268
+
269
+ ## Infraestructura compartida
270
+
271
+ ### `OpenRouterClient`
272
+
273
+ Envuelve la API de completaciones de chat de OpenRouter. Comportamientos clave:
274
+
275
+ - **Modelo de reserva**: prueba cada modelo de la lista resuelta en orden; recurre a reserva en errores HTTP o fallos de análisis. La traducción de la interfaz de usuario resuelve primero `ui.preferredModel` cuando está presente, luego los modelos `openrouter`.
276
+ - **Limitación de tasa**: detecta respuestas 429, espera `retry-after` (o 2s), reintenta una vez.
277
+ - **Almacenamiento en caché de prompts**: el mensaje del sistema se envía con `cache_control: { type: "ephemeral" }` para habilitar el almacenamiento en caché de prompts en modelos compatibles.
278
+ - **Registro de tráfico de depuración**: si `debugTrafficFilePath` está configurado, añade JSON de solicitud y respuesta a un archivo.
279
+
280
+ ### Carga de configuración
281
+
282
+ Canalización `loadI18nConfigFromFile(configPath, cwd)`:
283
+
284
+ 1. Leer y analizar `ai-i18n-tools.config.json` (JSON).
285
+ 2. `mergeWithDefaults` - fusión profunda con `defaultI18nConfigPartial`, y fusionar cualquier entrada `documentations[].sourceFiles` en `contentPaths`.
286
+ 3. `expandTargetLocalesFileReferenceInRawInput` - si `targetLocales` es una ruta de archivo, cargar el manifiesto y expandir a códigos de localización; establecer `uiLanguagesPath`.
287
+ 4. `expandDocumentationTargetLocalesInRawInput` - lo mismo para cada entrada `documentations[].targetLocales`.
288
+ 5. `parseI18nConfig` - Validación Zod + `validateI18nBusinessRules`.
289
+ 6. `applyEnvOverrides` - aplicar `OPENROUTER_API_KEY`, `I18N_SOURCE_LOCALE`, etc.
290
+ 7. `augmentConfigWithUiLanguagesFile` - adjuntar nombres de visualización del manifiesto.
291
+
292
+ ### Registrador
293
+
294
+ `Logger` admite niveles `debug`, `info`, `warn`, `error` con salida de color ANSI. El modo detallado (`-v`) habilita `debug`. Cuando `logFilePath` está configurado, las líneas de registro también se escriben en ese archivo.
295
+
296
+ ---
297
+
298
+ ## API de ayudas de tiempo de ejecución
299
+
300
+ Estas se exportan desde `'ai-i18n-tools/runtime'` y funcionan en cualquier entorno JavaScript (navegador, Node.js, Deno, Edge). **No** importan desde `i18next` o `react-i18next`.
301
+
302
+ ### Ayudas para RTL
303
+
304
+ ```ts
305
+ RTL_LANGS: ReadonlySet<string>
306
+ getTextDirection(lng: string): 'ltr' | 'rtl'
307
+ applyDirection(lng: string, element?: Element): void
308
+ ```
309
+
310
+ ### Fábricas de configuración de i18next
311
+
312
+ ```ts
313
+ defaultI18nInitOptions(sourceLocale?: string): i18nextInitOptions
314
+ wrapI18nWithKeyTrim(i18n: I18nLike): void
315
+ makeLoadLocale(
316
+ i18n: I18nWithResources,
317
+ localeLoaders: Record<string, () => Promise<unknown>>,
318
+ sourceLocale?: string
319
+ ): (lang: string) => Promise<void>
320
+ ```
321
+
322
+ ### Ayudas de visualización
323
+
324
+ ```ts
325
+ getUILanguageLabel(lang: UiLanguageEntry, t: TranslateFn): string
326
+ getUILanguageLabelNative(lang: UiLanguageEntry): string
327
+ ```
328
+
329
+ ### Ayudas de cadenas
330
+
331
+ ```ts
332
+ interpolateTemplate(str: string, vars: Record<string, string | number | boolean>): string
333
+ flipUiArrowsForRtl(text: string | null | undefined, isRtl: boolean): string | null | undefined
334
+ ```
335
+
336
+ ---
337
+
338
+ ## API programática
339
+
340
+ Todos los tipos y clases públicos se exportan desde la raíz del paquete. Ejemplo: ejecutar el paso de traducción de interfaz de usuario desde Node.js sin la CLI:
341
+
342
+ ```ts
343
+ import { loadI18nConfigFromFile, runTranslateUI } from 'ai-i18n-tools';
344
+
345
+ // Config must have features.translateUIStrings: true (and valid targetLocales, etc.).
346
+ const config = loadI18nConfigFromFile('ai-i18n-tools.config.json');
347
+
348
+ const summary = await runTranslateUI(config, {
349
+ cwd: process.cwd(),
350
+ locales: config.targetLocales,
351
+ force: false,
352
+ dryRun: false,
353
+ verbose: false,
354
+ });
355
+ console.log(
356
+ `Updated ${summary.stringsUpdated} string(s); locales touched: ${summary.localesTouched.join(', ')}`
357
+ );
358
+ ```
359
+
360
+ Exportaciones clave:
361
+
362
+ | Exportación | Descripción |
363
+ |---|---|
364
+ | `loadI18nConfigFromFile` | Cargar, fusionar, validar configuración desde un archivo JSON. |
365
+ | `parseI18nConfig` | Validar un objeto de configuración en bruto. |
366
+ | `TranslationCache` | Caché SQLite - instanciar con una ruta `cacheDir`. |
367
+ | `UIStringExtractor` | Extraer cadenas `t("…")` desde fuente JS/TS. |
368
+ | `MarkdownExtractor` | Extraer segmentos traducibles desde markdown. |
369
+ | `JsonExtractor` | Extraer desde archivos JSON de etiquetas de Docusaurus. |
370
+ | `SvgExtractor` | Extraer desde archivos SVG. |
371
+ | `OpenRouterClient` | Hacer solicitudes de traducción a OpenRouter. |
372
+ | `PlaceholderHandler` | Proteger/restaurar sintaxis markdown alrededor de la traducción. |
373
+ | `splitTranslatableIntoBatches` | Agrupar segmentos en lotes de tamaño para LLM. |
374
+ | `validateTranslation` | Comprobaciones estructurales después de la traducción. |
375
+ | `resolveDocumentationOutputPath` | Resolver ruta de archivo de salida para un documento traducido. |
376
+ | `Glossary` / `GlossaryMatcher` | Cargar y aplicar glosarios de traducción. |
377
+ | `runTranslateUI` | Punto de entrada programático para traducción de interfaz de usuario. |
378
+
379
+ ---
380
+
381
+ ## Puntos de extensión
382
+
383
+ ### Nombres de funciones personalizadas (extracción de interfaz de usuario)
384
+
385
+ Añadir nombres de funciones de traducción no estándar mediante configuración:
386
+
387
+ ```json
388
+ {
389
+ "ui": {
390
+ "reactExtractor": {
391
+ "funcNames": ["t", "i18n.t", "translate", "i18n.translate"]
392
+ }
393
+ }
394
+ }
395
+ ```
396
+
397
+ ### Extractores personalizados
398
+
399
+ Implementar `ContentExtractor` del paquete:
400
+
401
+ ```ts
402
+ import { BaseExtractor, type Segment } from 'ai-i18n-tools';
403
+
404
+ class MyExtractor extends BaseExtractor {
405
+ readonly name = 'my-format';
406
+ canHandle(filepath: string) { return filepath.endsWith('.myext'); }
407
+ extract(content: string): Segment[] { /* … */ }
408
+ reassemble(segments: Segment[], translations: Map<string, string>): string { /* … */ }
409
+ }
410
+ ```
411
+
412
+ Pásalo a la tubería de traducción de documentos importando las utilidades de `doc-translate.ts` programáticamente.
413
+
414
+ ### Rutas de salida personalizadas
415
+
416
+ Usa `markdownOutput.pathTemplate` para cualquier diseño de archivo:
417
+
418
+ ```json
419
+ {
420
+ "documentations": [
421
+ {
422
+ "markdownOutput": {
423
+ "pathTemplate": "{outputDir}/{locale}/{relativeToDocsRoot}"
424
+ }
425
+ }
426
+ ]
427
+ }
428
+ ```