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: Visão Geral do Pacote
2
+
3
+ Este documento descreve a arquitetura interna do `ai-i18n-tools`, como cada componente se encaixa e como os dois fluxos de trabalho principais são implementados.
4
+
5
+ Para instruções de uso prático, consulte [GETTING_STARTED.md](GETTING_STARTED.pt-BR.md).
6
+
7
+ <small>**Leia em outros 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
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
14
+ <!-- NÃO EDITE ESTA SEÇÃO, EM VEZ DISSO, REEXECUTE doctoc PARA ATUALIZAR -->
15
+ **Tabela de Conteúdos**
16
+
17
+ - [Visão geral da arquitetura](#architecture-overview)
18
+ - [Árvore de código-fonte](#source-tree)
19
+ - [Fluxo de Trabalho 1 - Internos de Tradução de UI](#workflow-1---ui-translation-internals)
20
+ - [`UIStringExtractor`](#uistringextractor)
21
+ - [`strings.json`](#stringsjson)
22
+ - [Arquivos de localidade plana](#flat-locale-files)
23
+ - [Prompts de Tradução de UI](#ui-translation-prompts)
24
+ - [Fluxo de Trabalho 2 - Internos de Tradução de Documentos](#workflow-2---document-translation-internals)
25
+ - [Extratores](#extractors)
26
+ - [Proteção de placeholders](#placeholder-protection)
27
+ - [Cache (`TranslationCache`)](#cache-translationcache)
28
+ - [Resolução de caminho de saída](#output-path-resolution)
29
+ - [Reescrita de links planos](#flat-link-rewriting)
30
+ - [Infraestrutura compartilhada](#shared-infrastructure)
31
+ - [`OpenRouterClient`](#openrouterclient)
32
+ - [Carregamento de configuração](#config-loading)
33
+ - [Logger](#logger)
34
+ - [API de helpers em tempo de execução](#runtime-helpers-api)
35
+ - [Helpers RTL](#rtl-helpers)
36
+ - [Fábricas de configuração do i18next](#i18next-setup-factories)
37
+ - [Helpers de exibição](#display-helpers)
38
+ - [Helpers de string](#string-helpers)
39
+ - [API programática](#programmatic-api)
40
+ - [Pontos de extensão](#extension-points)
41
+ - [Nomes de funções personalizadas (extração de UI)](#custom-function-names-ui-extraction)
42
+ - [Extratores personalizados](#custom-extractors)
43
+ - [Caminhos de saída personalizados](#custom-output-paths)
44
+
45
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
46
+
47
+ ---
48
+
49
+ ## Visão geral da arquitetura
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
+ Tudo que os consumidores podem precisar programaticamente é re-exportado de `src/index.ts`.
65
+
66
+ ---
67
+
68
+ ## Árvore de código-fonte
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
+ ## Fluxo de Trabalho 1 - Internos de Tradução 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
+ Usa `Parser.parseFuncFromString` do `i18next-scanner` para encontrar chamadas `t("literal")` e `i18n.t("literal")` em qualquer arquivo JS/TS. Nomes de funções e extensões de arquivo são configuráveis, e a extração também pode incluir a `description` do `package.json` do projeto quando `reactExtractor.includePackageDescription` está habilitado. Hashes de segmento são **os primeiros 8 caracteres hexadecimais MD5** da string de origem aparada - esses se tornam as chaves em `strings.json`.
152
+
153
+ ### `strings.json`
154
+
155
+ O catálogo mestre tem a seguinte estrutura:
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 localidade, qual modelo produziu aquela tradução após a última execução bem-sucedida do `translate-ui` para aquela localidade (ou `user-edited` se o texto foi salvo a partir da interface web `editor`). `locations` (opcional) — onde o `extract` encontrou a string.
175
+
176
+ O `extract` adiciona novas chaves e preserva os dados existentes de `translated` / `models` para chaves ainda presentes na varredura. O `translate-ui` preenche entradas `translated` ausentes, atualiza `models` para as localidades que traduz e gera arquivos de localidade planos.
177
+
178
+ ### Arquivos de localidade plana
179
+
180
+ Cada localidade de destino recebe um arquivo JSON plano (`de.json`) mapeando string de origem → tradução (sem o campo `models`):
181
+
182
+ ```json
183
+ {
184
+ "The English string": "Der deutsche Text",
185
+ "Save": "Speichern"
186
+ }
187
+ ```
188
+
189
+ i18next carrega esses como pacotes de recursos e procura traduções pela string de origem (modelo chave-como-padrão).
190
+
191
+ ### Prompts de Tradução de UI
192
+
193
+ `buildUIPromptMessages` constrói mensagens do sistema + do usuário que:
194
+ - Identificam os idiomas de origem e destino (pelo nome de exibição de `localeDisplayNames` ou `ui-languages.json`).
195
+ - Enviam um array JSON de strings e solicitam um array JSON de traduções em retorno.
196
+ - Incluem dicas de glossário quando disponíveis.
197
+
198
+ `OpenRouterClient.translateUIBatch` tenta cada modelo em ordem, recorrendo a análise ou erros de rede. A CLI constrói essa lista a partir de `openrouter.translationModels` (ou padrão/hierarquia legado); para `translate-ui`, o opcional `ui.preferredModel` é adicionado no início quando definido (removendo duplicatas em relação ao restante).
199
+
200
+ ---
201
+
202
+ ## Fluxo de Trabalho 2 - Internos de Tradução 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
+ ### Extratores
227
+
228
+ Todos os extratores estendem `BaseExtractor` e implementam `extract(content, filepath): Segment[]`.
229
+
230
+ - `MarkdownExtractor` - divide o markdown em segmentos tipados: `frontmatter`, `heading`, `paragraph`, `code`, `admonition`. Segmentos não traduzíveis (blocos de código, HTML bruto) são preservados textualmente.
231
+ - `JsonExtractor` - extrai valores de string dos arquivos de rótulos JSON do Docusaurus.
232
+ - `SvgExtractor` - extrai conteúdo de `<text>`, `<title>` e `<desc>` do SVG (usado pelo `translate-svg` para ativos em `config.svg`, não pelo `translate-docs`).
233
+
234
+ ### Proteção de placeholders
235
+
236
+ Antes da tradução, a sintaxe sensível é substituída por tokens opacos para evitar a corrupção do LLM:
237
+
238
+ 1. **Marcadores de admonição** (`:::note`, `:::`) - restaurados com o texto original exato.
239
+ 2. **Âncoras de documento** (HTML `<a id="…">`, cabeçalho do Docusaurus `{#…}`) - preservados literalmente.
240
+ 3. **URLs Markdown** (`](url)`, `src="../…"`) - restaurados de um mapa após a tradução.
241
+
242
+ ### Cache (`TranslationCache`)
243
+
244
+ O banco de dados SQLite (via `node:sqlite`) armazena linhas indexadas por `(source_hash, locale)` com `translated_text`, `model`, `filepath`, `last_hit_at` e campos relacionados. O hash é SHA-256 dos primeiros 16 caracteres hexadecimais do conteúdo normalizado (espaços em branco colapsados).
245
+
246
+ Em cada execução, os segmentos são procurados por hash × locale. Apenas os erros de cache vão para o LLM. Após a tradução, `last_hit_at` é redefinido para as linhas de segmento no escopo de tradução atual que não foram acessadas. `cleanup` executa `sync --force-update` primeiro, depois remove linhas de segmento obsoletas (null `last_hit_at` / filepath vazio), poda chaves de `file_tracking` quando o caminho de origem resolvido está ausente no disco (`doc-block:…`, `svg-assets:…`, etc.), e remove linhas de tradução cuja metadata filepath aponta para um arquivo ausente; faz um backup de `cache.db` primeiro, a menos que `--no-backup` seja passado.
247
+
248
+ O comando `translate-docs` também usa **rastreamento de arquivos** para que fontes inalteradas com saídas existentes possam pular o trabalho completamente. `--force-update` reexecuta o processamento de arquivos enquanto ainda usa o cache de segmentos; `--force` limpa o rastreamento de arquivos e ignora as leituras do cache de segmentos para tradução de API. Veja [Getting Started](GETTING_STARTED.pt-BR.md#cache-behaviour-and-translate-docs-flags) para a tabela completa de flags.
249
+
250
+ **Formato do prompt em lote:** `translate-docs --prompt-format` seleciona o formato XML (`<seg>` / `<t>`) ou formato de array/objeto JSON apenas para `OpenRouterClient.translateDocumentBatch`; extração, marcadores de posição e validação permanecem inalterados. Veja [Formato do prompt em lote](GETTING_STARTED.pt-BR.md#batch-prompt-format).
251
+
252
+ ### Resolução do caminho de saída
253
+
254
+ `resolveDocumentationOutputPath(config, cwd, locale, relPath, kind)` mapeia um caminho relativo à fonte para o caminho de saída:
255
+
256
+ - Estilo `nested` (padrão): `{outputDir}/{locale}/{relPath}` para markdown.
257
+ - Estilo `docusaurus`: dentro de `docsRoot`, as saídas usam `{outputDir}/{locale}/docusaurus-plugin-content-docs/current/{relativeToDocsRoot}`; caminhos fora de `docsRoot` retornam ao layout aninhado.
258
+ - Estilo `flat`: `{outputDir}/{stem}.{locale}{extension}`. Quando `flatPreserveRelativeDir` é `true`, os subdiretórios de origem são mantidos sob `outputDir`.
259
+ - **Personalizado** `pathTemplate`: qualquer layout markdown usando `{outputDir}`, `{locale}`, `{LOCALE}`, `{relPath}`, `{stem}`, `{basename}`, `{extension}`, `{docsRoot}`, `{relativeToDocsRoot}`.
260
+ - **Personalizado** `jsonPathTemplate`: layout personalizado separado para arquivos de rótulos JSON, usando os mesmos marcadores de posição.
261
+ - `linkRewriteDocsRoot` ajuda o reescritor de links planos a calcular os prefixos corretos quando a saída traduzida está enraizada em outro local além da raiz padrão do projeto.
262
+
263
+ ### Reescrita de links planos
264
+
265
+ Quando `markdownOutput.style === "flat"`, arquivos markdown traduzidos são colocados ao lado da fonte com sufixos de localidade. Links relativos entre páginas são reescritos para que `[Guide](../guide.md)` em `readme.de.md` aponte para `guide.de.md`. Controlado por `rewriteRelativeLinks` (habilitado automaticamente para estilo plano sem um `pathTemplate` personalizado).
266
+
267
+ ---
268
+
269
+ ## Infraestrutura compartilhada
270
+
271
+ ### `OpenRouterClient`
272
+
273
+ Envolve a API de conclusões de chat do OpenRouter. Comportamentos principais:
274
+
275
+ - **Fallback de modelo**: tenta cada modelo na lista resolvida em ordem; recorre a erros HTTP ou falhas de análise. A tradução da interface do usuário resolve `ui.preferredModel` primeiro quando presente, depois os modelos `openrouter`.
276
+ - **Limitação de taxa**: detecta respostas 429, aguarda `retry-after` (ou 2s), tenta novamente uma vez.
277
+ - **Cache de prompt**: a mensagem do sistema é enviada com `cache_control: { type: "ephemeral" }` para habilitar o cache de prompt em modelos suportados.
278
+ - **Registro de tráfego de depuração**: se `debugTrafficFilePath` estiver definido, anexa a solicitação e a resposta JSON a um arquivo.
279
+
280
+ ### Carregamento de configuração
281
+
282
+ `loadI18nConfigFromFile(configPath, cwd)` pipeline:
283
+
284
+ 1. Ler e analisar `ai-i18n-tools.config.json` (JSON).
285
+ 2. `mergeWithDefaults` - mesclar profundamente com `defaultI18nConfigPartial` e mesclar quaisquer entradas de `documentations[].sourceFiles` em `contentPaths`.
286
+ 3. `expandTargetLocalesFileReferenceInRawInput` - se `targetLocales` for um caminho de arquivo, carregar o manifesto e expandir para códigos de localidade; definir `uiLanguagesPath`.
287
+ 4. `expandDocumentationTargetLocalesInRawInput` - o mesmo para cada entrada de `documentations[].targetLocales`.
288
+ 5. `parseI18nConfig` - validação Zod + `validateI18nBusinessRules`.
289
+ 6. `applyEnvOverrides` - aplicar `OPENROUTER_API_KEY`, `I18N_SOURCE_LOCALE`, etc.
290
+ 7. `augmentConfigWithUiLanguagesFile` - anexar nomes de exibição do manifesto.
291
+
292
+ ### Logger
293
+
294
+ `Logger` suporta níveis `debug`, `info`, `warn`, `error` com saída de cor ANSI. O modo detalhado (`-v`) ativa `debug`. Quando `logFilePath` está definido, as linhas de log também são escritas naquele arquivo.
295
+
296
+ ---
297
+
298
+ ## API de auxiliares em tempo de execução
299
+
300
+ Esses são exportados de `'ai-i18n-tools/runtime'` e funcionam em qualquer ambiente JavaScript (navegador, Node.js, Deno, Edge). Eles **não** importam de `i18next` ou `react-i18next`.
301
+
302
+ ### Auxiliares 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 configuração do 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
+ ### Auxiliares de exibição
323
+
324
+ ```ts
325
+ getUILanguageLabel(lang: UiLanguageEntry, t: TranslateFn): string
326
+ getUILanguageLabelNative(lang: UiLanguageEntry): string
327
+ ```
328
+
329
+ ### Auxiliares de string
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 os tipos e classes públicos são exportados da raiz do pacote. Exemplo: executando a etapa de tradução da interface do usuário a partir do Node.js sem a 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
+ Principais exportações:
361
+
362
+ | Exportação | Descrição |
363
+ |---|---|
364
+ | `loadI18nConfigFromFile` | Carregar, mesclar, validar configuração de um arquivo JSON. |
365
+ | `parseI18nConfig` | Validar um objeto de configuração bruto. |
366
+ | `TranslationCache` | Cache SQLite - instanciar com um caminho `cacheDir`. |
367
+ | `UIStringExtractor` | Extrair strings `t("…")` de código fonte JS/TS. |
368
+ | `MarkdownExtractor` | Extrair segmentos traduzíveis de markdown. |
369
+ | `JsonExtractor` | Extrair de arquivos de rótulo JSON do Docusaurus. |
370
+ | `SvgExtractor` | Extrair de arquivos SVG. |
371
+ | `OpenRouterClient` | Fazer solicitações de tradução para OpenRouter. |
372
+ | `PlaceholderHandler` | Proteger/restaurar a sintaxe markdown em torno da tradução. |
373
+ | `splitTranslatableIntoBatches` | Agrupar segmentos em lotes do tamanho LLM. |
374
+ | `validateTranslation` | Verificações estruturais após a tradução. |
375
+ | `resolveDocumentationOutputPath` | Resolver o caminho do arquivo de saída para um documento traduzido. |
376
+ | `Glossary` / `GlossaryMatcher` | Carregar e aplicar glossários de tradução. |
377
+ | `runTranslateUI` | Ponto de entrada programático para tradução da interface do usuário. |
378
+
379
+ ---
380
+
381
+ ## Pontos de extensão
382
+
383
+ ### Nomes de funções personalizadas (extração de UI)
384
+
385
+ Adicionar nomes de funções de tradução não padrão via configuração:
386
+
387
+ ```json
388
+ {
389
+ "ui": {
390
+ "reactExtractor": {
391
+ "funcNames": ["t", "i18n.t", "translate", "i18n.translate"]
392
+ }
393
+ }
394
+ }
395
+ ```
396
+
397
+ ### Extratores personalizados
398
+
399
+ Implemente `ContentExtractor` do pacote:
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
+ Passe-o para o pipeline de tradução de documentos importando as utilidades de `doc-translate.ts` programaticamente.
413
+
414
+ ### Caminhos de saída personalizados
415
+
416
+ Use `markdownOutput.pathTemplate` para qualquer layout de arquivo:
417
+
418
+ ```json
419
+ {
420
+ "documentations": [
421
+ {
422
+ "markdownOutput": {
423
+ "pathTemplate": "{outputDir}/{locale}/{relativeToDocsRoot}"
424
+ }
425
+ }
426
+ ]
427
+ }
428
+ ```