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.
- package/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/api/openrouter.d.ts +115 -0
- package/dist/api/openrouter.d.ts.map +1 -0
- package/dist/api/openrouter.js +399 -0
- package/dist/api/openrouter.js.map +1 -0
- package/dist/cli/doc-translate.d.ts +90 -0
- package/dist/cli/doc-translate.d.ts.map +1 -0
- package/dist/cli/doc-translate.js +1153 -0
- package/dist/cli/doc-translate.js.map +1 -0
- package/dist/cli/export-ui-xliff.d.ts +32 -0
- package/dist/cli/export-ui-xliff.d.ts.map +1 -0
- package/dist/cli/export-ui-xliff.js +153 -0
- package/dist/cli/export-ui-xliff.js.map +1 -0
- package/dist/cli/extract-strings.d.ts +12 -0
- package/dist/cli/extract-strings.d.ts.map +1 -0
- package/dist/cli/extract-strings.js +80 -0
- package/dist/cli/extract-strings.js.map +1 -0
- package/dist/cli/file-utils.d.ts +10 -0
- package/dist/cli/file-utils.d.ts.map +1 -0
- package/dist/cli/file-utils.js +77 -0
- package/dist/cli/file-utils.js.map +1 -0
- package/dist/cli/format.d.ts +21 -0
- package/dist/cli/format.d.ts.map +1 -0
- package/dist/cli/format.js +75 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/helpers.d.ts +27 -0
- package/dist/cli/helpers.d.ts.map +1 -0
- package/dist/cli/helpers.js +84 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +772 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/log-output.d.ts +13 -0
- package/dist/cli/log-output.d.ts.map +1 -0
- package/dist/cli/log-output.js +75 -0
- package/dist/cli/log-output.js.map +1 -0
- package/dist/cli/translate-svg.d.ts +7 -0
- package/dist/cli/translate-svg.d.ts.map +1 -0
- package/dist/cli/translate-svg.js +167 -0
- package/dist/cli/translate-svg.js.map +1 -0
- package/dist/cli/translate-ui-strings.d.ts +27 -0
- package/dist/cli/translate-ui-strings.d.ts.map +1 -0
- package/dist/cli/translate-ui-strings.js +357 -0
- package/dist/cli/translate-ui-strings.js.map +1 -0
- package/dist/core/cache-tracking-keys.d.ts +12 -0
- package/dist/core/cache-tracking-keys.d.ts.map +1 -0
- package/dist/core/cache-tracking-keys.js +20 -0
- package/dist/core/cache-tracking-keys.js.map +1 -0
- package/dist/core/cache.d.ts +153 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +546 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/config.d.ts +58 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +392 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/doc-file-tracking.d.ts +8 -0
- package/dist/core/doc-file-tracking.d.ts.map +1 -0
- package/dist/core/doc-file-tracking.js +27 -0
- package/dist/core/doc-file-tracking.js.map +1 -0
- package/dist/core/errors.d.ts +19 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +23 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/locale-utils.d.ts +20 -0
- package/dist/core/locale-utils.d.ts.map +1 -0
- package/dist/core/locale-utils.js +75 -0
- package/dist/core/locale-utils.js.map +1 -0
- package/dist/core/output-paths.d.ts +22 -0
- package/dist/core/output-paths.d.ts.map +1 -0
- package/dist/core/output-paths.js +130 -0
- package/dist/core/output-paths.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +62 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +232 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/prompts.d.ts +27 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +57 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/svg-asset-paths.d.ts +40 -0
- package/dist/core/svg-asset-paths.d.ts.map +1 -0
- package/dist/core/svg-asset-paths.js +107 -0
- package/dist/core/svg-asset-paths.js.map +1 -0
- package/dist/core/types.d.ts +388 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +265 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/ui-languages.d.ts +66 -0
- package/dist/core/ui-languages.d.ts.map +1 -0
- package/dist/core/ui-languages.js +277 -0
- package/dist/core/ui-languages.js.map +1 -0
- package/dist/core/user-edited-model.d.ts +3 -0
- package/dist/core/user-edited-model.d.ts.map +1 -0
- package/dist/core/user-edited-model.js +3 -0
- package/dist/core/user-edited-model.js.map +1 -0
- package/dist/edit-cache-app/app.js +1326 -0
- package/dist/edit-cache-app/index.html +287 -0
- package/dist/edit-cache-app/styles.css +664 -0
- package/dist/extractors/base-extractor.d.ts +15 -0
- package/dist/extractors/base-extractor.d.ts.map +1 -0
- package/dist/extractors/base-extractor.js +23 -0
- package/dist/extractors/base-extractor.js.map +1 -0
- package/dist/extractors/classify-segment.d.ts +6 -0
- package/dist/extractors/classify-segment.d.ts.map +1 -0
- package/dist/extractors/classify-segment.js +20 -0
- package/dist/extractors/classify-segment.js.map +1 -0
- package/dist/extractors/json-extractor.d.ts +16 -0
- package/dist/extractors/json-extractor.d.ts.map +1 -0
- package/dist/extractors/json-extractor.js +128 -0
- package/dist/extractors/json-extractor.js.map +1 -0
- package/dist/extractors/markdown-extractor.d.ts +15 -0
- package/dist/extractors/markdown-extractor.d.ts.map +1 -0
- package/dist/extractors/markdown-extractor.js +205 -0
- package/dist/extractors/markdown-extractor.js.map +1 -0
- package/dist/extractors/svg-extractor.d.ts +19 -0
- package/dist/extractors/svg-extractor.d.ts.map +1 -0
- package/dist/extractors/svg-extractor.js +132 -0
- package/dist/extractors/svg-extractor.js.map +1 -0
- package/dist/extractors/ui-string-extractor.d.ts +40 -0
- package/dist/extractors/ui-string-extractor.d.ts.map +1 -0
- package/dist/extractors/ui-string-extractor.js +146 -0
- package/dist/extractors/ui-string-extractor.js.map +1 -0
- package/dist/extractors/ui-string-locations.d.ts +23 -0
- package/dist/extractors/ui-string-locations.d.ts.map +1 -0
- package/dist/extractors/ui-string-locations.js +138 -0
- package/dist/extractors/ui-string-locations.js.map +1 -0
- package/dist/glossary/glossary.d.ts +34 -0
- package/dist/glossary/glossary.d.ts.map +1 -0
- package/dist/glossary/glossary.js +260 -0
- package/dist/glossary/glossary.js.map +1 -0
- package/dist/glossary/matcher.d.ts +10 -0
- package/dist/glossary/matcher.d.ts.map +1 -0
- package/dist/glossary/matcher.js +12 -0
- package/dist/glossary/matcher.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/processors/admonition-placeholders.d.ts +8 -0
- package/dist/processors/admonition-placeholders.d.ts.map +1 -0
- package/dist/processors/admonition-placeholders.js +59 -0
- package/dist/processors/admonition-placeholders.js.map +1 -0
- package/dist/processors/anchor-placeholders.d.ts +8 -0
- package/dist/processors/anchor-placeholders.d.ts.map +1 -0
- package/dist/processors/anchor-placeholders.js +37 -0
- package/dist/processors/anchor-placeholders.js.map +1 -0
- package/dist/processors/batch-processor.d.ts +10 -0
- package/dist/processors/batch-processor.d.ts.map +1 -0
- package/dist/processors/batch-processor.js +33 -0
- package/dist/processors/batch-processor.js.map +1 -0
- package/dist/processors/bold-code-placeholders.d.ts +14 -0
- package/dist/processors/bold-code-placeholders.d.ts.map +1 -0
- package/dist/processors/bold-code-placeholders.js +116 -0
- package/dist/processors/bold-code-placeholders.js.map +1 -0
- package/dist/processors/doc-postprocess.d.ts +51 -0
- package/dist/processors/doc-postprocess.d.ts.map +1 -0
- package/dist/processors/doc-postprocess.js +215 -0
- package/dist/processors/doc-postprocess.js.map +1 -0
- package/dist/processors/emphasis-placeholders.d.ts +6 -0
- package/dist/processors/emphasis-placeholders.d.ts.map +1 -0
- package/dist/processors/emphasis-placeholders.js +262 -0
- package/dist/processors/emphasis-placeholders.js.map +1 -0
- package/dist/processors/flat-link-rewrite.d.ts +32 -0
- package/dist/processors/flat-link-rewrite.d.ts.map +1 -0
- package/dist/processors/flat-link-rewrite.js +90 -0
- package/dist/processors/flat-link-rewrite.js.map +1 -0
- package/dist/processors/glossary-force-placeholders.d.ts +12 -0
- package/dist/processors/glossary-force-placeholders.d.ts.map +1 -0
- package/dist/processors/glossary-force-placeholders.js +58 -0
- package/dist/processors/glossary-force-placeholders.js.map +1 -0
- package/dist/processors/inline-code-placeholders.d.ts +11 -0
- package/dist/processors/inline-code-placeholders.d.ts.map +1 -0
- package/dist/processors/inline-code-placeholders.js +87 -0
- package/dist/processors/inline-code-placeholders.js.map +1 -0
- package/dist/processors/placeholder-handler.d.ts +38 -0
- package/dist/processors/placeholder-handler.d.ts.map +1 -0
- package/dist/processors/placeholder-handler.js +55 -0
- package/dist/processors/placeholder-handler.js.map +1 -0
- package/dist/processors/translation-placeholder-leaks.d.ts +2 -0
- package/dist/processors/translation-placeholder-leaks.d.ts.map +1 -0
- package/dist/processors/translation-placeholder-leaks.js +9 -0
- package/dist/processors/translation-placeholder-leaks.js.map +1 -0
- package/dist/processors/url-placeholders.d.ts +10 -0
- package/dist/processors/url-placeholders.d.ts.map +1 -0
- package/dist/processors/url-placeholders.js +29 -0
- package/dist/processors/url-placeholders.js.map +1 -0
- package/dist/processors/validator.d.ts +23 -0
- package/dist/processors/validator.d.ts.map +1 -0
- package/dist/processors/validator.js +186 -0
- package/dist/processors/validator.js.map +1 -0
- package/dist/runtime/i18next-helpers.d.ts +146 -0
- package/dist/runtime/i18next-helpers.d.ts.map +1 -0
- package/dist/runtime/i18next-helpers.js +192 -0
- package/dist/runtime/i18next-helpers.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/template.d.ts +21 -0
- package/dist/runtime/template.d.ts.map +1 -0
- package/dist/runtime/template.js +28 -0
- package/dist/runtime/template.js.map +1 -0
- package/dist/runtime/ui-language-display.d.ts +16 -0
- package/dist/runtime/ui-language-display.d.ts.map +1 -0
- package/dist/runtime/ui-language-display.js +26 -0
- package/dist/runtime/ui-language-display.js.map +1 -0
- package/dist/server/translation-editor.d.ts +25 -0
- package/dist/server/translation-editor.d.ts.map +1 -0
- package/dist/server/translation-editor.js +583 -0
- package/dist/server/translation-editor.js.map +1 -0
- package/dist/utils/concurrency.d.ts +31 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +103 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/hash.d.ts +5 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +9 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/ignore-parser.d.ts +7 -0
- package/dist/utils/ignore-parser.d.ts.map +1 -0
- package/dist/utils/ignore-parser.js +26 -0
- package/dist/utils/ignore-parser.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +158 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/GETTING_STARTED.md +697 -0
- package/docs/PACKAGE_OVERVIEW.md +427 -0
- package/docs/ai-i18n-tools-context.md +481 -0
- package/package.json +117 -0
- package/translated-docs/README.de.md +157 -0
- package/translated-docs/README.es.md +157 -0
- package/translated-docs/README.fr.md +157 -0
- package/translated-docs/README.hi.md +157 -0
- package/translated-docs/README.ja.md +157 -0
- package/translated-docs/README.ko.md +157 -0
- package/translated-docs/README.pt-BR.md +157 -0
- package/translated-docs/README.zh-CN.md +157 -0
- package/translated-docs/README.zh-TW.md +157 -0
- package/translated-docs/docs/GETTING_STARTED.de.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.es.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.fr.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.hi.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.ja.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.ko.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.pt-BR.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.zh-CN.md +682 -0
- package/translated-docs/docs/GETTING_STARTED.zh-TW.md +682 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.de.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.es.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.fr.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.hi.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.ja.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.ko.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.pt-BR.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.zh-CN.md +428 -0
- package/translated-docs/docs/PACKAGE_OVERVIEW.zh-TW.md +428 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# ai-i18n-tools:套件概述
|
|
2
|
+
|
|
3
|
+
本文件描述了 `ai-i18n-tools` 的內部架構,各組件如何協同運作,以及兩個核心工作流程的實現方式。
|
|
4
|
+
|
|
5
|
+
有關實際使用說明,請參見 [GETTING_STARTED.md](GETTING_STARTED.zh-TW.md)。
|
|
6
|
+
|
|
7
|
+
<small>**以其他語言閱讀:**</small>
|
|
8
|
+
|
|
9
|
+
<small id="lang-list">[en-GB](../../docs/PACKAGE_OVERVIEW.md) · [de](./PACKAGE_OVERVIEW.de.md) · [es](./PACKAGE_OVERVIEW.es.md) · [fr](./PACKAGE_OVERVIEW.fr.md) · [hi](./PACKAGE_OVERVIEW.hi.md) · [ja](./PACKAGE_OVERVIEW.ja.md) · [ko](./PACKAGE_OVERVIEW.ko.md) · [pt-BR](./PACKAGE_OVERVIEW.pt-BR.md) · [zh-CN](./PACKAGE_OVERVIEW.zh-CN.md) · [zh-TW](./PACKAGE_OVERVIEW.zh-TW.md)</small>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
14
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
15
|
+
**目錄**
|
|
16
|
+
|
|
17
|
+
- [架構概述](#architecture-overview)
|
|
18
|
+
- [源碼樹](#source-tree)
|
|
19
|
+
- [工作流程 1 - UI 翻譯內部](#workflow-1---ui-translation-internals)
|
|
20
|
+
- [`UIStringExtractor`](#uistringextractor)
|
|
21
|
+
- [`strings.json`](#stringsjson)
|
|
22
|
+
- [平面區域文件](#flat-locale-files)
|
|
23
|
+
- [UI 翻譯提示](#ui-translation-prompts)
|
|
24
|
+
- [工作流程 2 - 文檔翻譯內部](#workflow-2---document-translation-internals)
|
|
25
|
+
- [提取器](#extractors)
|
|
26
|
+
- [佔位符保護](#placeholder-protection)
|
|
27
|
+
- [緩存 (`TranslationCache`)](#cache-translationcache)
|
|
28
|
+
- [輸出路徑解析](#output-path-resolution)
|
|
29
|
+
- [平面鏈接重寫](#flat-link-rewriting)
|
|
30
|
+
- [共享基礎設施](#shared-infrastructure)
|
|
31
|
+
- [`OpenRouterClient`](#openrouterclient)
|
|
32
|
+
- [配置加載](#config-loading)
|
|
33
|
+
- [日誌記錄器](#logger)
|
|
34
|
+
- [運行時幫助 API](#runtime-helpers-api)
|
|
35
|
+
- [RTL 幫助器](#rtl-helpers)
|
|
36
|
+
- [i18next 設置工廠](#i18next-setup-factories)
|
|
37
|
+
- [顯示幫助器](#display-helpers)
|
|
38
|
+
- [字符串幫助器](#string-helpers)
|
|
39
|
+
- [程序化 API](#programmatic-api)
|
|
40
|
+
- [擴展點](#extension-points)
|
|
41
|
+
- [自定義函數名稱 (UI 提取)](#custom-function-names-ui-extraction)
|
|
42
|
+
- [自定義提取器](#custom-extractors)
|
|
43
|
+
- [自定義輸出路徑](#custom-output-paths)
|
|
44
|
+
|
|
45
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 架構概述
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
ai-i18n-tools
|
|
53
|
+
├── CLI (src/cli/) - commands: init, extract, translate-docs, translate-svg, translate-ui, sync, status, …
|
|
54
|
+
├── Core (src/core/) - config, types, cache, prompts, output paths, UI languages
|
|
55
|
+
├── Extractors (src/extractors/) - segment extraction from JS/TS, markdown, JSON, SVG
|
|
56
|
+
├── Processors (src/processors/) - placeholders, batching, validation, link rewriting
|
|
57
|
+
├── API (src/api/) - OpenRouter HTTP client
|
|
58
|
+
├── Glossary (src/glossary/) - glossary loading and term matching
|
|
59
|
+
├── Runtime (src/runtime/) - i18next helpers, display helpers (no i18next import)
|
|
60
|
+
├── Server (src/server/) - local Express web editor for cache / glossary
|
|
61
|
+
└── Utils (src/utils/) - logger, hash, ignore parser
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
消費者可能需要的所有程序化內容都從 `src/index.ts` 重新導出。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 源碼樹
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
src/
|
|
72
|
+
├── index.ts Public API re-exports
|
|
73
|
+
│
|
|
74
|
+
├── cli/
|
|
75
|
+
│ ├── index.ts CLI entry point (commander)
|
|
76
|
+
│ ├── extract-strings.ts `extract` command implementation
|
|
77
|
+
│ ├── translate-ui-strings.ts `translate-ui` command implementation
|
|
78
|
+
│ ├── doc-translate.ts `translate-docs` command (documentation files only)
|
|
79
|
+
│ ├── translate-svg.ts `translate-svg` command (standalone assets from `config.svg`)
|
|
80
|
+
│ ├── helpers.ts Shared CLI utilities
|
|
81
|
+
│ └── file-utils.ts File collection helpers
|
|
82
|
+
│
|
|
83
|
+
├── core/
|
|
84
|
+
│ ├── types.ts Zod schemas + TypeScript types for all config shapes
|
|
85
|
+
│ ├── config.ts Config loading, merging, validation, init templates
|
|
86
|
+
│ ├── cache.ts SQLite translation cache (node:sqlite)
|
|
87
|
+
│ ├── prompt-builder.ts LLM prompt construction for docs and UI strings
|
|
88
|
+
│ ├── output-paths.ts Docusaurus / flat output path resolution
|
|
89
|
+
│ ├── ui-languages.ts ui-languages.json loading and locale resolution
|
|
90
|
+
│ ├── locale-utils.ts BCP-47 normalization and locale list parsing
|
|
91
|
+
│ └── errors.ts Typed error classes
|
|
92
|
+
│
|
|
93
|
+
├── extractors/
|
|
94
|
+
│ ├── base-extractor.ts Abstract base class for all extractors
|
|
95
|
+
│ ├── ui-string-extractor.ts JS/TS source scanner (i18next-scanner)
|
|
96
|
+
│ ├── classify-segment.ts Heuristic segment type classification
|
|
97
|
+
│ ├── markdown-extractor.ts Markdown / MDX segment extraction
|
|
98
|
+
│ ├── json-extractor.ts JSON label file extraction
|
|
99
|
+
│ └── svg-extractor.ts SVG text extraction
|
|
100
|
+
│
|
|
101
|
+
├── processors/
|
|
102
|
+
│ ├── placeholder-handler.ts Chain: admonitions → anchors → URLs
|
|
103
|
+
│ ├── url-placeholders.ts Markdown URL protection/restore
|
|
104
|
+
│ ├── admonition-placeholders.ts Docusaurus admonition protection/restore
|
|
105
|
+
│ ├── anchor-placeholders.ts HTML anchor / heading ID protection/restore
|
|
106
|
+
│ ├── batch-processor.ts Segment → batch grouping (count + char limits)
|
|
107
|
+
│ ├── validator.ts Post-translation structural checks
|
|
108
|
+
│ └── flat-link-rewrite.ts Relative link rewriting for flat output
|
|
109
|
+
│
|
|
110
|
+
├── api/
|
|
111
|
+
│ └── openrouter.ts OpenRouter HTTP client with model fallback chain
|
|
112
|
+
│
|
|
113
|
+
├── glossary/
|
|
114
|
+
│ ├── glossary.ts Glossary loading (CSV + auto-build from strings.json)
|
|
115
|
+
│ └── matcher.ts Term hint extraction for prompts
|
|
116
|
+
│
|
|
117
|
+
├── runtime/
|
|
118
|
+
│ ├── index.ts Runtime re-exports
|
|
119
|
+
│ ├── template.ts interpolateTemplate, flipUiArrowsForRtl
|
|
120
|
+
│ ├── ui-language-display.ts getUILanguageLabel, getUILanguageLabelNative
|
|
121
|
+
│ └── i18next-helpers.ts RTL detection, i18next setup factories
|
|
122
|
+
│
|
|
123
|
+
├── server/
|
|
124
|
+
│ └── translation-editor.ts Express app for cache / strings.json / glossary editor
|
|
125
|
+
│
|
|
126
|
+
└── utils/
|
|
127
|
+
├── logger.ts Leveled logger with ANSI support
|
|
128
|
+
├── hash.ts Segment hash (SHA-256 first 16 hex)
|
|
129
|
+
└── ignore-parser.ts .translate-ignore file parser
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 工作流程 1 - UI 翻譯內部
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
source files (JS/TS)
|
|
138
|
+
│
|
|
139
|
+
▼ UIStringExtractor (i18next-scanner Parser)
|
|
140
|
+
strings.json ─────────────────── master catalog
|
|
141
|
+
│ { hash: { source, translated, models?, locations? } }
|
|
142
|
+
▼
|
|
143
|
+
OpenRouterClient.translateUIBatch()
|
|
144
|
+
│ sends JSON array of source strings, receives JSON array of translations (+ model id per batch)
|
|
145
|
+
▼
|
|
146
|
+
de.json, pt-BR.json … ─────────── per-locale flat maps: source → translation (no model metadata)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `UIStringExtractor`
|
|
150
|
+
|
|
151
|
+
使用 `i18next-scanner` 的 `Parser.parseFuncFromString` 來查找任何 JS/TS 文件中的 `t("literal")` 和 `i18n.t("literal")` 調用。函數名稱和文件擴展名是可配置的,當啟用 `reactExtractor.includePackageDescription` 時,提取還可以包括項目的 `package.json` `description`。段哈希是修剪後源字符串的 **MD5 前 8 個十六進制字符** - 這些成為 `strings.json` 中的鍵。
|
|
152
|
+
|
|
153
|
+
### `strings.json`
|
|
154
|
+
|
|
155
|
+
主目錄的結構為:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"<md5-8>": {
|
|
160
|
+
"source": "The English string",
|
|
161
|
+
"translated": {
|
|
162
|
+
"de": "Der deutsche Text",
|
|
163
|
+
"pt-BR": "O texto em português"
|
|
164
|
+
},
|
|
165
|
+
"models": {
|
|
166
|
+
"de": "anthropic/claude-3.5-haiku",
|
|
167
|
+
"pt-BR": "openai/gpt-4o"
|
|
168
|
+
},
|
|
169
|
+
"locations": [{ "file": "src/app/page.tsx", "line": 51 }]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`models`(選用)— 每個語系,標示該語系在上一次成功的 `translate-ui` 執行後,是由哪個模型產生的翻譯(若文字是從 `editor` 網頁 UI 儲存的,則為 `user-edited`)。`locations`(選用)— `extract` 發現字串的位置。
|
|
175
|
+
|
|
176
|
+
`extract` 會新增鍵值,並保留仍存在於掃描中的鍵之現有 `translated` / `models` 資料。`translate-ui` 會填入遺漏的 `translated` 條目,更新其所翻譯語系的 `models`,並寫入扁平化的語系檔案。
|
|
177
|
+
|
|
178
|
+
### 平面區域文件
|
|
179
|
+
|
|
180
|
+
每個目標語系會取得一個扁平的 JSON 檔案(例如 `de.json`),將原始字串對應至翻譯(不含 `models` 欄位):
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"The English string": "Der deutsche Text",
|
|
185
|
+
"Save": "Speichern"
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
i18next 將這些作為資源包加載,並通過源字符串查找翻譯(鍵作為默認模型)。
|
|
190
|
+
|
|
191
|
+
### UI 翻譯提示
|
|
192
|
+
|
|
193
|
+
`buildUIPromptMessages` 構建系統 + 用戶消息,該消息:
|
|
194
|
+
- 確定源語言和目標語言(通過 `localeDisplayNames` 或 `ui-languages.json` 中的顯示名稱)。
|
|
195
|
+
- 發送 JSON 字符串數組並請求返回 JSON 翻譯數組。
|
|
196
|
+
- 在可用時包括詞彙提示。
|
|
197
|
+
|
|
198
|
+
`OpenRouterClient.translateUIBatch` 會依序嘗試每個模型,並在解析或網路錯誤時進行備援。CLI 會根據 `openrouter.translationModels`(或舊版的預設/備援)建立此清單;對於 `translate-ui`,若設定 `ui.preferredModel`,則會將其前置(與其餘清單去重複)。
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 工作流程 2 - 文檔翻譯內部
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
markdown/MDX/JSON files (`translate-docs`)
|
|
206
|
+
│
|
|
207
|
+
▼ MarkdownExtractor / JsonExtractor
|
|
208
|
+
segments[] ─────────────────── typed segments with hash + content
|
|
209
|
+
│
|
|
210
|
+
▼ PlaceholderHandler
|
|
211
|
+
protected text ──────────────── URLs, admonitions, anchors replaced with tokens
|
|
212
|
+
│
|
|
213
|
+
▼ splitTranslatableIntoBatches
|
|
214
|
+
batches[] ───────────────────── grouped by count + char limit
|
|
215
|
+
│
|
|
216
|
+
▼ TranslationCache lookup
|
|
217
|
+
cache hit → skip, miss → OpenRouterClient.translateDocumentBatch
|
|
218
|
+
│
|
|
219
|
+
▼ PlaceholderHandler.restoreAfterTranslation
|
|
220
|
+
final text ──────────────────── placeholders restored
|
|
221
|
+
│
|
|
222
|
+
▼ resolveDocumentationOutputPath
|
|
223
|
+
output file ─────────────────── Docusaurus layout or flat layout
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 提取器
|
|
227
|
+
|
|
228
|
+
所有提取器都擴展 `BaseExtractor` 並實現 `extract(content, filepath): Segment[]`。
|
|
229
|
+
|
|
230
|
+
- `MarkdownExtractor` - 將 Markdown 拆分為帶類型的區段:`frontmatter`、`heading`、`paragraph`、`code`、`admonition`。不可翻譯的區段(程式碼區塊、原始 HTML)會原樣保留。
|
|
231
|
+
- `JsonExtractor` - 從 Docusaurus JSON 標籤檔案中提取字串值。
|
|
232
|
+
- `SvgExtractor` - 從 SVG 提取 `<text>`、`<title>` 和 `<desc>` 內容(由 `translate-svg` 用於 `config.svg` 下的資源,不供 `translate-docs` 使用)。
|
|
233
|
+
|
|
234
|
+
### 佔位符保護
|
|
235
|
+
|
|
236
|
+
在翻譯之前,敏感語法會被不透明的標記替換,以防止 LLM 的損壞:
|
|
237
|
+
|
|
238
|
+
1. **Admonition 標記** (`:::note`, `:::`) - 恢復為精確的原始文本。
|
|
239
|
+
2. **文檔錨點** (HTML `<a id="…">`,Docusaurus 標題 `{#…}`) - 逐字保留。
|
|
240
|
+
3. **Markdown URL** (`](url)`,`src="../…"`) - 在翻譯後從映射中恢復。
|
|
241
|
+
|
|
242
|
+
### 緩存 (`TranslationCache`)
|
|
243
|
+
|
|
244
|
+
SQLite 數據庫(通過 `node:sqlite`)存儲以 `(source_hash, locale)` 為鍵的行,包含 `translated_text`、`model`、`filepath`、`last_hit_at` 和相關字段。哈希是標準化內容的 SHA-256 前 16 個十六進制字符(空白折疊)。
|
|
245
|
+
|
|
246
|
+
在每次運行中,根據哈希 × 語言環境查找段落。只有緩存未命中才會發送到 LLM。翻譯後,當前翻譯範圍內未命中的段落的 `last_hit_at` 將重置。`cleanup` 首先運行 `sync --force-update`,然後刪除過期的段落行(null `last_hit_at` / 空的 filepath),在解析的源路徑在磁碟上缺失時修剪 `file_tracking` 鍵(`doc-block:…`、`svg-assets:…` 等),並刪除其元數據 filepath 指向缺失文件的翻譯行;除非傳遞 `--no-backup`,否則會先備份 `cache.db`。
|
|
247
|
+
|
|
248
|
+
`translate-docs` 命令還使用 **文件跟踪**,因此未更改的源文件具有現有輸出可以完全跳過工作。`--force-update` 重新運行文件處理,同時仍使用段落緩存;`--force` 清除文件跟踪並繞過段落緩存讀取以進行 API 翻譯。請參見 [Getting Started](GETTING_STARTED.zh-TW.md#cache-behaviour-and-translate-docs-flags) 獲取完整的標誌表。
|
|
249
|
+
|
|
250
|
+
**批次提示格式:** `translate-docs --prompt-format` 僅針對 `OpenRouterClient.translateDocumentBatch` 選擇 XML(`<seg>` / `<t>`)或 JSON 陣列/物件格式;擷取、佔位符與驗證保持不變。請參閱 [批次提示格式](GETTING_STARTED.zh-TW.md#batch-prompt-format)。
|
|
251
|
+
|
|
252
|
+
### 輸出路徑解析
|
|
253
|
+
|
|
254
|
+
`resolveDocumentationOutputPath(config, cwd, locale, relPath, kind)` 將源相對路徑映射到輸出路徑:
|
|
255
|
+
|
|
256
|
+
- `nested` 樣式(預設):Markdown 使用 `{outputDir}/{locale}/{relPath}`。
|
|
257
|
+
- `docusaurus` 樣式:在 `docsRoot` 下,輸出使用 `{outputDir}/{locale}/docusaurus-plugin-content-docs/current/{relativeToDocsRoot}`;在 `docsRoot` 外的路徑則回退至 nested 版面配置。
|
|
258
|
+
- `flat` 樣式:`{outputDir}/{stem}.{locale}{extension}`。當 `flatPreserveRelativeDir` 為 `true` 時,原始來源的子目錄會保留在 `outputDir` 下。
|
|
259
|
+
- **自訂** `pathTemplate`:使用 `{outputDir}`、`{locale}`、`{LOCALE}`、`{relPath}`、`{stem}`、`{basename}`、`{extension}`、`{docsRoot}`、`{relativeToDocsRoot}` 的任何 Markdown 版面配置。
|
|
260
|
+
- **自訂** `jsonPathTemplate`:針對 JSON 標籤檔案的獨立自訂版面配置,使用相同的佔位符。
|
|
261
|
+
- `linkRewriteDocsRoot` 協助扁平化連結重寫器在翻譯輸出根目錄不同於預設專案根目錄時,計算正確的前置詞。
|
|
262
|
+
|
|
263
|
+
### 平面鏈接重寫
|
|
264
|
+
|
|
265
|
+
當 `markdownOutput.style === "flat"` 時,翻譯後的 markdown 文件將與源文件並排放置,並帶有語言後綴。頁面之間的相對鏈接會被重寫,以便 `readme.de.md` 中的 `[Guide](../guide.md)` 指向 `guide.de.md`。由 `rewriteRelativeLinks` 控制(在沒有自定義 `pathTemplate` 的平面樣式中自動啟用)。
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## 共享基礎設施
|
|
270
|
+
|
|
271
|
+
### `OpenRouterClient`
|
|
272
|
+
|
|
273
|
+
封裝 OpenRouter 聊天完成 API。主要行為:
|
|
274
|
+
|
|
275
|
+
- **模型回退**:按順序嘗試解析列表中的每個模型;在 HTTP 錯誤或解析失敗時回退。當存在時,UI 翻譯首先解析 `ui.preferredModel`,然後是 `openrouter` 模型。
|
|
276
|
+
- **速率限制**:檢測到 429 響應,等待 `retry-after`(或 2 秒),然後重試一次。
|
|
277
|
+
- **提示緩存**:系統消息以 `cache_control: { type: "ephemeral" }` 發送,以啟用支持模型的提示緩存。
|
|
278
|
+
- **調試流量日誌**:如果設置了 `debugTrafficFilePath`,則將請求和響應 JSON 附加到文件中。
|
|
279
|
+
|
|
280
|
+
### 配置加載
|
|
281
|
+
|
|
282
|
+
`loadI18nConfigFromFile(configPath, cwd)` 管道:
|
|
283
|
+
|
|
284
|
+
1. 讀取並解析 `ai-i18n-tools.config.json`(JSON)。
|
|
285
|
+
2. `mergeWithDefaults` - 與 `defaultI18nConfigPartial` 深度合併,並將任何 `documentations[].sourceFiles` 條目合併到 `contentPaths` 中。
|
|
286
|
+
3. `expandTargetLocalesFileReferenceInRawInput` - 如果 `targetLocales` 是文件路徑,則加載清單並擴展為區域代碼;設置 `uiLanguagesPath`。
|
|
287
|
+
4. `expandDocumentationTargetLocalesInRawInput` - 對每個 `documentations[].targetLocales` 條目執行相同操作。
|
|
288
|
+
5. `parseI18nConfig` - Zod 驗證 + `validateI18nBusinessRules`。
|
|
289
|
+
6. `applyEnvOverrides` - 應用 `OPENROUTER_API_KEY`、`I18N_SOURCE_LOCALE` 等。
|
|
290
|
+
7. `augmentConfigWithUiLanguagesFile` - 附加清單顯示名稱。
|
|
291
|
+
|
|
292
|
+
### 日誌記錄器
|
|
293
|
+
|
|
294
|
+
`Logger` 支持 `debug`、`info`、`warn`、`error` 等級,並提供 ANSI 顏色輸出。詳細模式(`-v`)啟用 `debug`。當設置 `logFilePath` 時,日誌行也會寫入該文件。
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 運行時輔助 API
|
|
299
|
+
|
|
300
|
+
這些從 `'ai-i18n-tools/runtime'` 導出,並在任何 JavaScript 環境中工作(瀏覽器、Node.js、Deno、Edge)。它們**不**從 `i18next` 或 `react-i18next` 導入。
|
|
301
|
+
|
|
302
|
+
### RTL 輔助工具
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
RTL_LANGS: ReadonlySet<string>
|
|
306
|
+
getTextDirection(lng: string): 'ltr' | 'rtl'
|
|
307
|
+
applyDirection(lng: string, element?: Element): void
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### i18next 設置工廠
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
defaultI18nInitOptions(sourceLocale?: string): i18nextInitOptions
|
|
314
|
+
wrapI18nWithKeyTrim(i18n: I18nLike): void
|
|
315
|
+
makeLoadLocale(
|
|
316
|
+
i18n: I18nWithResources,
|
|
317
|
+
localeLoaders: Record<string, () => Promise<unknown>>,
|
|
318
|
+
sourceLocale?: string
|
|
319
|
+
): (lang: string) => Promise<void>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### 顯示輔助工具
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
getUILanguageLabel(lang: UiLanguageEntry, t: TranslateFn): string
|
|
326
|
+
getUILanguageLabelNative(lang: UiLanguageEntry): string
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 字串輔助工具
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
interpolateTemplate(str: string, vars: Record<string, string | number | boolean>): string
|
|
333
|
+
flipUiArrowsForRtl(text: string | null | undefined, isRtl: boolean): string | null | undefined
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 程式化 API
|
|
339
|
+
|
|
340
|
+
所有公共類型和類別都從包根目錄導出。示例:從 Node.js 運行 translate-UI 步驟而不使用 CLI:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
import { loadI18nConfigFromFile, runTranslateUI } from 'ai-i18n-tools';
|
|
344
|
+
|
|
345
|
+
// Config must have features.translateUIStrings: true (and valid targetLocales, etc.).
|
|
346
|
+
const config = loadI18nConfigFromFile('ai-i18n-tools.config.json');
|
|
347
|
+
|
|
348
|
+
const summary = await runTranslateUI(config, {
|
|
349
|
+
cwd: process.cwd(),
|
|
350
|
+
locales: config.targetLocales,
|
|
351
|
+
force: false,
|
|
352
|
+
dryRun: false,
|
|
353
|
+
verbose: false,
|
|
354
|
+
});
|
|
355
|
+
console.log(
|
|
356
|
+
`Updated ${summary.stringsUpdated} string(s); locales touched: ${summary.localesTouched.join(', ')}`
|
|
357
|
+
);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
關鍵導出:
|
|
361
|
+
|
|
362
|
+
| 導出 | 描述 |
|
|
363
|
+
|---|---|
|
|
364
|
+
| `loadI18nConfigFromFile` | 從 JSON 文件加載、合併、驗證配置。 |
|
|
365
|
+
| `parseI18nConfig` | 驗證原始配置對象。 |
|
|
366
|
+
| `TranslationCache` | SQLite 緩存 - 使用 `cacheDir` 路徑實例化。 |
|
|
367
|
+
| `UIStringExtractor` | 從 JS/TS 源中提取 `t("…")` 字串。 |
|
|
368
|
+
| `MarkdownExtractor` | 從 markdown 中提取可翻譯的片段。 |
|
|
369
|
+
| `JsonExtractor` | 從 Docusaurus JSON 標籤文件中提取。 |
|
|
370
|
+
| `SvgExtractor` | 從 SVG 文件中提取。 |
|
|
371
|
+
| `OpenRouterClient` | 向 OpenRouter 發送翻譯請求。 |
|
|
372
|
+
| `PlaceholderHandler` | 保護/恢復翻譯周圍的 markdown 語法。 |
|
|
373
|
+
| `splitTranslatableIntoBatches` | 將片段分組為 LLM 大小的批次。 |
|
|
374
|
+
| `validateTranslation` | 翻譯後的結構檢查。 |
|
|
375
|
+
| `resolveDocumentationOutputPath` | 解決翻譯文檔的輸出文件路徑。 |
|
|
376
|
+
| `Glossary` / `GlossaryMatcher` | 加載和應用翻譯詞彙表。 |
|
|
377
|
+
| `runTranslateUI` | 程式化 translate-UI 入口點。 |
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 擴展點
|
|
382
|
+
|
|
383
|
+
### 自定義函數名稱(UI 提取)
|
|
384
|
+
|
|
385
|
+
通過配置添加非標準翻譯函數名稱:
|
|
386
|
+
|
|
387
|
+
```json
|
|
388
|
+
{
|
|
389
|
+
"ui": {
|
|
390
|
+
"reactExtractor": {
|
|
391
|
+
"funcNames": ["t", "i18n.t", "translate", "i18n.translate"]
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### 自定義提取器
|
|
398
|
+
|
|
399
|
+
從套件中實作 `ContentExtractor`:
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
import { BaseExtractor, type Segment } from 'ai-i18n-tools';
|
|
403
|
+
|
|
404
|
+
class MyExtractor extends BaseExtractor {
|
|
405
|
+
readonly name = 'my-format';
|
|
406
|
+
canHandle(filepath: string) { return filepath.endsWith('.myext'); }
|
|
407
|
+
extract(content: string): Segment[] { /* … */ }
|
|
408
|
+
reassemble(segments: Segment[], translations: Map<string, string>): string { /* … */ }
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
通過以程式方式導入 `doc-translate.ts` 工具,將其傳遞到 doc-translate 管道。
|
|
413
|
+
|
|
414
|
+
### 自訂輸出路徑
|
|
415
|
+
|
|
416
|
+
使用 `markdownOutput.pathTemplate` 來設置任何文件佈局:
|
|
417
|
+
|
|
418
|
+
```json
|
|
419
|
+
{
|
|
420
|
+
"documentations": [
|
|
421
|
+
{
|
|
422
|
+
"markdownOutput": {
|
|
423
|
+
"pathTemplate": "{outputDir}/{locale}/{relativeToDocsRoot}"
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
}
|
|
428
|
+
```
|