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.ko.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자리 16진수**이며, 이는 소스 문자열을 잘라낸 후 생성되며 `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` - 마크다운을 `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. **주석 표시자** (`:::note`, `:::`) - 정확한 원본 텍스트로 복원됩니다.
|
|
239
|
+
2. **문서 앵커** (HTML `<a id="…">`, Docusaurus 제목 `{#…}`) - 원문 그대로 보존됩니다.
|
|
240
|
+
3. **마크다운 URL** (`](url)`, `src="../…"`) - 번역 후 맵에서 복원됩니다.
|
|
241
|
+
|
|
242
|
+
### 캐시(`TranslationCache`)
|
|
243
|
+
|
|
244
|
+
SQLite 데이터베이스(`node:sqlite`를 통해)는 `(source_hash, locale)`을 키로 하여 `translated_text`, `model`, `filepath`, `last_hit_at` 및 관련 필드와 함께 행을 저장합니다. 해시는 정규화된 콘텐츠(공백이 축소됨)의 SHA-256 해시값의 처음 16자리 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.ko.md#cache-behaviour-and-translate-docs-flags)를 참조하세요.
|
|
249
|
+
|
|
250
|
+
**배치 프롬프트 형식:** `translate-docs --prompt-format`은 `OpenRouterClient.translateDocumentBatch`에만 적용되는 XML(`<seg>` / `<t>`) 또는 JSON 배열/객체 형식을 선택합니다. 추출, 자리 표시자, 검증은 변경되지 않습니다. [배치 프롬프트 형식](GETTING_STARTED.ko.md#batch-prompt-format)을 참조하세요.
|
|
251
|
+
|
|
252
|
+
### 출력 경로 결정
|
|
253
|
+
|
|
254
|
+
`resolveDocumentationOutputPath(config, cwd, locale, relPath, kind)`은 소스 기준 경로를 출력 경로에 매핑합니다.
|
|
255
|
+
|
|
256
|
+
- `nested` 스타일(기본값): 마크다운의 경우 `{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}`를 사용하는 임의의 마크다운 레이아웃.
|
|
260
|
+
- **사용자 정의** `jsonPathTemplate`: JSON 레이블 파일을 위한 별도의 사용자 정의 레이아웃으로, 동일한 자리 표시자를 사용합니다.
|
|
261
|
+
- `linkRewriteDocsRoot`는 번역된 출력이 기본 프로젝트 루트 외부에 위치할 때 평면 링크 재작성기가 올바른 접두사를 계산할 수 있도록 도와줍니다.
|
|
262
|
+
|
|
263
|
+
### 평면 링크 재작성
|
|
264
|
+
|
|
265
|
+
`markdownOutput.style === "flat"`일 때 번역된 마크다운 파일은 로케일 접미사와 함께 소스와 동일한 위치에 배치됩니다. 페이지 간의 상대 링크는 `readme.de.md`의 `[Guide](../guide.md)`가 `guide.de.md`를 가리키도록 재작성됩니다. `rewriteRelativeLinks`에 의해 제어되며(사용자 정의 `pathTemplate` 없이 flat 스타일에서는 자동 활성화됨).
|
|
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`는 ANSI 색상 출력을 지원하는 `debug`, `info`, `warn`, `error` 레벨을 제공합니다. 상세 모드(`-v`)는 `debug` 레벨을 활성화합니다. `logFilePath`가 설정된 경우 로그 라인은 해당 파일에도 기록됩니다.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 런타임 헬퍼 API
|
|
299
|
+
|
|
300
|
+
이 API는 `'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
|
+
모든 공개 타입과 클래스는 패키지 루트에서 내보내집니다. 예: CLI 없이 Node.js에서 UI 번역 단계를 실행하는 경우:
|
|
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` | 마크다운에서 번역 가능한 세그먼트를 추출합니다. |
|
|
369
|
+
| `JsonExtractor` | Docusaurus JSON 레이블 파일에서 추출합니다. |
|
|
370
|
+
| `SvgExtractor` | SVG 파일에서 추출합니다. |
|
|
371
|
+
| `OpenRouterClient` | OpenRouter로 번역 요청을 보냅니다. |
|
|
372
|
+
| `PlaceholderHandler` | 번역 주변의 마크다운 구문을 보호하고 복원합니다. |
|
|
373
|
+
| `splitTranslatableIntoBatches` | 세그먼트를 LLM 크기의 배치로 그룹화합니다. |
|
|
374
|
+
| `validateTranslation` | 번역 후 구조적 검사를 수행합니다. |
|
|
375
|
+
| `resolveDocumentationOutputPath` | 번역된 문서의 출력 파일 경로를 결정합니다. |
|
|
376
|
+
| `Glossary` / `GlossaryMatcher` | 번역 용어집을 로드하고 적용합니다. |
|
|
377
|
+
| `runTranslateUI` | 프로그래밍 방식의 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
|
+
```
|