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,392 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ConfigValidationError } from "./errors.js";
4
+ import { coerceTargetLocalesField, englishLanguageNameForLocale, normalizeLocale, parseLocaleList, } from "./locale-utils.js";
5
+ import { augmentConfigWithUiLanguagesFile, expandDocumentationTargetLocalesInRawInput, expandTargetLocalesFileReferenceInRawInput, getDocumentationTargetLocaleCodes, resolveLocalesForUI, } from "./ui-languages.js";
6
+ import { i18nConfigSchema, } from "./types.js";
7
+ export { coerceTargetLocalesField, englishLanguageNameForLocale, normalizeLocale, parseLocaleList };
8
+ const DEFAULT_OPENROUTER_MODELS = [
9
+ "openai/gpt-4o-mini",
10
+ "deepseek/deepseek-v3.2",
11
+ "google/gemini-3.1-flash-lite-preview",
12
+ "qwen/qwen3.6-plus",
13
+ "moonshotai/kimi-k2.5",
14
+ "anthropic/claude-sonnet-4.6",
15
+ ];
16
+ /**
17
+ * Ordered OpenRouter models: non-empty `translationModels`, else legacy default + fallback.
18
+ */
19
+ export function resolveTranslationModels(o) {
20
+ if (Array.isArray(o.translationModels) && o.translationModels.length > 0) {
21
+ const list = o.translationModels
22
+ .filter((m) => typeof m === "string" && m.trim().length > 0)
23
+ .map((m) => m.trim());
24
+ if (list.length > 0) {
25
+ return list;
26
+ }
27
+ }
28
+ const out = [];
29
+ if (o.defaultModel?.trim()) {
30
+ out.push(o.defaultModel.trim());
31
+ }
32
+ const fb = o.fallbackModel?.trim();
33
+ if (fb && fb !== out[0]) {
34
+ out.push(fb);
35
+ }
36
+ return out;
37
+ }
38
+ /**
39
+ * Ordered OpenRouter models for UI translation: optional `ui.preferredModel` first, then
40
+ * {@link resolveTranslationModels} for `openrouter`, with the preferred id deduplicated from the tail.
41
+ */
42
+ export function resolveUITranslationModels(config) {
43
+ const base = resolveTranslationModels(config.openrouter);
44
+ const pref = config.ui.preferredModel?.trim();
45
+ if (!pref) {
46
+ return base;
47
+ }
48
+ const out = [pref];
49
+ for (const m of base) {
50
+ if (m !== pref) {
51
+ out.push(m);
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+ function deepMergeDefaults(base, override) {
57
+ if (override === null ||
58
+ override === undefined ||
59
+ typeof override !== "object" ||
60
+ Array.isArray(override)) {
61
+ return base;
62
+ }
63
+ const o = override;
64
+ const next = { ...base };
65
+ for (const key of Object.keys(o)) {
66
+ const bv = next[key];
67
+ const ov = o[key];
68
+ if (ov !== undefined &&
69
+ typeof ov === "object" &&
70
+ ov !== null &&
71
+ !Array.isArray(ov) &&
72
+ typeof bv === "object" &&
73
+ bv !== null &&
74
+ !Array.isArray(bv)) {
75
+ next[key] = deepMergeDefaults(bv, ov);
76
+ }
77
+ else if (ov !== undefined) {
78
+ next[key] = ov;
79
+ }
80
+ }
81
+ return next;
82
+ }
83
+ /** Merge each block's `sourceFiles` into `contentPaths` (unique). */
84
+ function mergeDocumentationSourceFiles(raw) {
85
+ const docs = raw.documentations;
86
+ if (!Array.isArray(docs)) {
87
+ return;
88
+ }
89
+ for (const item of docs) {
90
+ if (!item || typeof item !== "object" || Array.isArray(item)) {
91
+ continue;
92
+ }
93
+ const d = item;
94
+ const cp = d.contentPaths;
95
+ const sf = d.sourceFiles;
96
+ const list = Array.isArray(cp) ? [...cp] : [];
97
+ if (Array.isArray(sf)) {
98
+ for (const p of sf) {
99
+ if (typeof p === "string" && p.trim() && !list.includes(p)) {
100
+ list.push(p);
101
+ }
102
+ }
103
+ }
104
+ d.contentPaths = list;
105
+ }
106
+ }
107
+ /**
108
+ * Single-documentation view for translate-docs: one block plus root `cacheDir` and shared settings.
109
+ */
110
+ export function toDocTranslateConfig(root, block) {
111
+ const { documentations: _, ...rest } = root;
112
+ return { ...rest, documentation: block };
113
+ }
114
+ export const defaultI18nConfigPartial = {
115
+ sourceLocale: "en",
116
+ targetLocales: [],
117
+ openrouter: {
118
+ baseUrl: "https://openrouter.ai/api/v1",
119
+ translationModels: [...DEFAULT_OPENROUTER_MODELS],
120
+ maxTokens: 8192,
121
+ temperature: 0.2,
122
+ },
123
+ features: {
124
+ extractUIStrings: false,
125
+ translateUIStrings: false,
126
+ translateMarkdown: false,
127
+ translateJSON: false,
128
+ translateSVG: false,
129
+ },
130
+ glossary: {},
131
+ ui: {
132
+ sourceRoots: [],
133
+ stringsJson: "strings.json",
134
+ flatOutputDir: "./locales",
135
+ },
136
+ cacheDir: ".translation-cache",
137
+ documentations: [
138
+ {
139
+ contentPaths: [],
140
+ outputDir: "./i18n",
141
+ markdownOutput: {},
142
+ },
143
+ ],
144
+ };
145
+ /**
146
+ * Merge user JSON (partial) with package defaults, then validate with Zod.
147
+ */
148
+ export function mergeWithDefaults(raw) {
149
+ const asObj = raw !== null && typeof raw === "object" && !Array.isArray(raw)
150
+ ? raw
151
+ : {};
152
+ mergeDocumentationSourceFiles(asObj);
153
+ return deepMergeDefaults(defaultI18nConfigPartial, asObj);
154
+ }
155
+ export function validateI18nBusinessRules(config) {
156
+ const models = resolveTranslationModels(config.openrouter);
157
+ const needsDocTranslation = config.features.translateMarkdown || config.features.translateJSON;
158
+ const needsExtract = config.features.extractUIStrings;
159
+ const needsUITranslation = config.features.translateUIStrings;
160
+ const src = normalizeLocale(config.sourceLocale);
161
+ const needsSvgTranslation = config.features.translateSVG && Boolean(config.svg);
162
+ const needsSvgApi = needsSvgTranslation &&
163
+ getDocumentationTargetLocaleCodes(config).some((l) => normalizeLocale(l) !== src);
164
+ if (config.features.translateSVG && !config.svg) {
165
+ throw new ConfigValidationError("translateSVG is enabled but no svg block is configured (sourcePath, outputDir, style)");
166
+ }
167
+ if ((needsDocTranslation || needsUITranslation || needsSvgApi) && models.length === 0) {
168
+ throw new ConfigValidationError("openrouter.translationModels (non-empty array), or legacy defaultModel, is required when translateUIStrings, translateSVG (with non-source locales), or doc translate features are enabled");
169
+ }
170
+ const uiTargetsFromFileOnly = needsUITranslation && !needsDocTranslation && Boolean(config.uiLanguagesPath?.trim());
171
+ if (needsDocTranslation && getDocumentationTargetLocaleCodes(config).length === 0) {
172
+ throw new ConfigValidationError("When translateMarkdown / translateJSON is enabled, set non-empty targetLocales " +
173
+ "and/or documentations[].targetLocales (documentation-only locale list).");
174
+ }
175
+ if (needsUITranslation && config.targetLocales.length === 0 && !uiTargetsFromFileOnly) {
176
+ throw new ConfigValidationError("targetLocales must be non-empty when translateUIStrings is enabled (unless only UI translation is on and uiLanguagesPath points at your ui-languages.json), " +
177
+ 'or use a single manifest path in targetLocales (e.g. ["src/renderer/locales/ui-languages.json"])');
178
+ }
179
+ if (needsExtract && config.ui.sourceRoots.length === 0) {
180
+ throw new ConfigValidationError("ui.sourceRoots must be non-empty when extractUIStrings is enabled");
181
+ }
182
+ if (needsDocTranslation) {
183
+ const hasPaths = config.documentations.some((d) => d.contentPaths.length > 0);
184
+ if (!hasPaths) {
185
+ throw new ConfigValidationError("documentations[].contentPaths must be non-empty in at least one block when translateMarkdown / translateJSON is enabled");
186
+ }
187
+ }
188
+ }
189
+ /** Validate config for the `translate-svg` command (call after normal load). */
190
+ export function assertSvgCommandConfig(config) {
191
+ if (!config.svg) {
192
+ throw new ConfigValidationError("translate-svg requires an svg block in config: sourcePath, outputDir, style (flat | nested)");
193
+ }
194
+ const src = normalizeLocale(config.sourceLocale);
195
+ const needsApi = getDocumentationTargetLocaleCodes(config).some((l) => normalizeLocale(l) !== src);
196
+ if (needsApi) {
197
+ const models = resolveTranslationModels(config.openrouter);
198
+ if (models.length === 0) {
199
+ throw new ConfigValidationError("translate-svg requires openrouter.translationModels (or legacy defaultModel) when translating to non-source locales");
200
+ }
201
+ }
202
+ }
203
+ /**
204
+ * Parse and validate unified config (after optional merge with {@link mergeWithDefaults}).
205
+ */
206
+ export function parseI18nConfig(input) {
207
+ const parsed = i18nConfigSchema.safeParse(input);
208
+ if (!parsed.success) {
209
+ const issues = parsed.error.issues.map((e) => ({
210
+ path: e.path.join(".") || "(root)",
211
+ message: e.message,
212
+ }));
213
+ throw new ConfigValidationError(`Invalid ai-i18n-tools config: ${issues.map((i) => `${i.path}: ${i.message}`).join("; ")}`, issues);
214
+ }
215
+ validateI18nBusinessRules(parsed.data);
216
+ return parsed.data;
217
+ }
218
+ /**
219
+ * Apply environment overrides (OpenRouter and optional locale hints).
220
+ * Does not re-validate; call {@link parseI18nConfig} after merge if shape may have changed.
221
+ */
222
+ export function applyEnvOverrides(config) {
223
+ const baseUrl = process.env.OPENROUTER_BASE_URL?.trim();
224
+ const next = {
225
+ ...config,
226
+ openrouter: {
227
+ ...config.openrouter,
228
+ ...(baseUrl ? { baseUrl } : {}),
229
+ },
230
+ };
231
+ const targetsEnv = process.env.I18N_TARGET_LOCALES?.trim();
232
+ if (targetsEnv) {
233
+ next.targetLocales = parseLocaleList(targetsEnv);
234
+ }
235
+ const sourceEnv = process.env.I18N_SOURCE_LOCALE?.trim();
236
+ if (sourceEnv) {
237
+ next.sourceLocale = normalizeLocale(sourceEnv);
238
+ }
239
+ return next;
240
+ }
241
+ /**
242
+ * Load `ai-i18n-tools.config.json` or a given path; merge defaults; validate.
243
+ */
244
+ export function loadI18nConfigFromFile(configPath, cwd = process.cwd()) {
245
+ const resolved = path.isAbsolute(configPath) ? configPath : path.join(cwd, configPath);
246
+ if (!fs.existsSync(resolved)) {
247
+ throw new ConfigValidationError(`Config file not found: ${resolved}`);
248
+ }
249
+ const text = fs.readFileSync(resolved, "utf8");
250
+ let json;
251
+ try {
252
+ json = JSON.parse(text);
253
+ }
254
+ catch (e) {
255
+ throw new ConfigValidationError(`Invalid JSON in config file: ${resolved}: ${e instanceof Error ? e.message : String(e)}`);
256
+ }
257
+ const merged = mergeWithDefaults(json);
258
+ expandTargetLocalesFileReferenceInRawInput(merged, cwd);
259
+ expandDocumentationTargetLocalesInRawInput(merged, cwd);
260
+ const parsed = parseI18nConfig(merged);
261
+ const withEnv = applyEnvOverrides(parsed);
262
+ validateI18nBusinessRules(withEnv);
263
+ const augmented = augmentConfigWithUiLanguagesFile(withEnv, cwd);
264
+ if (augmented.features.translateUIStrings && resolveLocalesForUI(augmented, cwd).length === 0) {
265
+ throw new ConfigValidationError("translateUIStrings is enabled but no UI target locales resolved: set targetLocales to a locale array, " +
266
+ "a string path to ui-languages.json, and/or uiLanguagesPath (see docs/GETTING_STARTED.md)");
267
+ }
268
+ return augmented;
269
+ }
270
+ /** Default filename for `init` / CLI (Phase 4). */
271
+ export const DEFAULT_CONFIG_FILENAME = "ai-i18n-tools.config.json";
272
+ /**
273
+ * Template objects for `init`.
274
+ *
275
+ * `ui-markdown` - Workflow 1 (UI string extraction/translation) for a React/Next.js app.
276
+ * `ui-docusaurus` - Workflow 2 (markdown/JSON document translation) for Docusaurus sites.
277
+ *
278
+ * Both templates include all top-level fields so the generated file is self-documenting.
279
+ * See docs/GETTING_STARTED.md for a full annotated explanation of every field.
280
+ */
281
+ export const initConfigTemplates = {
282
+ uiMarkdown: () => ({
283
+ ...defaultI18nConfigPartial,
284
+ sourceLocale: "en-GB",
285
+ // Must match sourceLocale - path to ui-languages.json OR an array of BCP-47 codes
286
+ targetLocales: "src/locales/ui-languages.json",
287
+ openrouter: {
288
+ baseUrl: "https://openrouter.ai/api/v1",
289
+ translationModels: [...DEFAULT_OPENROUTER_MODELS],
290
+ maxTokens: 8192,
291
+ temperature: 0.2,
292
+ },
293
+ features: {
294
+ // Workflow 1: UI string extraction and translation
295
+ extractUIStrings: true,
296
+ translateUIStrings: true,
297
+ // Workflow 2: document translation (enable when you have markdown to translate)
298
+ translateMarkdown: false,
299
+ translateJSON: false,
300
+ translateSVG: false,
301
+ },
302
+ glossary: {
303
+ uiGlossary: "src/locales/strings.json",
304
+ userGlossary: "glossary-user.csv",
305
+ },
306
+ ui: {
307
+ sourceRoots: ["src/"],
308
+ stringsJson: "src/locales/strings.json",
309
+ flatOutputDir: "src/locales/",
310
+ },
311
+ // Parallelism: translate-ui effective default 4; translate-docs effective default 3 when omitted.
312
+ concurrency: 4,
313
+ // translate-docs: max parallel OpenRouter batch requests per file.
314
+ batchConcurrency: 4,
315
+ batchSize: 20,
316
+ maxBatchChars: 4096,
317
+ cacheDir: ".translation-cache",
318
+ documentations: [
319
+ {
320
+ contentPaths: [],
321
+ outputDir: "./i18n",
322
+ markdownOutput: {
323
+ style: "flat",
324
+ },
325
+ // Merged into translated markdown front matter (translation_*, source_*); omit or false to skip.
326
+ addFrontmatter: true,
327
+ },
328
+ ],
329
+ }),
330
+ uiDocusaurus: () => ({
331
+ ...defaultI18nConfigPartial,
332
+ sourceLocale: "en",
333
+ // Must match Docusaurus defaultLocale - path to ui-languages.json OR array of BCP-47 codes
334
+ targetLocales: "i18n/ui-languages.json",
335
+ openrouter: {
336
+ baseUrl: "https://openrouter.ai/api/v1",
337
+ translationModels: [...DEFAULT_OPENROUTER_MODELS],
338
+ maxTokens: 8192,
339
+ temperature: 0.2,
340
+ },
341
+ features: {
342
+ // Workflow 1: enable if you also have a React UI with t() calls to extract
343
+ extractUIStrings: false,
344
+ translateUIStrings: false,
345
+ // Workflow 2: Docusaurus document translation
346
+ translateMarkdown: true,
347
+ translateJSON: true,
348
+ translateSVG: false,
349
+ },
350
+ glossary: {
351
+ uiGlossary: "src/locales/strings.json",
352
+ userGlossary: "glossary-user.csv",
353
+ },
354
+ ui: {
355
+ sourceRoots: ["src/"],
356
+ stringsJson: "src/locales/strings.json",
357
+ flatOutputDir: "src/locales/",
358
+ },
359
+ // Docs-focused template: match translate-docs default (3) for parallel locales.
360
+ concurrency: 3,
361
+ batchConcurrency: 4,
362
+ batchSize: 20,
363
+ maxBatchChars: 4096,
364
+ cacheDir: ".translation-cache",
365
+ documentations: [
366
+ {
367
+ contentPaths: ["docs/"],
368
+ outputDir: "i18n/",
369
+ jsonSource: "i18n/en",
370
+ markdownOutput: {
371
+ // 'docusaurus' places translated files under i18n/<locale>/docusaurus-plugin-content-docs/current/
372
+ style: "docusaurus",
373
+ docsRoot: "docs",
374
+ },
375
+ addFrontmatter: true,
376
+ },
377
+ ],
378
+ }),
379
+ };
380
+ /**
381
+ * Write a starter config JSON for `ai-i18n-tools init`.
382
+ * See docs/GETTING_STARTED.md for a full annotated explanation of every field.
383
+ */
384
+ export function writeInitConfigFile(outPath, template, cwd = process.cwd()) {
385
+ const resolved = path.isAbsolute(outPath) ? outPath : path.join(cwd, outPath);
386
+ const raw = initConfigTemplates[template]();
387
+ const merged = mergeWithDefaults(raw);
388
+ parseI18nConfig(merged);
389
+ fs.mkdirSync(path.dirname(resolved), { recursive: true });
390
+ fs.writeFileSync(resolved, `${JSON.stringify(merged, null, 2)}\n`, "utf8");
391
+ }
392
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @param relPath - Path segment after the block id: project-root-relative posix (e.g. markdown under
3
+ * `contentPaths`, or JSON sources as cwd-relative paths so cleanup can resolve them next to `jsonSource`).
4
+ */
5
+ export declare function documentationFileTrackingKey(blockIndex: number, relPath: string): string;
6
+ /** Resolve a stored filepath key to an absolute path under project root for existence checks. */
7
+ export declare function resolveDocTrackingKeyToAbs(projectRoot: string, filepath: string): string;
8
+ //# sourceMappingURL=doc-file-tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-file-tracking.d.ts","sourceRoot":"","sources":["../../src/core/doc-file-tracking.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGxF;AAED,iGAAiG;AACjG,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUxF"}
@@ -0,0 +1,27 @@
1
+ import path from "path";
2
+ /**
3
+ * Namespaces documentation file-tracking keys in the shared SQLite cache when multiple
4
+ * `documentations` blocks exist, so the same relative path in different blocks does not collide.
5
+ */
6
+ const PREFIX = "doc-block:";
7
+ /**
8
+ * @param relPath - Path segment after the block id: project-root-relative posix (e.g. markdown under
9
+ * `contentPaths`, or JSON sources as cwd-relative paths so cleanup can resolve them next to `jsonSource`).
10
+ */
11
+ export function documentationFileTrackingKey(blockIndex, relPath) {
12
+ const p = relPath.split("\\").join("/");
13
+ return `${PREFIX}${blockIndex}:${p}`;
14
+ }
15
+ /** Resolve a stored filepath key to an absolute path under project root for existence checks. */
16
+ export function resolveDocTrackingKeyToAbs(projectRoot, filepath) {
17
+ if (filepath.startsWith(PREFIX)) {
18
+ const rest = filepath.slice(PREFIX.length);
19
+ const idx = rest.indexOf(":");
20
+ if (idx >= 0) {
21
+ const rel = rest.slice(idx + 1);
22
+ return path.resolve(projectRoot, rel);
23
+ }
24
+ }
25
+ return path.resolve(projectRoot, filepath);
26
+ }
27
+ //# sourceMappingURL=doc-file-tracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-file-tracking.js","sourceRoot":"","sources":["../../src/core/doc-file-tracking.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,MAAM,GAAG,YAAY,CAAC;AAE5B;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAkB,EAAE,OAAe;IAC9E,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO,GAAG,MAAM,GAAG,UAAU,IAAI,CAAC,EAAE,CAAC;AACvC,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,0BAA0B,CAAC,WAAmB,EAAE,QAAgB;IAC9E,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAChC,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** Base class for package errors with an optional machine-readable code. */
2
+ export declare class I18nToolsError extends Error {
3
+ readonly code?: string | undefined;
4
+ constructor(message: string, code?: string | undefined);
5
+ }
6
+ export declare class ConfigValidationError extends I18nToolsError {
7
+ readonly issues?: readonly {
8
+ path: string;
9
+ message: string;
10
+ }[] | undefined;
11
+ constructor(message: string, issues?: readonly {
12
+ path: string;
13
+ message: string;
14
+ }[] | undefined);
15
+ }
16
+ export declare class CacheError extends I18nToolsError {
17
+ constructor(message: string);
18
+ }
19
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qBAAa,cAAe,SAAQ,KAAK;aAGrB,IAAI,CAAC,EAAE,MAAM;gBAD7B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA;CAMhC;AAED,qBAAa,qBAAsB,SAAQ,cAAc;aAGrC,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;gBADrE,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,YAAA;CAKxE;AAED,qBAAa,UAAW,SAAQ,cAAc;gBAChC,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,23 @@
1
+ /** Base class for package errors with an optional machine-readable code. */
2
+ export class I18nToolsError extends Error {
3
+ constructor(message, code) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "I18nToolsError";
7
+ Object.setPrototypeOf(this, new.target.prototype);
8
+ }
9
+ }
10
+ export class ConfigValidationError extends I18nToolsError {
11
+ constructor(message, issues) {
12
+ super(message, "CONFIG_VALIDATION");
13
+ this.issues = issues;
14
+ this.name = "ConfigValidationError";
15
+ }
16
+ }
17
+ export class CacheError extends I18nToolsError {
18
+ constructor(message) {
19
+ super(message, "CACHE");
20
+ this.name = "CacheError";
21
+ }
22
+ }
23
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YACE,OAAe,EACC,IAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,SAAI,GAAJ,IAAI,CAAS;QAG7B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD,YACE,OAAe,EACC,MAAqD;QAErE,KAAK,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QAFpB,WAAM,GAAN,MAAM,CAA+C;QAGrE,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,cAAc;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared locale normalization and list parsing (used by config, ui-languages, CLI).
3
+ */
4
+ export declare function normalizeLocale(locale: string): string;
5
+ /**
6
+ * English language name for a BCP-47 tag (e.g. `ko` → `"Korean"`, `en-GB` → `"British English"`).
7
+ * Used for LLM prompts when `localeDisplayNames` is unset. Returns `undefined` if `Intl` cannot resolve a useful label.
8
+ */
9
+ export declare function englishLanguageNameForLocale(localeCode: string): string | undefined;
10
+ /** Split CLI/config locale lists (commas and/or ASCII whitespace). Dedupes, preserves order. */
11
+ export declare function parseLocaleList(raw: string): string[];
12
+ /**
13
+ * Normalize JSON config `targetLocales`: either a single manifest path string or an array of locale codes.
14
+ */
15
+ export declare function coerceTargetLocalesField(value: unknown): string[];
16
+ /** Mutate raw config input so `targetLocales` is always `string[]` (string → one-element array). */
17
+ export declare function assignCoercedTargetLocales(raw: {
18
+ targetLocales?: unknown;
19
+ }): void;
20
+ //# sourceMappingURL=locale-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-utils.d.ts","sourceRoot":"","sources":["../../src/core/locale-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAStD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBnF;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAerD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAWjE;AAED,oGAAoG;AACpG,wBAAgB,0BAA0B,CAAC,GAAG,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAEjF"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Shared locale normalization and list parsing (used by config, ui-languages, CLI).
3
+ */
4
+ export function normalizeLocale(locale) {
5
+ const normalized = locale.trim();
6
+ if (normalized.includes("-")) {
7
+ const parts = normalized.split("-");
8
+ if (parts.length === 2) {
9
+ return `${parts[0].toLowerCase()}-${parts[1].toUpperCase()}`;
10
+ }
11
+ }
12
+ return normalized.toLowerCase();
13
+ }
14
+ /**
15
+ * English language name for a BCP-47 tag (e.g. `ko` → `"Korean"`, `en-GB` → `"British English"`).
16
+ * Used for LLM prompts when `localeDisplayNames` is unset. Returns `undefined` if `Intl` cannot resolve a useful label.
17
+ */
18
+ export function englishLanguageNameForLocale(localeCode) {
19
+ const tag = normalizeLocale(localeCode);
20
+ if (!tag) {
21
+ return undefined;
22
+ }
23
+ try {
24
+ const dn = new Intl.DisplayNames(["en"], { type: "language" });
25
+ const name = dn.of(tag);
26
+ if (typeof name !== "string" || !name.trim()) {
27
+ return undefined;
28
+ }
29
+ const t = name.trim();
30
+ if (t.toLowerCase() === tag.toLowerCase()) {
31
+ return undefined;
32
+ }
33
+ return t;
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ /** Split CLI/config locale lists (commas and/or ASCII whitespace). Dedupes, preserves order. */
40
+ export function parseLocaleList(raw) {
41
+ const seen = new Set();
42
+ const out = [];
43
+ const parts = raw
44
+ .split(/[\s,]+/)
45
+ .map((s) => s.trim())
46
+ .filter((s) => s.length > 0);
47
+ for (const part of parts) {
48
+ const n = normalizeLocale(part);
49
+ if (!seen.has(n)) {
50
+ seen.add(n);
51
+ out.push(n);
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+ /**
57
+ * Normalize JSON config `targetLocales`: either a single manifest path string or an array of locale codes.
58
+ */
59
+ export function coerceTargetLocalesField(value) {
60
+ if (typeof value === "string") {
61
+ const t = value.trim();
62
+ return t ? [t] : [];
63
+ }
64
+ if (Array.isArray(value)) {
65
+ return value
66
+ .filter((x) => typeof x === "string" && x.trim().length > 0)
67
+ .map((x) => x.trim());
68
+ }
69
+ return [];
70
+ }
71
+ /** Mutate raw config input so `targetLocales` is always `string[]` (string → one-element array). */
72
+ export function assignCoercedTargetLocales(raw) {
73
+ Object.assign(raw, { targetLocales: coerceTargetLocalesField(raw.targetLocales) });
74
+ }
75
+ //# sourceMappingURL=locale-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-utils.js","sourceRoot":"","sources":["../../src/core/locale-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IACjC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAkB;IAC7D,MAAM,GAAG,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG;SACd,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aACxE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,0BAA0B,CAAC,GAAgC;IACzE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,wBAAwB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;AACrF,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { I18nDocTranslateConfig } from "./types.js";
2
+ export type DocArtifactKind = "markdown" | "json";
3
+ /** Normalize to forward slashes for template keys and comparisons. */
4
+ export declare function toPosix(p: string): string;
5
+ export interface PathTemplateContext {
6
+ outputDir: string;
7
+ locale: string;
8
+ relPath: string;
9
+ docsRoot: string;
10
+ }
11
+ /**
12
+ * Expand `{outputDir}`, `{locale}`, `{LOCALE}`, `{relPath}`, `{stem}`, `{basename}`, `{extension}`,
13
+ * `{docsRoot}`, `{relativeToDocsRoot}`.
14
+ */
15
+ export declare function expandPathTemplate(template: string, ctx: PathTemplateContext): string;
16
+ /**
17
+ * Resolve absolute output path for a translated documentation artifact.
18
+ */
19
+ export declare function resolveDocumentationOutputPath(config: I18nDocTranslateConfig, cwd: string, locale: string, relPath: string, kind: DocArtifactKind): string;
20
+ /** Whether to run relative link rewriting for flat markdown outputs. */
21
+ export declare function shouldRewriteFlatMarkdownLinks(config: I18nDocTranslateConfig): boolean;
22
+ //# sourceMappingURL=output-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-paths.d.ts","sourceRoot":"","sources":["../../src/core/output-paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,MAAM,CAAC;AAIlD,sEAAsE;AACtE,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAaD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,mBAAmB,GAAG,MAAM,CA4BrF;AA8DD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,GACpB,MAAM,CAuBR;AAED,wEAAwE;AACxE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAStF"}