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,682 @@
1
+ # ai-i18n-tools: Erste Schritte
2
+
3
+ `ai-i18n-tools` bietet zwei unabhängige, kombinierbare Workflows:
4
+
5
+ - **Workflow 1 - UI-Übersetzung**: Extrahieren Sie `t("…")`-Aufrufe aus jeder JS/TS-Quelle, übersetzen Sie sie über OpenRouter und schreiben Sie flache JSON-Dateien pro Sprache, die für i18next bereitstehen.
6
+ - **Workflow 2 - Dokumentenübersetzung**: Übersetzen Sie Markdown (MDX) und Docusaurus JSON-Beschriftungsdateien in beliebig viele Sprachen, mit intelligenter Zwischenspeicherung. **SVG**-Ressourcen verwenden `features.translateSVG`, den obersten `svg`-Block und `translate-svg` (siehe [CLI-Referenz](#cli-reference)).
7
+
8
+ Beide Workflows verwenden OpenRouter (jeden kompatiblen LLM) und teilen sich eine einzige Konfigurationsdatei.
9
+
10
+ <small>**In anderen Sprachen lesen:** </small>
11
+
12
+ <small id="lang-list">[en-GB](../../docs/GETTING_STARTED.md) · [de](./GETTING_STARTED.de.md) · [es](./GETTING_STARTED.es.md) · [fr](./GETTING_STARTED.fr.md) · [hi](./GETTING_STARTED.hi.md) · [ja](./GETTING_STARTED.ja.md) · [ko](./GETTING_STARTED.ko.md) · [pt-BR](./GETTING_STARTED.pt-BR.md) · [zh-CN](./GETTING_STARTED.zh-CN.md) · [zh-TW](./GETTING_STARTED.zh-TW.md)</small>
13
+
14
+ ---
15
+
16
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
17
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
18
+ **Inhaltsverzeichnis**
19
+
20
+ - [Installation](#installation)
21
+ - [Schnellstart](#quick-start)
22
+ - [Workflow 1 – UI-Übersetzung](#workflow-1---ui-translation)
23
+ - [Schritt 1: Initialisieren](#step-1-initialise)
24
+ - [Schritt 2: Zeichenketten extrahieren](#step-2-extract-strings)
25
+ - [Schritt 3: UI-Zeichenketten übersetzen](#step-3-translate-ui-strings)
26
+ - [Export nach XLIFF 2.0 (optional)](#exporting-to-xliff-20-optional)
27
+ - [Schritt 4: i18next zur Laufzeit verbinden](#step-4-wire-i18next-at-runtime)
28
+ - [Verwenden von `t()` im Quellcode](#using-t-in-source-code)
29
+ - [Interpolation](#interpolation)
30
+ - [Sprachumschalter-Benutzeroberfläche](#language-switcher-ui)
31
+ - [RTL-Sprachen](#rtl-languages)
32
+ - [Workflow 2 – Dokumentenübersetzung](#workflow-2---document-translation)
33
+ - [Schritt 1: Initialisieren](#step-1-initialise-1)
34
+ - [Schritt 2: Dokumente übersetzen](#step-2-translate-documents)
35
+ - [Cache-Verhalten und `translate-docs`-Flags](#cache-behaviour-and-translate-docs-flags)
36
+ - [Ausgabe-Layouts](#output-layouts)
37
+ - [Kombinierter Workflow (UI + Docs)](#combined-workflow-ui--docs)
38
+ - [Konfigurationsreferenz](#configuration-reference)
39
+ - [`sourceLocale`](#sourcelocale)
40
+ - [`targetLocales`](#targetlocales)
41
+ - [`uiLanguagesPath` (optional)](#uilanguagespath-optional)
42
+ - [`concurrency` (optional)](#concurrency-optional)
43
+ - [`batchConcurrency` (optional)](#batchconcurrency-optional)
44
+ - [`batchSize` / `maxBatchChars` (optional)](#batchsize--maxbatchchars-optional)
45
+ - [`openrouter`](#openrouter)
46
+ - [`features`](#features)
47
+ - [`ui`](#ui)
48
+ - [`cacheDir`](#cachedir)
49
+ - [`documentations`](#documentations)
50
+ - [`svg` (optional)](#svg-optional)
51
+ - [`glossary`](#glossary)
52
+ - [CLI-Referenz](#cli-reference)
53
+ - [Umgebungsvariablen](#environment-variables)
54
+
55
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
56
+
57
+ ## Installation
58
+
59
+ Das veröffentlichte Paket ist **nur ESM**. Verwenden Sie `import`/`import()` in Node.js oder Ihrem Bundler; **verwenden Sie nicht `require('ai-i18n-tools')`.**
60
+
61
+ ```bash
62
+ npm install ai-i18n-tools
63
+ # or
64
+ pnpm add ai-i18n-tools
65
+ # or
66
+ yarn add ai-i18n-tools
67
+ ```
68
+
69
+ Setze deinen OpenRouter API-Schlüssel:
70
+
71
+ ```bash
72
+ export OPENROUTER_API_KEY=sk-or-v1-your-key-here
73
+ ```
74
+
75
+ Oder erstellen Sie eine `.env`-Datei im Projektstamm:
76
+
77
+ ```env
78
+ OPENROUTER_API_KEY=sk-or-v1-your-key-here
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Schnellstart
84
+
85
+ Die Standard-`init`-Vorlage (`ui-markdown`) ermöglicht nur die **UI**-Extraktion und -Übersetzung. Die `ui-docusaurus`-Vorlage ermöglicht die **Dokumenten**-Übersetzung (`translate-docs`). Verwenden Sie `sync`, wenn Sie einen Befehl möchten, der Extraktion, UI-Übersetzung, optionale eigenständige SVG-Übersetzung und Dokumentationsübersetzung gemäß Ihrer Konfiguration ausführt.
86
+
87
+ ```bash
88
+ # Workflow 1 - UI strings (default template enables extract + translate-ui)
89
+ npx ai-i18n-tools init
90
+ npx ai-i18n-tools extract
91
+ npx ai-i18n-tools translate-ui
92
+
93
+ # Workflow 2 - docs (Docusaurus-oriented template)
94
+ npx ai-i18n-tools init -t ui-docusaurus
95
+ npx ai-i18n-tools translate-docs
96
+
97
+ # Combined: extract UI strings, then translate UI + SVG + docs (per config features)
98
+ npx ai-i18n-tools sync
99
+
100
+ # Markdown translation status (per file × locale)
101
+ npx ai-i18n-tools status
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Workflow 1 - UI-Übersetzung
107
+
108
+ Entwickelt für jedes JS/TS-Projekt, das i18next verwendet: React-Apps, Next.js (Client- und Serverkomponenten), Node.js-Dienste, CLI-Tools.
109
+
110
+ ### Schritt 1: Initialisieren
111
+
112
+ ```bash
113
+ npx ai-i18n-tools init
114
+ ```
115
+
116
+ Dies schreibt `ai-i18n-tools.config.json` mit der `ui-markdown`-Vorlage. Bearbeiten Sie es, um Folgendes festzulegen:
117
+
118
+ - `sourceLocale` - Ihr Quellsprach-BCP-47-Code (z. B. `"en-GB"`). **Muss übereinstimmen** mit `SOURCE_LOCALE`, das aus Ihrer Runtime-i18n-Setup-Datei exportiert wurde (`src/i18n.ts` / `src/i18n.js`).
119
+ - `targetLocales` - Pfad zu Ihrem `ui-languages.json`-Manifest ODER ein Array von BCP-47-Codes.
120
+ - `ui.sourceRoots` - Verzeichnisse, die nach `t("…")`-Aufrufen durchsucht werden sollen (z. B. `["src/"]`).
121
+ - `ui.stringsJson` - wo das Master-Katalog geschrieben werden soll (z. B. `"src/locales/strings.json"`).
122
+ - `ui.flatOutputDir` - wo `de.json`, `pt-BR.json` usw. geschrieben werden sollen (z. B. `"src/locales/"`).
123
+ - `ui.preferredModel` (optional) - OpenRouter-Modell-ID, die **zuerst** nur für `translate-ui` versucht wird; bei einem Fehler fährt die CLI mit `openrouter.translationModels` (oder dem veralteten `defaultModel` / `fallbackModel`) in der Reihenfolge fort und überspringt Duplikate.
124
+
125
+ ### Schritt 2: Strings extrahieren
126
+
127
+ ```bash
128
+ npx ai-i18n-tools extract
129
+ ```
130
+
131
+ Durchsucht alle JS/TS-Dateien unter `ui.sourceRoots` nach `t("literal")` und `i18n.t("literal")`-Aufrufen. Schreibt (oder fügt hinzu) in `ui.stringsJson`.
132
+
133
+ Der Scanner ist konfigurierbar: Fügen Sie benutzerdefinierte Funktionsnamen über `ui.reactExtractor.funcNames` hinzu.
134
+
135
+ ### Schritt 3: UI-Strings übersetzen
136
+
137
+ ```bash
138
+ npx ai-i18n-tools translate-ui
139
+ ```
140
+
141
+ Liest `strings.json`, sendet Batches an OpenRouter für jede Zielsprache, schreibt flache JSON-Dateien (`de.json`, `fr.json` usw.) in `ui.flatOutputDir`. Wenn `ui.preferredModel` gesetzt ist, wird dieses Modell vor der geordneten Liste in `openrouter.translationModels` versucht (Dokumentenübersetzung und andere Befehle verwenden weiterhin nur `openrouter`).
142
+
143
+ Für jeden Eintrag speichert `translate-ui` die **OpenRouter-Modell-ID**, die jede Locale erfolgreich übersetzt hat, in einem optionalen `models`-Objekt (mit denselben Locale-Schlüsseln wie `translated`). Zeichenketten, die im lokalen `editor`-Befehl bearbeitet wurden, werden im `models`-Objekt für diese Locale mit dem Sentinel-Wert `user-edited` markiert. Die flachen Dateien pro Locale unter `ui.flatOutputDir` enthalten weiterhin nur **Quellzeichenkette → Übersetzung**; sie beinhalten `models` nicht (sodass die Laufzeit-Bundles unverändert bleiben).
144
+
145
+ > **Hinweis zur Verwendung des Cache-Editors:** Wenn Sie einen Eintrag im Cache-Editor bearbeiten, müssen Sie einen `sync --force-update` (oder den entsprechenden `translate`-Befehl mit `--force-update`) ausführen, um die Ausgabedateien mit dem aktualisierten Cache-Eintrag neu zu schreiben. Denken Sie auch daran, dass, wenn sich der Quelltext später ändert, Ihre manuelle Bearbeitung verloren geht, da ein neuer Cache-Schlüssel (Hash) für den neuen Quellstring generiert wird.
146
+
147
+ ### Export nach XLIFF 2.0 (optional)
148
+
149
+ Um UI-Zeichenketten an einen Übersetzungsdienstleister, ein TMS oder ein CAT-Tool weiterzugeben, exportieren Sie den Katalog als **XLIFF 2.0** (eine Datei pro Zielsprache). Dieser Befehl ist **schreibgeschützt**: Er verändert `strings.json` nicht und ruft keine API auf.
150
+
151
+ ```bash
152
+ npx ai-i18n-tools export-ui-xliff
153
+ ```
154
+
155
+ Standardmäßig werden die Dateien neben `ui.stringsJson` abgelegt und benannt wie `strings.de.xliff`, `strings.pt-BR.xliff` (Basisname Ihres Katalogs + Sprache + `.xliff`). Verwenden Sie `-o` / `--output-dir`, um an einen anderen Ort zu schreiben. Vorhandene Übersetzungen aus `strings.json` erscheinen in `<target>`; fehlende Sprachen verwenden `state="initial"` ohne `<target>`, sodass Tools diese ergänzen können. Verwenden Sie `--untranslated-only`, um nur Einheiten zu exportieren, die für jede Sprache noch übersetzt werden müssen (nützlich für Vendor-Batches). `--dry-run` gibt Pfade aus, ohne Dateien zu schreiben.
156
+
157
+ ### Schritt 4: i18next zur Laufzeit einbinden
158
+
159
+ Erstellen Sie Ihre i18n-Setup-Datei mit den von `'ai-i18n-tools/runtime'` exportierten Helfern:
160
+
161
+ ```js
162
+ // src/i18n.js (or src/i18n.ts)
163
+ import i18n from 'i18next';
164
+ import { initReactI18next } from 'react-i18next';
165
+ import uiLanguages from './locales/ui-languages.json';
166
+ import {
167
+ defaultI18nInitOptions,
168
+ wrapI18nWithKeyTrim,
169
+ makeLoadLocale,
170
+ applyDirection,
171
+ } from 'ai-i18n-tools/runtime';
172
+
173
+ // Must match sourceLocale in ai-i18n-tools.config.json
174
+ export const SOURCE_LOCALE = 'en-GB';
175
+
176
+ void i18n.use(initReactI18next).init(defaultI18nInitOptions(SOURCE_LOCALE));
177
+ wrapI18nWithKeyTrim(i18n);
178
+ i18n.on('languageChanged', applyDirection);
179
+ applyDirection(i18n.language);
180
+
181
+ const localeLoaders = Object.fromEntries(
182
+ uiLanguages
183
+ .filter(({ code }) => code !== SOURCE_LOCALE)
184
+ .map(({ code }) => [code, () => import(`./locales/${code}.json`)])
185
+ );
186
+
187
+ export const loadLocale = makeLoadLocale(i18n, localeLoaders, SOURCE_LOCALE);
188
+ export default i18n;
189
+ ```
190
+
191
+ Importieren Sie `i18n.js`, bevor React rendert (z. B. am Anfang Ihres Einstiegspunkts). Wenn der Benutzer die Sprache ändert, rufen Sie `await loadLocale(code)` und dann `i18n.changeLanguage(code)` auf.
192
+
193
+ `SOURCE_LOCALE` wird exportiert, sodass jede andere Datei, die es benötigt (z. B. ein Sprachwechsler), es direkt von `'./i18n'` importieren kann.
194
+
195
+ `defaultI18nInitOptions(sourceLocale)` gibt die Standardoptionen für Setups mit Schlüssel-als-Standard zurück:
196
+
197
+ - `parseMissingKeyHandler` gibt den Schlüssel selbst zurück, sodass nicht übersetzte Strings den Quelltext anzeigen.
198
+ - `nsSeparator: false` erlaubt Schlüssel, die Doppelpunkte enthalten.
199
+ - `interpolation.escapeValue: false` - sicher zu deaktivieren: React entkommt Werten selbst, und Node.js/CLI-Ausgaben haben kein HTML, das entkommen werden muss.
200
+
201
+ `wrapI18nWithKeyTrim(i18n)` umhüllt `i18n.t`, sodass: (1) Schlüssel vor der Suche abgeschnitten werden, was der Speicherung durch das Extraktionsskript entspricht; (2) <code>{"{{var}}"}</code>-Interpolation angewendet wird, wenn die Quell-locale den rohen Schlüssel zurückgibt – sodass <code>{"t('Hallo {{name}}', { name })"}</code> auch für die Ausgangssprache korrekt funktioniert.
202
+
203
+ `makeLoadLocale(i18n, loaders, sourceLocale)` gibt eine asynchrone `loadLocale(lang)`-Funktion zurück, die das JSON-Bundle für eine Locale dynamisch importiert und bei i18next registriert.
204
+
205
+ ### Verwendung von `t()` im Quellcode
206
+
207
+ Rufen Sie `t()` mit einem **wörtlichen String** auf, damit das Extraktionsskript ihn finden kann:
208
+
209
+ ```jsx
210
+ import { useTranslation } from 'react-i18next';
211
+
212
+ function MyComponent() {
213
+ const { t } = useTranslation();
214
+ return <button>{t('Save')}</button>;
215
+ }
216
+ ```
217
+
218
+ Das gleiche Muster funktioniert außerhalb von React (Node.js, Serverkomponenten, CLI):
219
+
220
+ ```js
221
+ import i18n from './i18n.js';
222
+ console.log(i18n.t('Processing complete'));
223
+ ```
224
+
225
+ **Regeln:**
226
+
227
+ - Nur diese Formen werden extrahiert: `t("…")`, `t('…')`, `t(`…`)`, `i18n.t("…")`.
228
+ - Der Schlüssel muss ein **literal string** sein - keine Variablen oder Ausdrücke als Schlüssel.
229
+ - Verwenden Sie keine Template-Literale für den Schlüssel: <code>{'t(`Hello ${name}`)'}</code> ist nicht extrahierbar.
230
+
231
+ ### Interpolation
232
+
233
+ Verwenden Sie die native Interpolation des zweiten Arguments von i18next für <code>{"{{var}}"}</code> Platzhalter:
234
+
235
+ ```js
236
+ // i18next handles substitution natively, even in key-as-default mode
237
+ t('Hello {{name}}, you have {{count}} messages', { name, count })
238
+ // → "Hello Alice, you have 3 messages"
239
+ ```
240
+
241
+ Das Extraktionsskript ignoriert das zweite Argument - nur der literale Schlüsselstring <code>{"\"Hello {{name}}, Sie haben {{count}} Nachrichten\""}</code> wird extrahiert und zur Übersetzung gesendet. Übersetzer werden angewiesen, die <code>{"{{...}}"}</code> Tokens beizubehalten.
242
+
243
+ ### Spracheinstellungen UI
244
+
245
+ Verwenden Sie das Manifest `ui-languages.json`, um einen Sprachwähler zu erstellen. `ai-i18n-tools` exportiert zwei Anzeigehilfen:
246
+
247
+ ```tsx
248
+ import { useMemo } from 'react';
249
+ import { useTranslation } from 'react-i18next';
250
+ import {
251
+ getUILanguageLabel,
252
+ getUILanguageLabelNative,
253
+ type UiLanguageEntry,
254
+ } from 'ai-i18n-tools/runtime';
255
+ import uiLanguages from './locales/ui-languages.json';
256
+ import { loadLocale } from './i18n';
257
+
258
+ function LanguageSelect({
259
+ value,
260
+ onChange,
261
+ }: {
262
+ value: string;
263
+ onChange: (code: string) => void;
264
+ }) {
265
+ const { t, i18n } = useTranslation();
266
+
267
+ const options = useMemo(
268
+ () =>
269
+ (uiLanguages as UiLanguageEntry[]).map((lang) => ({
270
+ code: lang.code,
271
+ // Settings/content dropdowns: shows translated name when available
272
+ label: getUILanguageLabel(lang, t),
273
+ // Header globe menu: shows "English / Deutsch"-style label, no t() call
274
+ nativeLabel: getUILanguageLabelNative(lang),
275
+ })),
276
+ [t]
277
+ );
278
+
279
+ const handleChange = async (code: string) => {
280
+ await loadLocale(code);
281
+ i18n.changeLanguage(code);
282
+ onChange(code);
283
+ };
284
+
285
+ return (
286
+ <select value={value} onChange={(e) => handleChange(e.target.value)}>
287
+ {options.map((row) => (
288
+ <option key={row.code} value={row.code}>
289
+ {row.label}
290
+ </option>
291
+ ))}
292
+ </select>
293
+ );
294
+ }
295
+ ```
296
+
297
+ `getUILanguageLabel(lang, t)` – zeigt `t(englishName)` an, wenn übersetzt, oder `englishName / t(englishName)`, wenn beide unterschiedlich sind. Geeignet für Einstellungsseiten.
298
+
299
+ `getUILanguageLabelNative(lang)` – zeigt `englishName / label` an (kein `t()`-Aufruf pro Zeile). Geeignet für Kopfzeilenmenüs, bei denen der native Name sichtbar sein soll.
300
+
301
+ Das Manifest `ui-languages.json` ist ein JSON-Array von <code>{"{ code, label, englishName }"}</code> Einträgen. Beispiel:
302
+
303
+ ```json
304
+ [
305
+ { "code": "en-GB", "label": "English (UK)", "englishName": "English (UK)" },
306
+ { "code": "pt-BR", "label": "Português (BR)", "englishName": "Portuguese (BR)" },
307
+ { "code": "de", "label": "Deutsch", "englishName": "German" },
308
+ { "code": "fr", "label": "Français", "englishName": "French" },
309
+ { "code": "ar", "label": "العربية", "englishName": "Arabic" }
310
+ ]
311
+ ```
312
+
313
+ Setzen Sie `targetLocales` in der Konfiguration auf den Pfad dieser Datei, damit der Übersetzungsbefehl dieselbe Liste verwendet.
314
+
315
+ ### RTL-Sprachen
316
+
317
+ `ai-i18n-tools` exportiert `getTextDirection(lng)` und `applyDirection(lng)`:
318
+
319
+ ```js
320
+ import { getTextDirection, applyDirection } from 'ai-i18n-tools/runtime';
321
+
322
+ getTextDirection('ar') // 'rtl'
323
+ getTextDirection('en-GB') // 'ltr'
324
+
325
+ // Applied automatically via i18n.on('languageChanged', applyDirection) - see Step 4
326
+ ```
327
+
328
+ `applyDirection` setzt `document.documentElement.dir` (Browser) oder ist ein No-Op (Node.js). Übergeben Sie ein optionales `element` Argument, um ein bestimmtes Element anzusprechen.
329
+
330
+ Für Strings, die `→` Pfeile enthalten können, drehen Sie sie für RTL-Layouts um:
331
+
332
+ ```js
333
+ import { flipUiArrowsForRtl } from 'ai-i18n-tools/runtime';
334
+ const { i18n } = useTranslation();
335
+ const isRtl = getTextDirection(i18n.language) === 'rtl';
336
+ const label = flipUiArrowsForRtl(t('Next → Step'), isRtl);
337
+ ```
338
+
339
+ ---
340
+
341
+ ## Workflow 2 - Dokumentübersetzung
342
+
343
+ Entwickelt für Markdown-Dokumentation, Docusaurus-Websites und JSON-Beschriftungsdateien. Eigenständige SVG-Ressourcen werden über [`translate-svg`](#cli-reference) übersetzt, wenn `features.translateSVG` aktiviert ist und der oberste `svg`-Block gesetzt ist – nicht über `documentations[].contentPaths`.
344
+
345
+ ### Schritt 1: Initialisieren
346
+
347
+ ```bash
348
+ npx ai-i18n-tools init -t ui-docusaurus
349
+ ```
350
+
351
+ Bearbeiten Sie die generierte `ai-i18n-tools.config.json`:
352
+
353
+ - `sourceLocale` – Ausgangssprache (muss mit `defaultLocale` in `docusaurus.config.js` übereinstimmen).
354
+ - `targetLocales` – Array mit Sprachcodes oder Pfad zu einer Manifest-Datei.
355
+ - `cacheDir` – gemeinsames SQLite-Cache-Verzeichnis für alle Dokumentations-Pipelines (und standardmäßiges Protokollverzeichnis für `--write-logs`).
356
+ - `documentations` – Array mit Dokumentationsblöcken. Jeder Block enthält optional `description`, `contentPaths`, `outputDir`, optional `jsonSource`, `markdownOutput`, `targetLocales`, `addFrontmatter` usw.
357
+ - `documentations[].description` – optionale kurze Notiz für Maintainer (was dieser Block abdeckt). Falls gesetzt, erscheint sie in der Überschrift von `translate-docs` (`🌐 …: translating …`) und in den Abschnittsüberschriften von `status`.
358
+ - `documentations[].contentPaths` – Markdown/MDX-Quellverzeichnisse oder -Dateien (siehe auch `documentations[].jsonSource` für JSON-Labels).
359
+ - `documentations[].outputDir` – Ausgabewurzelverzeichnis für die Übersetzungen dieses Blocks.
360
+ - `documentations[].markdownOutput.style` – `"nested"` (Standard), `"docusaurus"` oder `"flat"` (siehe [Ausgabe-Layouts](#output-layouts)).
361
+
362
+ ### Schritt 2: Dokumente übersetzen
363
+
364
+ ```bash
365
+ npx ai-i18n-tools translate-docs
366
+ ```
367
+
368
+ Dies übersetzt alle Dateien in jedem `documentations`-Block von `contentPaths` in alle effektiven Dokumentations-Lokalisierungen (Vereinigung der `targetLocales` jedes Blocks, wenn gesetzt, sonst die root `targetLocales`). Bereits übersetzte Segmente werden aus dem SQLite-Cache geliefert – nur neue oder geänderte Segmente werden an das LLM gesendet.
369
+
370
+ Um eine einzelne Lokalisierung zu übersetzen:
371
+
372
+ ```bash
373
+ npx ai-i18n-tools translate-docs --locale de
374
+ ```
375
+
376
+ Um zu prüfen, was übersetzt werden muss:
377
+
378
+ ```bash
379
+ npx ai-i18n-tools status
380
+ ```
381
+
382
+ #### Cache-Verhalten und `translate-docs`-Flags
383
+
384
+ Die CLI führt **Datei-Tracking** in SQLite (Source-Hash pro Datei × Lokalisierung) und **Segment**-Zeilen (Hash × Lokalisierung pro übersetzbarem Abschnitt). Ein normaler Lauf überspringt eine Datei vollständig, wenn der getrackte Hash mit der aktuellen Quelle übereinstimmt **und** die Ausgabedatei bereits existiert; andernfalls wird die Datei verarbeitet und der Segment-Cache verwendet, sodass unveränderter Text nicht die API aufruft.
385
+
386
+ | Flag | Effekt |
387
+ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
388
+ | *(default)* | Überspringt unveränderte Dateien, wenn Tracking- und On-Disk-Ausgaben übereinstimmen; verwendet Segment-Cache für den Rest. |
389
+ | `--force-update` | Verarbeitet jede zutreffende Datei erneut (Extraktion, Neuzusammenstellung, Schreiben der Ausgaben), auch wenn das Dateitracking dies überspringen würde. **Segment-Cache wird weiterhin angewendet** – unveränderte Segmente werden nicht an das LLM gesendet. |
390
+ | `--force` | Löscht das Dateitracking für jede verarbeitete Datei und **liest den Segment-Cache nicht** für die API-Übersetzung (vollständige Neuübersetzung). Neue Ergebnisse werden weiterhin **in den Segment-Cache geschrieben**. |
391
+ | `--stats` | Gibt Segmentanzahlen, Anzahl der verfolgten Dateien und Segmentgesamtzahlen pro Locale aus und beendet sich dann. |
392
+ | `--clear-cache [locale]` | Löscht zwischengespeicherte Übersetzungen (und Dateitracking): für alle Locales oder ein einzelnes Locale, dann Beendigung. |
393
+ | `--prompt-format <mode>` | Wie jeder **Batch** von Segmenten an das Modell gesendet und geparst wird (`xml`, `json-array` oder `json-object`). Standard ist **`xml`**. Beeinflusst weder Extraktion, Platzhalter, Validierung, Cache noch Fallback-Verhalten – siehe [Batch-Prompt-Format](#batch-prompt-format). |
394
+
395
+ Sie können `--force` nicht mit `--force-update` kombinieren (sie schließen sich gegenseitig aus).
396
+
397
+ #### Batch-Prompt-Format
398
+
399
+ `translate-docs` sendet übersetzbare Segmente in **Batches** (gruppiert nach `batchSize` / `maxBatchChars`) an OpenRouter. Die **`--prompt-format`**-Option ändert nur das **Übertragungsformat** des Batches; die Segmentaufteilung, `PlaceholderHandler`-Token, Markdown-AST-Prüfungen, SQLite-Cache-Schlüssel und der pro-Segment-Fallback bei fehlgeschlagenem Batch-Parsing bleiben unverändert.
400
+
401
+ | Modus | Benutzernachricht | Modellantwort |
402
+ | ---- | ------------ | ----------- |
403
+ | **`xml`** (Standard) | Pseudo-XML: ein `<seg id="N">…</seg>` pro Segment (mit XML-Escaping). | Nur `<t id="N">…</t>` Blöcke, einer pro Segmentindex. |
404
+ | **`json-array`** | Ein JSON-Array aus Zeichenketten, ein Eintrag pro Segment in der Reihenfolge. | Ein JSON-Array mit **derselben Länge** (gleiche Reihenfolge). |
405
+ | **`json-object`** | Ein JSON-Objekt `{"0":"…","1":"…",…}`, indiziert nach Segmentnummer. | Ein JSON-Objekt mit den **gleichen Schlüsseln** und übersetzten Werten. |
406
+
407
+ Der Lauf-Header gibt außerdem `Batch prompt format: …` aus, damit Sie den aktiven Modus überprüfen können. JSON-Beschriftungsdateien (`jsonSource`) und eigenständige SVG-Batches verwenden dieselbe Einstellung, wenn diese Schritte als Teil von `translate-docs` ausgeführt werden (oder der Dokumentationsphase von `sync` – `sync` stellt dieses Flag nicht zur Verfügung; es ist standardmäßig auf **`xml`** gesetzt).
408
+
409
+ **Segment-Deduplizierung und Pfade in SQLite**
410
+
411
+ - Segmentzeilen sind global über `(source_hash, locale)` indiziert (Hash = normalisierter Inhalt). Identischer Text in zwei Dateien teilt sich eine Zeile; `translations.filepath` ist Metadaten (letzter Schreiber), kein zweiter Cache-Eintrag pro Datei.
412
+ - `file_tracking.filepath` verwendet namensraumbezogene Schlüssel: `doc-block:{index}:{relPath}` pro `documentations`-Block (`relPath` ist posix-Pfad relativ zum Projektstamm: Markdown-Pfade wie gesammelt; **JSON-Beschriftungsdateien verwenden den zum aktuellen Arbeitsverzeichnis relativen Pfad zur Quelldatei**, z. B. `docs-site/i18n/en/code.json`, sodass Cleanup die echte Datei auflösen kann) und `svg-assets:{relPath}` für eigenständige SVG-Assets unter `translate-svg`.
413
+ - `translations.filepath` speichert zum aktuellen Arbeitsverzeichnis relative posix-Pfade für Markdown-, JSON- und SVG-Segmente (SVG verwendet dieselbe Pfadstruktur wie andere Assets; das Präfix `svg-assets:…` existiert **nur** in `file_tracking`).
414
+ - Nach einem Lauf wird `last_hit_at` nur für Segmentzeilen **im gleichen Übersetzungsbereich** gelöscht (unter Berücksichtigung von `--path` und aktivierten Typen), die nicht getroffen wurden, sodass ein gefilterter oder nur-Dokumente-Lauf keine unabhängigen Dateien als veraltet markiert.
415
+
416
+ ### Ausgabe-Layouts
417
+
418
+ `"nested"` (Standard, wenn nicht angegeben) — spiegelt die Quellstruktur unter `{outputDir}/{locale}/` wider (z. B. `docs/guide.md` → `i18n/de/docs/guide.md`).
419
+
420
+ `"docusaurus"` — platziert Dateien, die sich unter `docsRoot` befinden, unter `i18n/<locale>/docusaurus-plugin-content-docs/current/<relativeToDocsRoot>`, entsprechend dem üblichen Docusaurus-i18n-Layout. Setzen Sie `documentations[].markdownOutput.docsRoot` auf die Wurzel Ihres Dokumentationsquellverzeichnisses (z. B. `"docs"`).
421
+
422
+ ```
423
+ docs/guide.md → i18n/de/docusaurus-plugin-content-docs/current/guide.md
424
+ i18n/en/sidebar.json → i18n/de/sidebar.json (JSON label files)
425
+ ```
426
+
427
+ `"flat"` – platziert übersetzte Dateien neben der Quelle mit einem Ländersuffix oder in einem Unterverzeichnis. Relative Links zwischen Seiten werden automatisch umgeschrieben.
428
+
429
+ ```
430
+ docs/guide.md → i18n/guide.de.md
431
+ ```
432
+
433
+ Sie können Pfade vollständig mit `documentations[].markdownOutput.pathTemplate` überschreiben. Platzhalter: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{docsRoot}"}</code>, <code>{"{relativeToDocsRoot}"}</code>.
434
+
435
+ ---
436
+
437
+ ## Kombinierter Workflow (UI + Dokumentation)
438
+
439
+ Aktivieren Sie alle Funktionen in einer einzigen Konfiguration, um beide Workflows zusammen auszuführen:
440
+
441
+ ```json
442
+ {
443
+ "sourceLocale": "en-GB",
444
+ "targetLocales": "src/locales/ui-languages.json",
445
+ "features": {
446
+ "extractUIStrings": true,
447
+ "translateUIStrings": true,
448
+ "translateMarkdown": true,
449
+ "translateJSON": false,
450
+ "translateSVG": false
451
+ },
452
+ "glossary": {
453
+ "uiGlossary": "src/locales/strings.json",
454
+ "userGlossary": "glossary-user.csv"
455
+ },
456
+ "ui": {
457
+ "sourceRoots": ["src/"],
458
+ "stringsJson": "src/locales/strings.json",
459
+ "flatOutputDir": "src/locales/"
460
+ },
461
+ "cacheDir": ".translation-cache",
462
+ "documentations": [
463
+ {
464
+ "contentPaths": ["docs/"],
465
+ "outputDir": "i18n/",
466
+ "markdownOutput": { "style": "flat" }
467
+ }
468
+ ]
469
+ }
470
+ ```
471
+
472
+ `glossary.uiGlossary` richtet die Dokumentübersetzung auf dasselbe `strings.json`-Katalog wie die UI aus, damit die Terminologie konsistent bleibt; `glossary.userGlossary` fügt CSV-Überschreibungen für Produktbegriffe hinzu.
473
+
474
+ Führen Sie `npx ai-i18n-tools sync` aus, um eine Pipeline auszuführen: **Extrahieren** von UI-Texten (wenn `features.extractUIStrings`), **Übersetzen** der UI-Texte (wenn `features.translateUIStrings`), **Übersetzen eigenständiger SVG-Ressourcen** (wenn `features.translateSVG` und ein `svg`-Block gesetzt sind) und anschließend **Übersetzen der Dokumentation** (jeder `documentations`-Block: Markdown/JSON wie konfiguriert). Überspringen Sie Teile mit `--no-ui`, `--no-svg` oder `--no-docs`. Der Dokumentationsschritt akzeptiert `--dry-run`, `-p` / `--path`, `--force` und `--force-update` (die letzten beiden gelten nur, wenn die Dokumentenübersetzung ausgeführt wird; sie werden ignoriert, wenn `--no-docs` angegeben wird).
475
+
476
+ Verwenden Sie `documentations[].targetLocales` in einem Block, um die Dateien dieses Blocks in ein **kleineres Teilset** als die UI zu übersetzen (effektive Dokumentationsgebiete sind die **Vereinigung** über die Blöcke):
477
+
478
+ ```json
479
+ {
480
+ "targetLocales": "src/locales/ui-languages.json",
481
+ "documentations": [
482
+ {
483
+ "contentPaths": ["docs/"],
484
+ "outputDir": "i18n/",
485
+ "targetLocales": ["de", "fr", "es"]
486
+ }
487
+ ]
488
+ }
489
+ ```
490
+
491
+ ---
492
+
493
+ ## Konfigurationsreferenz
494
+
495
+ ### `sourceLocale`
496
+
497
+ BCP-47-Code für die Quellsprache (z. B. `"en-GB"`, `"en"`, `"pt-BR"`). Für dieses Gebietsschema wird keine Übersetzungsdatei generiert - der Schlüsselstring selbst ist der Quelltext.
498
+
499
+ **Muss übereinstimmen** mit `SOURCE_LOCALE`, das aus Ihrer Runtime-i18n-Setup-Datei (`src/i18n.ts` / `src/i18n.js`) exportiert wird.
500
+
501
+ ### `targetLocales`
502
+
503
+ Welche Gebiete übersetzt werden sollen. Akzeptiert:
504
+
505
+ - **String-Pfad** zu einem `ui-languages.json`-Manifest (`"src/locales/ui-languages.json"`). Die Datei wird geladen und Gebietsschemacodes werden extrahiert.
506
+ - **Array von BCP-47-Codes** (`["de", "fr", "es"]`).
507
+ - **Ein-Element-Array mit einem Pfad** (`["src/locales/ui-languages.json"]`) - dasselbe Verhalten wie die String-Form.
508
+
509
+ `targetLocales` ist die primäre Gebietsschemaliste für die UI-Übersetzung und die Standardgebietsschemaliste für Dokumentationsblöcke. Wenn Sie hier ein explizites Array beibehalten möchten, aber dennoch manifestgesteuerte Labels und Gebietsschema-Filterung wünschen, setzen Sie auch `uiLanguagesPath`.
510
+
511
+ ### `uiLanguagesPath` (optional)
512
+
513
+ Pfad zu einem `ui-languages.json`-Manifest, das für Anzeigenamen, Gebietsschema-Filterung und Nachbearbeitung der Sprachliste verwendet wird.
514
+
515
+ Verwenden Sie dies, wenn:
516
+
517
+ - `targetLocales` ein explizites Array ist, Sie jedoch dennoch englische/nativen Labels aus dem Manifest wünschen.
518
+ - Sie möchten, dass `markdownOutput.postProcessing.languageListBlock` Gebietsschema-Labels aus demselben Manifest erstellt.
519
+ - Nur die UI-Übersetzung aktiviert ist und Sie möchten, dass das Manifest die effektive UI-Gebietsschemaliste bereitstellt.
520
+
521
+ ### `concurrency` (optional)
522
+
523
+ Maximale **Zielgebiete**, die gleichzeitig übersetzt werden (`translate-ui`, `translate-docs`, `translate-svg` und die entsprechenden Schritte innerhalb von `sync`). Wenn weggelassen, verwendet die CLI **4** für die UI-Übersetzung und **3** für die Dokumentationsübersetzung (eingebaute Standardwerte). Überschreiben Sie pro Ausführung mit `-j` / `--concurrency`.
524
+
525
+ ### `batchConcurrency` (optional)
526
+
527
+ **Übersetzen-Dokumente** und **Übersetzen-SVG** (und der Dokumentationsschritt von `sync`): maximale parallele OpenRouter **Batch**-Anfragen pro Datei (jeder Batch kann viele Segmente enthalten). Standard **4**, wenn weggelassen. Von `translate-ui` ignoriert. Überschreiben mit `-b` / `--batch-concurrency`. Bei `sync` gilt `-b` nur für den Dokumentationsübersetzungsschritt.
528
+
529
+ ### `batchSize` / `maxBatchChars` (optional)
530
+
531
+ Segment-Batching für die Dokumentenübersetzung: wie viele Segmente pro API-Anfrage und eine Zeichenobergrenze. Standardwerte: **20** Segmente, **4096** Zeichen (wenn weggelassen).
532
+
533
+ ### `openrouter`
534
+
535
+ | Feld | Beschreibung |
536
+ | ------------------- | ---------------------------------------------------------------------------------------- |
537
+ | `baseUrl` | OpenRouter-API-Basis-URL. Standard: `https://openrouter.ai/api/v1`. |
538
+ | `translationModels` | Bevorzugte, geordnete Liste von Modell-IDs. Das erste wird zuerst versucht; spätere Einträge dienen als Fallback bei Fehlern. Für `translate-ui`** können Sie zusätzlich `ui.preferredModel` setzen, um ein Modell vor dieser Liste zu versuchen (siehe `ui`). |
539
+ | `defaultModel` | Veraltetes einzelnes primäres Modell. Wird nur verwendet, wenn `translationModels` nicht gesetzt oder leer ist. |
540
+ | `fallbackModel` | Veraltetes einzelnes Fallback-Modell. Wird nach `defaultModel` verwendet, wenn `translationModels` nicht gesetzt oder leer ist. |
541
+ | `maxTokens` | Maximale Anzahl an Completion-Tokens pro Anfrage. Standard: `8192`. |
542
+ | `temperature` | Sampling-Temperatur. Standard: `0.2`. |
543
+
544
+ Setzen Sie `OPENROUTER_API_KEY` in Ihrer Umgebung oder `.env`-Datei.
545
+
546
+ ### `features`
547
+
548
+ | Feld | Workflow | Beschreibung |
549
+ | -------------------- | -------- | ----------------------------------------------------------------- |
550
+ | `extractUIStrings` | 1 | Quelle nach `t("…")` durchsuchen und `strings.json` schreiben/mergen. |
551
+ | `translateUIStrings` | 1 | Einträge in `strings.json` übersetzen und JSON-Dateien pro Sprache schreiben. |
552
+ | `translateMarkdown` | 2 | `.md` / `.mdx`-Dateien übersetzen. |
553
+ | `translateJSON` | 2 | Docusaurus JSON-Beschriftungsdateien übersetzen. |
554
+ | `translateSVG` | 2 | Eigenständige `.svg`-Ressourcen übersetzen (erfordert den obersten `svg`-Block). |
555
+
556
+ Übersetzen Sie **eigenständige** SVG-Ressourcen mit `translate-svg`, wenn `features.translateSVG` wahr ist und ein oberster `svg`-Block konfiguriert ist. Der `sync`-Befehl führt diesen Schritt aus, wenn beide Bedingungen erfüllt sind (es sei denn, `--no-svg` wird verwendet).
557
+
558
+ ### `ui`
559
+
560
+ | Feld | Beschreibung |
561
+ | --------------------------- | ----------------------------------------------------------------------- |
562
+ | `sourceRoots` | Verzeichnisse (relativ zum Arbeitsverzeichnis), die nach `t("…")`-Aufrufen durchsucht werden. |
563
+ | `stringsJson` | Pfad zur Master-Katalogdatei. Wird von `extract` aktualisiert. |
564
+ | `flatOutputDir` | Verzeichnis, in das die JSON-Dateien pro Sprache geschrieben werden (`de.json` usw.). |
565
+ | `preferredModel` | Optional. OpenRouter-Modell-ID, die zuerst für `translate-ui` versucht wird; danach `openrouter.translationModels` (oder Legacy-Modelle) in der angegebenen Reihenfolge, ohne diese ID zu duplizieren. |
566
+ | `reactExtractor.funcNames` | Zusätzliche Funktionsnamen, die durchsucht werden sollen (Standard: `["t", "i18n.t"]`). |
567
+ | `reactExtractor.extensions` | Dateierweiterungen, die einbezogen werden sollen (Standard: `[".js", ".jsx", ".ts", ".tsx"]`). |
568
+ | `reactExtractor.includePackageDescription` | Wenn `true` (Standard), schließt `extract` auch `package.json` `description` als UI-Text ein, falls vorhanden. |
569
+ | `reactExtractor.packageJsonPath` | Benutzerdefinierter Pfad zur `package.json`-Datei, die für diese optionale Beschreibungsextraktion verwendet wird. |
570
+
571
+ ### `cacheDir`
572
+
573
+ | Feld | Beschreibung |
574
+ | ---------- | ----------------------------------------------------------------------------- |
575
+ | `cacheDir` | SQLite-Cache-Verzeichnis (von allen `documentations`-Blöcken gemeinsam genutzt). Wiederverwendbar über mehrere Durchläufe. |
576
+
577
+ ### `documentations`
578
+
579
+ Array von Dokumentationspipeline-Blöcken. `translate-docs` und die Dokumentationsphase des `sync`-Prozesses **verarbeiten** jeden Block der Reihe nach.
580
+
581
+ | Feld | Beschreibung |
582
+ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
583
+ | `description` | Optionale, menschenlesbare Notiz für diesen Block (wird nicht für die Übersetzung verwendet). Wird in der `translate-docs`-Überschrift mit `🌐` präfixiert, wenn gesetzt; wird auch in den Überschriften des `status`-Abschnitts angezeigt. |
584
+ | `contentPaths` | Zu übersetzende Markdown-/MDX-Quellen (`translate-docs` durchsucht diese nach `.md` / `.mdx`). Die JSON-Bezeichnungen stammen aus `jsonSource` im selben Block. |
585
+ | `outputDir` | Stammverzeichnis für die übersetzte Ausgabe dieses Blocks. |
586
+ | `sourceFiles` | Optionaler Alias, der bei Laden in `contentPaths` zusammengeführt wird. |
587
+ | `targetLocales` | Optionale Teilmenge der Sprachcodes nur für diesen Block (sonst wird die globale `targetLocales` verwendet). Die effektiven Dokumentationssprachen ergeben sich als Vereinigung über alle Blöcke. |
588
+ | `jsonSource` | Quellverzeichnis für Docusaurus-JSON-Bezeichnungsdateien für diesen Block (z. B. `"i18n/en"`). |
589
+ | `markdownOutput.style` | `"nested"` (Standard), `"docusaurus"` oder `"flat"`. |
590
+ | `markdownOutput.docsRoot` | Quellverzeichnis der Dokumentation für das Docusaurus-Layout (z. B. `"docs"`). |
591
+ | `markdownOutput.pathTemplate` | Benutzerdefinierter Pfad für die Markdown-Ausgabe. Platzhalter: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{docsRoot}"}</code>, <code>{"{relativeToDocsRoot}"}</code>. |
592
+ | `markdownOutput.jsonPathTemplate` | Benutzerdefinierter Ausgabepfad für Bezeichnungsdateien im JSON-Format. Unterstützt dieselben Platzhalter wie `pathTemplate`. |
593
+ | `markdownOutput.flatPreserveRelativeDir` | Bei `flat`-Stil: Beibehaltung der Quellunterverzeichnisse, damit Dateien mit gleichem Basisnamen nicht kollidieren. |
594
+ | `markdownOutput.rewriteRelativeLinks` | Relative Links nach der Übersetzung neu schreiben (automatisch aktiviert beim `flat`-Stil). |
595
+ | `markdownOutput.linkRewriteDocsRoot` | Repository-Stammverzeichnis, das bei der Berechnung der Präfixe für die flache Link-Umschreibung verwendet wird. Normalerweise `"."` belassen, es sei denn, die übersetzten Dokumente befinden sich unter einer anderen Projektwurzel. |
596
+ | `markdownOutput.postProcessing` | Optionale Transformationen des übersetzten Markdown-**body** (YAML-Front Matter bleibt erhalten). Wird ausgeführt nach der Segmentzusammenfügung und der Umschreibung flacher Links, aber vor `addFrontmatter`. |
597
+ | `markdownOutput.postProcessing.regexAdjustments` | Geordnete Liste von `{ "description"?, "search", "replace" }`. `search` ist ein regulärer Ausdruck (reiner String verwendet das Flag `g`, oder `/Muster/Flags`). `replace` unterstützt Platzhalter wie `${translatedLocale}`, `${sourceLocale}`, `${sourceFullPath}`, `${translatedFullPath}`, `${sourceFilename}`, `${translatedFilename}`, `${sourceBasedir}`, `${translatedBasedir}` (ähnlich wie in der Referenz `additional-adjustments`). |
598
+ | `markdownOutput.postProcessing.languageListBlock` | `{ "start", "end", "separator" }` — der Übersetzer sucht die erste Zeile, die `start` enthält, und die passende `end`-Zeile, und ersetzt diesen Bereich dann durch einen kanonischen Sprachumschalter. Die Links werden relativ zum übersetzten Dateipfad erstellt; die Bezeichnungen stammen aus `uiLanguagesPath` / `ui-languages.json`, falls konfiguriert, andernfalls aus `localeDisplayNames` und den Sprachcodes. |
599
+ | `addFrontmatter` | Wenn `true` (Standard, wenn nicht angegeben), enthalten die übersetzten Markdown-Dateien YAML-Schlüssel: `translation_last_updated`, `source_file_mtime`, `source_file_hash`, `translation_language`, `source_file_path` und, falls mindestens ein Segment über Modell-Metadaten verfügt, `translation_models` (sortierte Liste der verwendeten OpenRouter-Modell-IDs). Auf `false` setzen, um zu überspringen. |
600
+
601
+ Beispiel (flache README-Pipeline — Screenshot-Pfade + optionaler Sprachlisten-Wrapper):
602
+
603
+ ```json
604
+ "markdownOutput": {
605
+ "style": "flat",
606
+ "postProcessing": {
607
+ "regexAdjustments": [
608
+ {
609
+ "description": "Per-locale screenshot folders",
610
+ "search": "images/screenshots/[^/]+/",
611
+ "replace": "images/screenshots/${translatedLocale}/"
612
+ }
613
+ ],
614
+ "languageListBlock": {
615
+ "start": "<small id=\"lang-list\">",
616
+ "end": "</small>",
617
+ "separator": " · "
618
+ }
619
+ }
620
+ }
621
+ ```
622
+
623
+ ### `svg` (optional)
624
+
625
+ Oberste Pfade und Layout für eigenständige SVG-Ressourcen. Die Übersetzung wird nur ausgeführt, wenn **`features.translateSVG`** wahr ist (über `translate-svg` oder die SVG-Phase von `sync`).
626
+
627
+ | Feld | Beschreibung |
628
+ | --------------------------- | ----------- |
629
+ | `sourcePath` | Ein Verzeichnis oder ein Array von Verzeichnissen, die rekursiv nach `.svg`-Dateien durchsucht werden. |
630
+ | `outputDir` | Wurzelverzeichnis für die übersetzten SVG-Ausgaben. |
631
+ | `style` | `"flat"` oder `"nested"`, wenn `pathTemplate` nicht gesetzt ist. |
632
+ | `pathTemplate` | Benutzerdefinierter SVG-Ausgabepfad. Platzhalter: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{relativeToSourceRoot}"}</code>. |
633
+ | `svgExtractor.forceLowercase` | Kleinbuchstabige übersetzte Texte bei der SVG-Zusammenstellung. Nützlich für Designs, die auf vollständig kleingeschriebenen Beschriftungen basieren. |
634
+
635
+ ### `glossary`
636
+
637
+ | Feld | Beschreibung |
638
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
639
+ | `uiGlossary` | Pfad zu `strings.json` – erstellt automatisch ein Glossar aus vorhandenen Übersetzungen. |
640
+ | `userGlossary` | Pfad zu einer CSV-Datei mit den Spalten `Original language string` (oder `en`), `locale`, `Translation` – eine Zeile pro Quellbegriff und Zielsprache (`locale` kann `*` für alle Ziele sein). |
641
+
642
+ Der veraltete Schlüssel `uiGlossaryFromStringsJson` wird weiterhin akzeptiert und beim Laden der Konfiguration auf `uiGlossary` abgebildet.
643
+
644
+ Generiere eine leere Glossar-CSV:
645
+
646
+ ```bash
647
+ npx ai-i18n-tools glossary-generate
648
+ ```
649
+
650
+ ---
651
+
652
+ ## CLI-Referenz
653
+
654
+ | Befehl | Beschreibung |
655
+ | --- | --- |
656
+ | `init [-t ui-markdown|ui-docusaurus] [-o path] [--with-translate-ignore]` | Schreibt eine Startkonfigurationsdatei (enthält `concurrency`, `batchConcurrency`, `batchSize`, `maxBatchChars` und `documentations[].addFrontmatter`). `--with-translate-ignore` erstellt eine Start-`.translate-ignore`. |
657
+ | `extract` | Scannt die Quelle nach `t("…")`-Aufrufen und aktualisiert `strings.json`. Erfordert `features.extractUIStrings`. |
658
+ | `translate-docs …` | Übersetzt Markdown/MDX und JSON für jeden `documentations`-Block (`contentPaths`, optional `jsonSource`). `-j`: maximale parallele Sprachvarianten; `-b`: maximale parallele Batch-API-Aufrufe pro Datei. `--prompt-format`: Batch-Übertragungsformat (`xml` \| `json-array` \| `json-object`). Siehe [Cache-Verhalten und `translate-docs`-Flags](#cache-behaviour-and-translate-docs-flags) und [Batch-Prompt-Format](#batch-prompt-format). |
659
+ | `translate-svg …` | Übersetzt eigenständige SVG-Ressourcen, die in `config.svg` konfiguriert sind (getrennt von der Dokumentation). Erfordert `features.translateSVG`. Gleiche Cache-Überlegungen wie bei Dokumentation; unterstützt `--no-cache`, um SQLite-Lese-/Schreibvorgänge für diese Ausführung zu überspringen. `-j`, `-b`, `--force`, `--force-update`, `-p` / `--path`, `--dry-run`. |
660
+ | `translate-ui [--locale <code>] [--force] [--dry-run] [-j <n>]` | Übersetzt nur die Benutzeroberflächenzeichenfolgen. `--force`: übersetzt alle Einträge pro Sprachvariante erneut (ignoriert vorhandene Übersetzungen). `--dry-run`: keine Schreibvorgänge, keine API-Aufrufe. `-j`: maximale parallele Sprachvarianten. Erfordert `features.translateUIStrings`. |
661
+ | `export-ui-xliff [-l <codes>] [-o <dir>] [--untranslated-only] [--dry-run]` | Exportiert `strings.json` nach XLIFF 2.0 (eine `.xliff` pro Zielsprachvariante). `-o` / `--output-dir`: Ausgabeverzeichnis (Standard: derselbe Ordner wie der Katalog). `--untranslated-only`: nur Einheiten ohne Übersetzung für diese Sprachvariante. Nur-Lesezugriff; keine API. |
662
+ | `sync …` | Extrahiert (falls aktiviert), dann UI-Übersetzung, dann `translate-svg`, wenn `features.translateSVG` und `config.svg` gesetzt sind, dann Dokumentationsübersetzung – es sei denn, sie wird mit `--no-ui`, `--no-svg` oder `--no-docs` übersprungen. Gemeinsame Flags: `-l`, `-p`, `--dry-run`, `-j`, `-b` (nur Dokumenten-Batchverarbeitung), `--force` / `--force-update` (nur Dokumentation; sich gegenseitig ausschließend, wenn Dokumentation ausgeführt wird). |
663
+ | `status` | Zeigt den Markdown-Übersetzungsstatus pro Datei × Sprachvariante an (kein `--locale`-Filter; Sprachvarianten stammen aus der Konfiguration). |
664
+ | `cleanup [--dry-run] [--no-backup] [--backup <path>]` | Führt zuerst `sync --force-update` aus (Extraktion, UI, SVG, Dokumentation), entfernt dann veraltete Segmentzeilen (null `last_hit_at` / leerer Dateipfad); löscht `file_tracking`-Zeilen, deren aufgelöster Quellpfad auf dem Datenträger fehlt; entfernt Übersetzungszeilen, deren `filepath`-Metadaten auf eine fehlende Datei verweisen. Protokolliert drei Zählungen (veraltet, verwaiste `file_tracking`, verwaiste Übersetzungen). Erstellt eine zeitgestempelte SQLite-Sicherung im Cache-Verzeichnis, es sei denn, `--no-backup` ist gesetzt. |
665
+ | `editor [-p <port>] [--no-open]` | Startet einen lokalen Web-Editor für den Cache, `strings.json` und die Glossar-CSV-Datei. `--no-open`: öffnet nicht automatisch den Standardbrowser.<br><br>**Hinweis:** Wenn Sie einen Eintrag im Cache-Editor bearbeiten, müssen Sie ein `sync --force-update` ausführen, um die Ausgabedateien mit dem aktualisierten Cache-Eintrag neu zu schreiben. Außerdem geht die manuelle Bearbeitung verloren, wenn sich der Quelltext später ändert, da ein neuer Cache-Schlüssel generiert wird. |
666
+ | `glossary-generate [-o <path>]` | Schreibt eine leere `glossary-user.csv`-Vorlage. `-o`: überschreibt den Ausgabepfad (Standard: `glossary.userGlossary` aus der Konfiguration oder `glossary-user.csv`). |
667
+
668
+ Alle Befehle akzeptieren `-c <path>`, um eine nicht standardmäßige Konfigurationsdatei anzugeben, `-v` für ausführliche Ausgaben und `-w` / `--write-logs [path]`, um die Konsolenausgabe in eine Protokolldatei zu leiten (Standardpfad: unter dem Wurzelverzeichnis `cacheDir`).
669
+
670
+ ---
671
+
672
+ ## Umgebungsvariablen
673
+
674
+ | Variable | Beschreibung |
675
+ | ---------------------- | ---------------------------------------------------------- |
676
+ | `OPENROUTER_API_KEY` | **Erforderlich.** Ihr OpenRouter API-Schlüssel. |
677
+ | `OPENROUTER_BASE_URL` | Überschreiben Sie die API-Basis-URL. |
678
+ | `I18N_SOURCE_LOCALE` | Überschreiben Sie `sourceLocale` zur Laufzeit. |
679
+ | `I18N_TARGET_LOCALES` | Komma-getrennte Gebietsschema-Codes zum Überschreiben von `targetLocales`. |
680
+ | `I18N_LOG_LEVEL` | Logger-Stufe (`debug`, `info`, `warn`, `error`, `silent`). |
681
+ | `NO_COLOR` | Wenn `1`, deaktivieren Sie ANSI-Farben in der Protokollausgabe. |
682
+ | `I18N_LOG_SESSION_MAX` | Maximalzeilen, die pro Protokollsitzung gespeichert werden (Standard `5000`). |