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,682 @@
|
|
|
1
|
+
# ai-i18n-tools: μμνκΈ°
|
|
2
|
+
|
|
3
|
+
`ai-i18n-tools`λ λ κ°μ§ λ
립μ μ΄λ©΄μλ μ‘°ν© κ°λ₯ν μν¬νλ‘μ°λ₯Ό μ 곡ν©λλ€:
|
|
4
|
+
|
|
5
|
+
- **Workflow 1 - UI Translation**: JS/TS μμ€μμ `t("β¦")` νΈμΆμ μΆμΆνκ³ OpenRouterλ₯Ό ν΅ν΄ λ²μν ν, i18nextμμ λ°λ‘ μ¬μ©ν μ μλ νλ©΄νλ μ§μλ³ JSON νμΌμ μμ±ν©λλ€.
|
|
6
|
+
- **Workflow 2 - Document Translation**: λ§ν¬λ€μ΄(MDX) λ° Docusaurus JSON λ μ΄λΈ νμΌμ μ¬λ¬ μ§μν μΈμ΄λ‘ λ²μνλ©°, μ€λ§νΈ μΊμ±μ μ§μν©λλ€. **SVG** μμ°μ `features.translateSVG`, μ΅μμ `svg` λΈλ‘ λ° `translate-svg`μ μ¬μ©ν©λλ€(μμΈν λ΄μ©μ [CLI μ°Έμ‘°](#cli-reference) μ°Έμ‘°).
|
|
7
|
+
|
|
8
|
+
λ μν¬νλ‘μ° λͺ¨λ OpenRouter(νΈνλλ λͺ¨λ LLM)λ₯Ό μ¬μ©νλ©° λ¨μΌ μ€μ νμΌμ 곡μ ν©λλ€.
|
|
9
|
+
|
|
10
|
+
<small>**λ€λ₯Έ μΈμ΄λ‘ μ½κΈ°:** </small>
|
|
11
|
+
|
|
12
|
+
<small id="lang-list">[en-GB](../../docs/GETTING_STARTED.md) Β· [de](./GETTING_STARTED.de.md) Β· [es](./GETTING_STARTED.es.md) Β· [fr](./GETTING_STARTED.fr.md) Β· [hi](./GETTING_STARTED.hi.md) Β· [ja](./GETTING_STARTED.ja.md) Β· [ko](./GETTING_STARTED.ko.md) Β· [pt-BR](./GETTING_STARTED.pt-BR.md) Β· [zh-CN](./GETTING_STARTED.zh-CN.md) Β· [zh-TW](./GETTING_STARTED.zh-TW.md)</small>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
17
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
18
|
+
**λͺ©μ°¨**
|
|
19
|
+
|
|
20
|
+
- [μ€μΉ](#installation)
|
|
21
|
+
- [λΉ λ₯Έ μμ](#quick-start)
|
|
22
|
+
- [μν¬νλ‘μ° 1 - UI λ²μ](#workflow-1---ui-translation)
|
|
23
|
+
- [1λ¨κ³: μ΄κΈ°ν](#step-1-initialise)
|
|
24
|
+
- [2λ¨κ³: λ¬Έμμ΄ μΆμΆ](#step-2-extract-strings)
|
|
25
|
+
- [3λ¨κ³: UI λ¬Έμμ΄ λ²μ](#step-3-translate-ui-strings)
|
|
26
|
+
- [XLIFF 2.0μΌλ‘ λ΄λ³΄λ΄κΈ° (μ ν μ¬ν)](#exporting-to-xliff-20-optional)
|
|
27
|
+
- [4λ¨κ³: λ°νμμ i18next μ°κ²°](#step-4-wire-i18next-at-runtime)
|
|
28
|
+
- [μμ€ μ½λμμ `t()` μ¬μ©νκΈ°](#using-t-in-source-code)
|
|
29
|
+
- [보κ°](#interpolation)
|
|
30
|
+
- [μΈμ΄ μ νκΈ° UI](#language-switcher-ui)
|
|
31
|
+
- [RTL μΈμ΄](#rtl-languages)
|
|
32
|
+
- [μν¬νλ‘μ° 2 - λ¬Έμ λ²μ](#workflow-2---document-translation)
|
|
33
|
+
- [1λ¨κ³: μ΄κΈ°ν](#step-1-initialise-1)
|
|
34
|
+
- [2λ¨κ³: λ¬Έμ λ²μ](#step-2-translate-documents)
|
|
35
|
+
- [μΊμ λμ λ° `translate-docs` νλκ·Έ](#cache-behaviour-and-translate-docs-flags)
|
|
36
|
+
- [μΆλ ₯ λ μ΄μμ](#output-layouts)
|
|
37
|
+
- [ν΅ν© μν¬νλ‘μ° (UI + λ¬Έμ)](#combined-workflow-ui--docs)
|
|
38
|
+
- [κ΅¬μ± μ°Έμ‘°](#configuration-reference)
|
|
39
|
+
- [`sourceLocale`](#sourcelocale)
|
|
40
|
+
- [`targetLocales`](#targetlocales)
|
|
41
|
+
- [`uiLanguagesPath` (μ ν μ¬ν)](#uilanguagespath-optional)
|
|
42
|
+
- [`concurrency` (μ ν μ¬ν)](#concurrency-optional)
|
|
43
|
+
- [`batchConcurrency` (μ ν μ¬ν)](#batchconcurrency-optional)
|
|
44
|
+
- [`batchSize` / `maxBatchChars` (μ ν μ¬ν)](#batchsize--maxbatchchars-optional)
|
|
45
|
+
- [`openrouter`](#openrouter)
|
|
46
|
+
- [`features`](#features)
|
|
47
|
+
- [`ui`](#ui)
|
|
48
|
+
- [`cacheDir`](#cachedir)
|
|
49
|
+
- [`documentations`](#documentations)
|
|
50
|
+
- [`svg` (μ ν μ¬ν)](#svg-optional)
|
|
51
|
+
- [`glossary`](#glossary)
|
|
52
|
+
- [CLI μ°Έμ‘°](#cli-reference)
|
|
53
|
+
- [νκ²½ λ³μ](#environment-variables)
|
|
54
|
+
|
|
55
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
56
|
+
|
|
57
|
+
## μ€μΉ
|
|
58
|
+
|
|
59
|
+
λ°°ν¬λ ν¨ν€μ§λ **ESM μ μ©**μ
λλ€. Node.js λλ λ²λ€λ¬μμλ `import`/`import()`λ₯Ό μ¬μ©νμΈμ. **`require('ai-i18n-tools')`λ μ¬μ©νμ§ λ§μΈμ.**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install ai-i18n-tools
|
|
63
|
+
# or
|
|
64
|
+
pnpm add ai-i18n-tools
|
|
65
|
+
# or
|
|
66
|
+
yarn add ai-i18n-tools
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
OpenRouter API ν€λ₯Ό μ€μ νμΈμ:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
export OPENROUTER_API_KEY=sk-or-v1-your-key-here
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
λλ νλ‘μ νΈ λ£¨νΈμ `.env` νμΌμ μμ±νμΈμ:
|
|
76
|
+
|
|
77
|
+
```env
|
|
78
|
+
OPENROUTER_API_KEY=sk-or-v1-your-key-here
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## λΉ λ₯Έ μμ
|
|
84
|
+
|
|
85
|
+
κΈ°λ³Έ `init` ν
νλ¦Ώ(`ui-markdown`)μ **UI** μΆμΆ λ° λ²μλ§μ νμ±νν©λλ€. `ui-docusaurus` ν
νλ¦Ώμ **λ¬Έμ** λ²μ(`translate-docs`)μ νμ±νν©λλ€. μ€μ μ λ°λΌ μΆμΆ, UI λ²μ, λ
립ν SVG λ²μ(μ ν μ¬ν), λ¬Έμ λ²μμ νλμ λͺ
λ Ήμ΄λ‘ μ€ννκ³ μ ν λ `sync`λ₯Ό μ¬μ©νμΈμ.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Workflow 1 - UI strings (default template enables extract + translate-ui)
|
|
89
|
+
npx ai-i18n-tools init
|
|
90
|
+
npx ai-i18n-tools extract
|
|
91
|
+
npx ai-i18n-tools translate-ui
|
|
92
|
+
|
|
93
|
+
# Workflow 2 - docs (Docusaurus-oriented template)
|
|
94
|
+
npx ai-i18n-tools init -t ui-docusaurus
|
|
95
|
+
npx ai-i18n-tools translate-docs
|
|
96
|
+
|
|
97
|
+
# Combined: extract UI strings, then translate UI + SVG + docs (per config features)
|
|
98
|
+
npx ai-i18n-tools sync
|
|
99
|
+
|
|
100
|
+
# Markdown translation status (per file Γ locale)
|
|
101
|
+
npx ai-i18n-tools status
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## μν¬νλ‘μ° 1 - UI λ²μ
|
|
107
|
+
|
|
108
|
+
i18nextλ₯Ό μ¬μ©νλ λͺ¨λ JS/TS νλ‘μ νΈλ₯Ό μν κ²μ
λλ€: React μ±, Next.js(ν΄λΌμ΄μΈνΈ λ° μλ² μ»΄ν¬λνΈ), Node.js μλΉμ€, CLI λꡬ λ±.
|
|
109
|
+
|
|
110
|
+
### 1λ¨κ³: μ΄κΈ°ν
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx ai-i18n-tools init
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
μ΄ λͺ
λ Ήμ `ui-markdown` ν
νλ¦ΏμΌλ‘ `ai-i18n-tools.config.json` νμΌμ μμ±ν©λλ€. λ€μμ μ€μ νκΈ° μν΄ μ΄ νμΌμ νΈμ§νμΈμ:
|
|
117
|
+
|
|
118
|
+
- `sourceLocale` - μλ³Έ μΈμ΄μ BCP-47 μ½λ (μ: `"en-GB"`). **λ°λμ** λ°νμ i18n μ€μ νμΌ(`src/i18n.ts` / `src/i18n.js`)μμ λ΄λ³΄λΈ `SOURCE_LOCALE`μ μΌμΉν΄μΌ ν©λλ€.
|
|
119
|
+
- `targetLocales` - `ui-languages.json` λ§€λνμ€νΈ νμΌμ κ²½λ‘ λλ BCP-47 μ½λ λ°°μ΄.
|
|
120
|
+
- `ui.sourceRoots` - `t("β¦")` νΈμΆμ κ²μν λλ ν°λ¦¬ (μ: `["src/"]`).
|
|
121
|
+
- `ui.stringsJson` - λ§μ€ν° μΉ΄νλ‘κ·Έλ₯Ό μ μ₯ν μμΉ (μ: `"src/locales/strings.json"`).
|
|
122
|
+
- `ui.flatOutputDir` - `de.json`, `pt-BR.json` λ±μ΄ μ μ₯λ μμΉ (μ: `"src/locales/"`).
|
|
123
|
+
- `ui.preferredModel` (μ ν μ¬ν) - `translate-ui` λͺ
λ Ήμ΄μμ **μ΅μ΄λ‘** μλν OpenRouter λͺ¨λΈ ID. μ€ν¨ μ CLIλ `openrouter.translationModels` (λλ μ΄μ λ°©μμΈ `defaultModel` / `fallbackModel`)μ μ μλ μμλλ‘ μλνλ©°, μ€λ³΅μ 건λλλλ€.
|
|
124
|
+
|
|
125
|
+
### 2λ¨κ³: λ¬Έμμ΄ μΆμΆ
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx ai-i18n-tools extract
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`ui.sourceRoots` μλμ λͺ¨λ JS/TS νμΌμμ `t("literal")` λ° `i18n.t("literal")` νΈμΆμ μ€μΊνκ³ , `ui.stringsJson`μ κΈ°λ‘νκ±°λ λ³ν©ν©λλ€.
|
|
132
|
+
|
|
133
|
+
μ€μΊλλ μ€μ κ°λ₯νλ©°, `ui.reactExtractor.funcNames`λ₯Ό ν΅ν΄ μ¬μ©μ μ μ ν¨μ μ΄λ¦μ μΆκ°ν μ μμ΅λλ€.
|
|
134
|
+
|
|
135
|
+
### 3λ¨κ³: UI λ¬Έμμ΄ λ²μ
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx ai-i18n-tools translate-ui
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`strings.json`μ μ½μ ν κ° λμ λ‘μΌμΌμ λν΄ OpenRouterλ‘ λ°°μΉ μ μ‘νκ³ , `ui.flatOutputDir`μ `de.json`, `fr.json` λ±μ νλ©΄ JSON νμΌμ μμ±ν©λλ€. `ui.preferredModel`μ΄ μ€μ λ κ²½μ°, ν΄λΉ λͺ¨λΈμ `openrouter.translationModels`μ μ μλ μμλλ‘ μλνκΈ° μ μ λ¨Όμ μλν©λλ€ (λ¬Έμ λ²μ λ° κΈ°ν λͺ
λ Ήμ΄λ μ¬μ ν `openrouter`λ§ μ¬μ©ν©λλ€).
|
|
142
|
+
|
|
143
|
+
κ° νλͺ©μ λν΄ `translate-ui`λ κ° λ‘μΌμΌμ μ±κ³΅μ μΌλ‘ λ²μν **OpenRouter λͺ¨λΈ ID**λ₯Ό μ νμ `models` κ°μ²΄μ μ μ₯ν©λλ€ (`translated`μ λμΌν λ‘μΌμΌ ν€ μ¬μ©). λ‘컬 `editor` λͺ
λ Ήμ΄λ‘ νΈμ§λ λ¬Έμμ΄μ ν΄λΉ λ‘μΌμΌμ `models`μ `user-edited`λΌλ μκ·Έλ κ°μΌλ‘ νμλ©λλ€. `ui.flatOutputDir` μλμ λ‘μΌμΌλ³ νλ©΄ νμΌμ **μλ³Έ λ¬Έμμ΄ β λ²μλ¬Έ**λ§ ν¬ν¨λλ©°, `models`λ ν¬ν¨λμ§ μμ΅λλ€ (λ°λΌμ λ°νμ λ²λ€μ λ³κ²½λμ§ μμ΅λλ€).
|
|
144
|
+
|
|
145
|
+
> **μΊμ μλν° μ¬μ© μ μ°Έκ³ μ¬ν:** μΊμ μλν°μμ νλͺ©μ νΈμ§ν κ²½μ°, μ
λ°μ΄νΈλ μΊμ νλͺ©μΌλ‘ μΆλ ₯ νμΌμ λ€μ μμ±νκΈ° μν΄ `sync --force-update` (λλ `--force-update` μ΅μ
μ μ¬μ©ν λλ±ν `translate` λͺ
λ Ήμ΄)λ₯Ό μ€νν΄μΌ ν©λλ€. λν, μ΄ν μλ³Έ ν
μ€νΈκ° λ³κ²½λλ©΄ μλ‘μ΄ μΊμ ν€(ν΄μ)κ° μμ±λλ―λ‘ μλ νΈμ§ λ΄μ©μ΄ μ¬λΌμ§λ€λ μ μ μ μνμΈμ.
|
|
146
|
+
|
|
147
|
+
### XLIFF 2.0μΌλ‘ λ΄λ³΄λ΄κΈ° (μ ν μ¬ν)
|
|
148
|
+
|
|
149
|
+
UI λ¬Έμμ΄μ λ²μ μ
체, TMS λλ CAT λꡬμ μ λ¬νλ €λ©΄ μΉ΄νλ‘κ·Έλ₯Ό **XLIFF 2.0** νμμΌλ‘ λ΄λ³΄λ΄μΈμ(λμ λ‘μΌμΌλΉ νλμ νμΌ). μ΄ λͺ
λ Ήμ **μ½κΈ° μ μ©** μ
λλ€. `strings.json`μ μμ νκ±°λ APIλ₯Ό νΈμΆνμ§ μμ΅λλ€.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npx ai-i18n-tools export-ui-xliff
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
κΈ°λ³Έμ μΌλ‘ νμΌμ `ui.stringsJson` μμ `strings.de.xliff`, `strings.pt-BR.xliff` νμ(μΉ΄νλ‘κ·Έμ κΈ°λ³Έ μ΄λ¦ + λ‘μΌμΌ + `.xliff`)μΌλ‘ μμ±λ©λλ€. λ€λ₯Έ μμΉμ μ°λ €λ©΄ `-o` / `--output-dir`λ₯Ό μ¬μ©νμΈμ. `strings.json`μ κΈ°μ‘΄ λ²μμ `<target>`μ λνλ©λλ€. λλ½λ λ‘μΌμΌμ `state="initial"`μΌλ‘ νμλλ©° `<target>`λ μμΌλ―λ‘ λꡬμμ μ΄λ₯Ό μ±μΈ μ μμ΅λλ€. `--untranslated-only`μ μ¬μ©νλ©΄ κ° λ‘μΌμΌμ λν΄ μμ§ λ²μμ΄ νμν νλͺ©λ§ λ΄λ³΄λΌ μ μμ΅λλ€(μ
체 λ°°μΉμ μ μ©ν¨). `--dry-run`μ νμΌμ μ°μ§ μκ³ κ²½λ‘λ§ μΆλ ₯ν©λλ€.
|
|
156
|
+
|
|
157
|
+
### 4λ¨κ³: λ°νμμμ i18next μ°κ²°
|
|
158
|
+
|
|
159
|
+
`'ai-i18n-tools/runtime'`μμ λ΄λ³΄λΈ ν¬νΌλ₯Ό μ¬μ©νμ¬ i18n μ€μ νμΌμ λ§λμΈμ:
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
// src/i18n.js (or src/i18n.ts)
|
|
163
|
+
import i18n from 'i18next';
|
|
164
|
+
import { initReactI18next } from 'react-i18next';
|
|
165
|
+
import uiLanguages from './locales/ui-languages.json';
|
|
166
|
+
import {
|
|
167
|
+
defaultI18nInitOptions,
|
|
168
|
+
wrapI18nWithKeyTrim,
|
|
169
|
+
makeLoadLocale,
|
|
170
|
+
applyDirection,
|
|
171
|
+
} from 'ai-i18n-tools/runtime';
|
|
172
|
+
|
|
173
|
+
// Must match sourceLocale in ai-i18n-tools.config.json
|
|
174
|
+
export const SOURCE_LOCALE = 'en-GB';
|
|
175
|
+
|
|
176
|
+
void i18n.use(initReactI18next).init(defaultI18nInitOptions(SOURCE_LOCALE));
|
|
177
|
+
wrapI18nWithKeyTrim(i18n);
|
|
178
|
+
i18n.on('languageChanged', applyDirection);
|
|
179
|
+
applyDirection(i18n.language);
|
|
180
|
+
|
|
181
|
+
const localeLoaders = Object.fromEntries(
|
|
182
|
+
uiLanguages
|
|
183
|
+
.filter(({ code }) => code !== SOURCE_LOCALE)
|
|
184
|
+
.map(({ code }) => [code, () => import(`./locales/${code}.json`)])
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
export const loadLocale = makeLoadLocale(i18n, localeLoaders, SOURCE_LOCALE);
|
|
188
|
+
export default i18n;
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
React λ λλ§ μ μ (μ: μ§μ
μ (entry point) μλ¨μμ) `i18n.js`λ₯Ό κ°μ Έμ€μΈμ. μ¬μ©μκ° μΈμ΄λ₯Ό λ³κ²½νλ©΄ `await loadLocale(code)`λ₯Ό νΈμΆν ν `i18n.changeLanguage(code)`λ₯Ό μ€ννμΈμ.
|
|
192
|
+
|
|
193
|
+
`SOURCE_LOCALE`λ λ΄λ³΄λ΄μ§λ―λ‘ λ€λ₯Έ νμΌ(μ: μΈμ΄ μ νκΈ°)μμλ `'./i18n'`μμ μ§μ κ°μ Έμ μ¬μ©ν μ μμ΅λλ€.
|
|
194
|
+
|
|
195
|
+
`defaultI18nInitOptions(sourceLocale)`μ ν€λ₯Ό κΈ°λ³Έκ°μΌλ‘ μ¬μ©νλ μ€μ μ μν νμ€ μ΅μ
μ λ°νν©λλ€:
|
|
196
|
+
|
|
197
|
+
- `parseMissingKeyHandler`λ ν€ μ체λ₯Ό λ°ννλ―λ‘, λ²μλμ§ μμ λ¬Έμμ΄μ μλ³Έ ν
μ€νΈλ₯Ό νμν©λλ€.
|
|
198
|
+
- `nsSeparator: false`λ μ½λ‘ μ ν¬ν¨ν ν€ μ¬μ©μ νμ©ν©λλ€.
|
|
199
|
+
- `interpolation.escapeValue: false` - Reactκ° μ체μ μΌλ‘ κ°μ μ΄μ€μΌμ΄ννλ―λ‘ μμ νκ² λΉνμ±νν μ μμΌλ©°, Node.js/CLI μΆλ ₯μλ μ΄μ€μΌμ΄νν HTMLμ΄ μμ΅λλ€.
|
|
200
|
+
|
|
201
|
+
`wrapI18nWithKeyTrim(i18n)`μ `i18n.t`λ₯Ό λννμ¬ (1) ν€κ° μ‘°ν μ μ μλμΌλ‘ 곡백μ μ κ±°νμ¬ μΆμΆ μ€ν¬λ¦½νΈκ° μ μ₯νλ λ°©μκ³Ό μΌμΉνκ³ , (2) μλ³Έ λ‘μΌμΌμ΄ μμ ν€λ₯Ό λ°νν λ <code>{"{{var}}"}</code> 보κ°μ΄ μ μ©λλλ‘ ν©λλ€. λ°λΌμ <code>{"t('Hello {{name}}', { name })"}</code>μ΄ μλ³Έ μΈμ΄μμλ μ μμ μΌλ‘ μλν©λλ€.
|
|
202
|
+
|
|
203
|
+
`makeLoadLocale(i18n, loaders, sourceLocale)`μ λ‘μΌμΌμ λν JSON λ²λ€μ λμ μΌλ‘ κ°μ Έμ i18nextμ λ±λ‘νλ λΉλκΈ° `loadLocale(lang)` ν¨μλ₯Ό λ°νν©λλ€.
|
|
204
|
+
|
|
205
|
+
### μμ€ μ½λμμ `t()` μ¬μ©νκΈ°
|
|
206
|
+
|
|
207
|
+
μΆμΆ μ€ν¬λ¦½νΈκ° μ°Ύμ μ μλλ‘ **리ν°λ΄ λ¬Έμμ΄**λ‘ `t()`λ₯Ό νΈμΆνμΈμ:
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
import { useTranslation } from 'react-i18next';
|
|
211
|
+
|
|
212
|
+
function MyComponent() {
|
|
213
|
+
const { t } = useTranslation();
|
|
214
|
+
return <button>{t('Save')}</button>;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
λμΌν ν¨ν΄μ React μΈλΆ(Node.js, μλ² μ»΄ν¬λνΈ, CLI)μμλ μλν©λλ€:
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
import i18n from './i18n.js';
|
|
222
|
+
console.log(i18n.t('Processing complete'));
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**κ·μΉ:**
|
|
226
|
+
|
|
227
|
+
- λ€μ νμλ§ μΆμΆλ©λλ€: `t("β¦")`, `t('β¦')`, `t(`β¦`)`, `i18n.t("β¦")`.
|
|
228
|
+
- ν€λ **리ν°λ΄ λ¬Έμμ΄**μ΄μ΄μΌ νλ©°, λ³μλ ννμμ ν€λ‘ μ¬μ©ν μ μμ΅λλ€.
|
|
229
|
+
- ν
νλ¦Ώ 리ν°λ΄μ ν€λ‘ μ¬μ©νμ§ λ§μμμ€: <code>{'t(`Hello ${name}`)'}</code>μ μΆμΆν μ μμ΅λλ€.
|
|
230
|
+
|
|
231
|
+
### 보κ°
|
|
232
|
+
|
|
233
|
+
<code>{"{{var}}"}</code> μ리 νμμμλ i18nextμ κΈ°λ³Έ λ λ²μ§Έ μΈμ 보κ°μ μ¬μ©ν©λλ€:
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
// i18next handles substitution natively, even in key-as-default mode
|
|
237
|
+
t('Hello {{name}}, you have {{count}} messages', { name, count })
|
|
238
|
+
// β "Hello Alice, you have 3 messages"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
μΆμΆ μ€ν¬λ¦½νΈλ λ λ²μ§Έ μΈμλ₯Ό 무μνλ©°, 리ν°λ΄ ν€ λ¬Έμμ΄μΈ <code>{"\"Hello {{name}}, you have {{count}} messages\""}</code>λ§ μΆμΆλμ΄ λ²μμ μν΄ μ μ‘λ©λλ€. λ²μμμκ²λ <code>{"{{...}}"}</code> ν ν°μ κ·Έλλ‘ μ μ§νλλ‘ μ§μν©λλ€.
|
|
242
|
+
|
|
243
|
+
### μΈμ΄ μ νκΈ° UI
|
|
244
|
+
|
|
245
|
+
`ui-languages.json` λ§€λνμ€νΈλ₯Ό μ¬μ©νμ¬ μΈμ΄ μ νκΈ°λ₯Ό ꡬμ±ν©λλ€. `ai-i18n-tools`λ λ κ°μ§ νμ ν¬νΌλ₯Ό λ΄λ³΄λ
λλ€:
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { useMemo } from 'react';
|
|
249
|
+
import { useTranslation } from 'react-i18next';
|
|
250
|
+
import {
|
|
251
|
+
getUILanguageLabel,
|
|
252
|
+
getUILanguageLabelNative,
|
|
253
|
+
type UiLanguageEntry,
|
|
254
|
+
} from 'ai-i18n-tools/runtime';
|
|
255
|
+
import uiLanguages from './locales/ui-languages.json';
|
|
256
|
+
import { loadLocale } from './i18n';
|
|
257
|
+
|
|
258
|
+
function LanguageSelect({
|
|
259
|
+
value,
|
|
260
|
+
onChange,
|
|
261
|
+
}: {
|
|
262
|
+
value: string;
|
|
263
|
+
onChange: (code: string) => void;
|
|
264
|
+
}) {
|
|
265
|
+
const { t, i18n } = useTranslation();
|
|
266
|
+
|
|
267
|
+
const options = useMemo(
|
|
268
|
+
() =>
|
|
269
|
+
(uiLanguages as UiLanguageEntry[]).map((lang) => ({
|
|
270
|
+
code: lang.code,
|
|
271
|
+
// Settings/content dropdowns: shows translated name when available
|
|
272
|
+
label: getUILanguageLabel(lang, t),
|
|
273
|
+
// Header globe menu: shows "English / Deutsch"-style label, no t() call
|
|
274
|
+
nativeLabel: getUILanguageLabelNative(lang),
|
|
275
|
+
})),
|
|
276
|
+
[t]
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const handleChange = async (code: string) => {
|
|
280
|
+
await loadLocale(code);
|
|
281
|
+
i18n.changeLanguage(code);
|
|
282
|
+
onChange(code);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return (
|
|
286
|
+
<select value={value} onChange={(e) => handleChange(e.target.value)}>
|
|
287
|
+
{options.map((row) => (
|
|
288
|
+
<option key={row.code} value={row.code}>
|
|
289
|
+
{row.label}
|
|
290
|
+
</option>
|
|
291
|
+
))}
|
|
292
|
+
</select>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`getUILanguageLabel(lang, t)` - λ²μλ κ²½μ° `t(englishName)`μ νμνκ³ , λ€λ₯Ό κ²½μ° `englishName / t(englishName)`μ νμν©λλ€. μ€μ νλ©΄μ μ ν©ν©λλ€.
|
|
298
|
+
|
|
299
|
+
`getUILanguageLabelNative(lang)` - `englishName / label`μ νμν©λλ€(`t()` νΈμΆ μμ΄ κ° νμ νμ). ν€λ λ©λ΄μ²λΌ νμ§ μΈμ΄ μ΄λ¦μ 보μ¬μ£Όκ³ μ ν λ μ ν©ν©λλ€.
|
|
300
|
+
|
|
301
|
+
`ui-languages.json` λ§€λνμ€νΈλ <code>{"{ code, label, englishName }"}</code> νλͺ©λ€μ JSON λ°°μ΄μ
λλ€. μμ:
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
[
|
|
305
|
+
{ "code": "en-GB", "label": "English (UK)", "englishName": "English (UK)" },
|
|
306
|
+
{ "code": "pt-BR", "label": "PortuguΓͺs (BR)", "englishName": "Portuguese (BR)" },
|
|
307
|
+
{ "code": "de", "label": "Deutsch", "englishName": "German" },
|
|
308
|
+
{ "code": "fr", "label": "FranΓ§ais", "englishName": "French" },
|
|
309
|
+
{ "code": "ar", "label": "Ψ§ΩΨΉΨ±Ψ¨ΩΨ©", "englishName": "Arabic" }
|
|
310
|
+
]
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
`targetLocales`λ₯Ό μ΄ νμΌμ κ²½λ‘λ‘ μ€μ νμ¬ λ²μ λͺ
λ Ήμ΄κ° λμΌν λͺ©λ‘μ μ¬μ©νλλ‘ ν©λλ€.
|
|
314
|
+
|
|
315
|
+
### RTL μΈμ΄
|
|
316
|
+
|
|
317
|
+
`ai-i18n-tools`λ `getTextDirection(lng)` λ° `applyDirection(lng)`μ λ΄λ³΄λ
λλ€:
|
|
318
|
+
|
|
319
|
+
```js
|
|
320
|
+
import { getTextDirection, applyDirection } from 'ai-i18n-tools/runtime';
|
|
321
|
+
|
|
322
|
+
getTextDirection('ar') // 'rtl'
|
|
323
|
+
getTextDirection('en-GB') // 'ltr'
|
|
324
|
+
|
|
325
|
+
// Applied automatically via i18n.on('languageChanged', applyDirection) - see Step 4
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`applyDirection`μ λΈλΌμ°μ μμ `document.documentElement.dir`μ μ€μ νκ³ , Node.jsμμλ μ무 μμ
λ νμ§ μμ΅λλ€. νΉμ μμλ₯Ό λμμΌλ‘ νλ €λ©΄ μ νμ μΌλ‘ `element` μΈμλ₯Ό μ λ¬ν μ μμ΅λλ€.
|
|
329
|
+
|
|
330
|
+
`β` νμ΄νλ₯Ό ν¬ν¨ν μ μλ λ¬Έμμ΄μ κ²½μ° RTL λ μ΄μμμμλ μ΄λ₯Ό λ°λλ‘ λ€μ§μ΅λλ€:
|
|
331
|
+
|
|
332
|
+
```js
|
|
333
|
+
import { flipUiArrowsForRtl } from 'ai-i18n-tools/runtime';
|
|
334
|
+
const { i18n } = useTranslation();
|
|
335
|
+
const isRtl = getTextDirection(i18n.language) === 'rtl';
|
|
336
|
+
const label = flipUiArrowsForRtl(t('Next β Step'), isRtl);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## μν¬νλ‘ 2 - λ¬Έμ λ²μ
|
|
342
|
+
|
|
343
|
+
λ§ν¬λ€μ΄ λ¬Έμ, Docusaurus μ¬μ΄νΈ λ° JSON λ μ΄λΈ νμΌμ μν μ€κ³μ
λλ€. λ
립ν SVG μμ°μ `features.translateSVG`μ΄ νμ±νλκ³ μ΅μμ `svg` λΈλ‘μ΄ μ€μ λ κ²½μ° [`translate-svg`](#cli-reference)μ ν΅ν΄ λ²μλλ©°, `documentations[].contentPaths`μ ν΅ν΄ λ²μλμ§ μμ΅λλ€.
|
|
344
|
+
|
|
345
|
+
### 1λ¨κ³: μ΄κΈ°ν
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
npx ai-i18n-tools init -t ui-docusaurus
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
μμ±λ `ai-i18n-tools.config.json`μ νΈμ§ν©λλ€:
|
|
352
|
+
|
|
353
|
+
- `sourceLocale` - μλ³Έ μΈμ΄ ( `docusaurus.config.js` μ `defaultLocale` κ³Ό μΌμΉν΄μΌ ν¨).
|
|
354
|
+
- `targetLocales` - λ‘μΌμΌ μ½λ λ°°μ΄ λλ λ§€λνμ€νΈ κ²½λ‘.
|
|
355
|
+
- `cacheDir` - λͺ¨λ λ¬Έμ νμ΄νλΌμΈμ 곡μ λλ SQLite μΊμ λλ ν°λ¦¬ (`--write-logs` μ κΈ°λ³Έ λ‘κ·Έ λλ ν°λ¦¬).
|
|
356
|
+
- `documentations` - λ¬Έμ λΈλ‘λ€μ λ°°μ΄. κ° λΈλ‘μ μ νμ `description`, `contentPaths`, `outputDir`, μ νμ `jsonSource`, `markdownOutput`, `targetLocales`, `addFrontmatter` λ±μ΄ ν¬ν¨λ μ μμ.
|
|
357
|
+
- `documentations[].description` - μ μ§ κ΄λ¦¬μλ₯Ό μν μ νμ κ°λ¨ν λ©λͺ¨ (ν΄λΉ λΈλ‘μ λ²μ). μ€μ λ κ²½μ° `translate-docs` ν€λλΌμΈ(`π β¦: translating β¦`) λ° `status` μΉμ
ν€λμ νμλ¨.
|
|
358
|
+
- `documentations[].contentPaths` - λ§ν¬λ€μ΄/MDX μλ³Έ λλ ν°λ¦¬ λλ νμΌ (JSON λ μ΄λΈμ κ²½μ° `documentations[].jsonSource` μ°Έμ‘°).
|
|
359
|
+
- `documentations[].outputDir` - ν΄λΉ λΈλ‘μ λ²μλ μΆλ ₯ 루νΈ.
|
|
360
|
+
- `documentations[].markdownOutput.style` - `"nested"` (κΈ°λ³Έκ°), `"docusaurus"`, λλ `"flat"` ( [μΆλ ₯ λ μ΄μμ](#output-layouts) μ°Έμ‘°).
|
|
361
|
+
|
|
362
|
+
### 2λ¨κ³: λ¬Έμ λ²μ
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
npx ai-i18n-tools translate-docs
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
μ΄κ²μ λͺ¨λ `documentations` λΈλ‘μ `contentPaths`μ μλ λͺ¨λ νμΌμ λͺ¨λ μ ν¨ν λ¬Έμ λ‘μΌμΌλ‘ λ²μν©λλ€(μ€μ λ κ²½μ° κ° λΈλ‘μ `targetLocales`μ ν©μ§ν©, κ·Έλ μ§ μμΌλ©΄ λ£¨νΈ `targetLocales`). μ΄λ―Έ λ²μλ μΈκ·Έλ¨ΌνΈλ SQLite μΊμμμ μ 곡λλ©° - μλ‘ μΆκ°λκ±°λ λ³κ²½λ μΈκ·Έλ¨ΌνΈλ§ LLMμΌλ‘ μ μ‘λ©λλ€.
|
|
369
|
+
|
|
370
|
+
λ¨μΌ λ‘μΌμΌμ λ²μνλ €λ©΄:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
npx ai-i18n-tools translate-docs --locale de
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
무μμ λ²μν΄μΌ νλμ§ νμΈνλ €λ©΄:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
npx ai-i18n-tools status
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### μΊμ λμ λ° `translate-docs` νλκ·Έ
|
|
383
|
+
|
|
384
|
+
CLIλ SQLiteμ **νμΌ μΆμ **(νμΌλΉ μμ€ ν΄μ Γ λ‘μΌμΌ)κ³Ό **μΈκ·Έλ¨ΌνΈ** ν(λ²μ κ°λ₯ν κ° μ²ν¬λΉ ν΄μ Γ λ‘μΌμΌ)μ μ μ§ν©λλ€. μΌλ° μ€νμμλ μΆμ λ ν΄μκ° νμ¬ μμ€ **μ** μΆλ ₯ νμΌμ΄ μ΄λ―Έ μ‘΄μ¬ν λ νμΌ μ 체λ₯Ό 건λλλλ€. κ·Έλ μ§ μμΌλ©΄ νμΌμ μ²λ¦¬νκ³ μΈκ·Έλ¨ΌνΈ μΊμλ₯Ό μ¬μ©νλ―λ‘ λ³κ²½λμ§ μμ ν
μ€νΈλ APIλ₯Ό νΈμΆνμ§ μμ΅λλ€.
|
|
385
|
+
|
|
386
|
+
| κΉλ° | ν¨κ³Ό |
|
|
387
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
388
|
+
| *(κΈ°λ³Έκ°)* | μΆμ μ λ³κ²½λμ§ μμ νμΌ κ±΄λλ°κΈ° + λμ€ν¬ μΆλ ₯ μΌμΉ; λλ¨Έμ§μ λν΄ μΈκ·Έλ¨ΌνΈ μΊμ μ¬μ©. |
|
|
389
|
+
| `--force-update` | νμΌ μΆμ μ΄ κ±΄λλ°λλΌλ λͺ¨λ μΌμΉ νμΌ μ¬μ²λ¦¬(μΆμΆ, μ¬μ‘°λ¦½, μΆλ ₯ μμ±). **μΈκ·Έλ¨ΌνΈ μΊμλ μ¬μ ν μ μ©λ¨** - λ³κ²½λμ§ μμ μΈκ·Έλ¨ΌνΈλ LLMμ μ μ‘λμ§ μμ΅λλ€. |
|
|
390
|
+
| `--force` | μ²λ¦¬λ κ° νμΌμ λν νμΌ μΆμ μ μ§μ°κ³ **μΈκ·Έλ¨ΌνΈ μΊμλ₯Ό μ½μ§ μμ** (μ 체 μ¬λ²μ). μ κ²°κ³Όλ μ¬μ ν **μΈκ·Έλ¨ΌνΈ μΊμμ κΈ°λ‘λ©λλ€**. |
|
|
391
|
+
| `--stats` | μΈκ·Έλ¨ΌνΈ μ, μΆμ λ νμΌ μ, λ‘μΌμΌλ³ μΈκ·Έλ¨ΌνΈ μ΄κ³λ₯Ό μΆλ ₯ν ν μ’
λ£ν©λλ€. |
|
|
392
|
+
| `--clear-cache [locale]` | μΊμλ λ²μ(λ° νμΌ μΆμ )μ μμ : λͺ¨λ λ‘μΌμΌ λλ λ¨μΌ λ‘μΌμΌ, κ·Έλ¦¬κ³ μ’
λ£ν©λλ€. |
|
|
393
|
+
| `--prompt-format <mode>` | μΈκ·Έλ¨ΌνΈ **λ°°μΉ**λ₯Ό λͺ¨λΈμ μ μ‘νκ³ κ΅¬λ¬Έ λΆμνλ λ°©μ(`xml`, `json-array` λλ `json-object`). κΈ°λ³Έκ° **`xml`**. μΆμΆ, μ리νμμ, μ ν¨μ± κ²μ¬, μΊμ λλ λ체 λμμ λ³κ²½λμ§ μμ - [λ°°μΉ ν둬ννΈ νμ](#batch-prompt-format) μ°Έμ‘°. |
|
|
394
|
+
|
|
395
|
+
`--force`λ `--force-update`μ ν¨κ» μ¬μ©ν μ μμ΅λλ€(μλ‘ λ°°νμ μ
λλ€).
|
|
396
|
+
|
|
397
|
+
#### λ°°μΉ ν둬ννΈ νμ
|
|
398
|
+
|
|
399
|
+
`translate-docs`λ λ²μ κ°λ₯ν μΈκ·Έλ¨ΌνΈλ₯Ό **λ°°μΉ**(`batchSize` / `maxBatchChars`λ‘ κ·Έλ£Ήν)λ‘ OpenRouterμ 보λ
λλ€. **`--prompt-format`** νλκ·Έλ ν΄λΉ λ°°μΉμ **μμ΄μ΄ νμ**λ§ λ³κ²½ν©λλ€. μΈκ·Έλ¨ΌνΈ λΆν , `PlaceholderHandler` ν ν°, λ§ν¬λ€μ΄ AST κ²μ¬, SQLite μΊμ ν€, λ°°μΉ κ΅¬λ¬Έ λΆμ μ€ν¨ μ μΈκ·Έλ¨ΌνΈλ³ λ체λ λ³κ²½λμ§ μμ΅λλ€.
|
|
400
|
+
|
|
401
|
+
| λͺ¨λ | μ¬μ©μ λ©μμ§ | λͺ¨λΈ νμ |
|
|
402
|
+
| ---- | ------------ | ----------- |
|
|
403
|
+
| **`xml`** (κΈ°λ³Έκ°) | μμ¬ XML: μΈκ·Έλ¨ΌνΈλΉ νλμ `<seg id="N">β¦</seg>`(XML μ΄μ€μΌμ΄ν ν¬ν¨). | `<t id="N">β¦</t>` λΈλ‘λ§, μΈκ·Έλ¨ΌνΈ μΈλ±μ€λΉ νλ. |
|
|
404
|
+
| **`json-array`** | λ¬Έμμ΄ λ°°μ΄ JSON, μμλλ‘ μΈκ·Έλ¨ΌνΈλΉ νλμ νλͺ©. | λμΌν **κΈΈμ΄**μ(λμΌν μμ) JSON λ°°μ΄. |
|
|
405
|
+
| **`json-object`** | JSON κ°μ²΄ `{"0":"β¦","1":"β¦",β¦}`, μΈκ·Έλ¨ΌνΈ μΈλ±μ€λ‘ ν€ μ§μ . | λμΌν **ν€**μ λ²μλ κ°μ κ°μ§ JSON κ°μ²΄. |
|
|
406
|
+
|
|
407
|
+
μ€ν ν€λμλ `Batch prompt format: β¦`κ° μΈμλλ―λ‘ νμ± λͺ¨λλ₯Ό νμΈν μ μμ΅λλ€. JSON λ μ΄λΈ νμΌ(`jsonSource`) λ° λ
립ν SVG λ°°μΉλ `translate-docs`(λλ `sync`μ λ¬Έμ λ¨κ³ - `sync`μμλ μ΄ νλκ·Έλ₯Ό λ
ΈμΆνμ§ μμ; κΈ°λ³Έκ°μ **`xml`**)μ μΌλΆλ‘ μ€νλ λ λμΌν μ€μ μ μ¬μ©ν©λλ€.
|
|
408
|
+
|
|
409
|
+
**μΈκ·Έλ¨ΌνΈ μ€λ³΅ μ κ±° λ° SQLiteμ κ²½λ‘**
|
|
410
|
+
|
|
411
|
+
- μΈκ·Έλ¨ΌνΈ νμ μ μμ μΌλ‘ `(source_hash, locale)`λ‘ ν€κ° μ§μ λ©λλ€(hash = μ κ·νλ μ½ν
μΈ ). λ νμΌμ λμΌν ν
μ€νΈκ° μμΌλ©΄ νλμ νμ 곡μ νλ©°, `translations.filepath`λ λ©νλ°μ΄ν°(λ§μ§λ§ μμ±μ)μΌ λΏ νμΌλ³ λ λ²μ§Έ μΊμ νλͺ©μ΄ μλλλ€.
|
|
412
|
+
- `file_tracking.filepath`λ λ€μμ€νμ΄μ€κ° μλ ν€λ₯Ό μ¬μ©ν©λλ€: κ° `documentations` λΈλ‘λ§λ€ `doc-block:{index}:{relPath}` (`relPath`λ νλ‘μ νΈ λ£¨νΈ κΈ°μ€ posix: μμ§λ λ§ν¬λ€μ΄ κ²½λ‘) λ° `translate-svg` μλμ λ
립ν SVG μμ°μλ `svg-assets:{relPath}`λ₯Ό μ¬μ©ν©λλ€. **JSON λ μ΄λΈ νμΌμ μμ€ νμΌμ λν cwd κΈ°μ€ κ²½λ‘λ₯Ό μ¬μ©ν©λλ€**. μ: `docs-site/i18n/en/code.json`μ΄λ―λ‘ μ 리(cleanup)μμ μ€μ νμΌμ νμΈν μ μμ΅λλ€.
|
|
413
|
+
- `translations.filepath`λ λ§ν¬λ€μ΄, JSON λ° SVG μΈκ·Έλ¨ΌνΈμ λν΄ cwd κΈ°μ€ posix κ²½λ‘λ₯Ό μ μ₯ν©λλ€(SVGλ λ€λ₯Έ μμ°κ³Ό λμΌν κ²½λ‘ νμμ μ¬μ©νλ©°, `svg-assets:β¦` μ λμ¬λ **`file_tracking`μμλ§** μ¬μ©λ©λλ€).
|
|
414
|
+
- μ€ν ν `last_hit_at`μ κ°μ λ²μ λ²μ **λ΄μ μΈκ·Έλ¨ΌνΈ νμ λν΄μλ§** μ§μμ§λλ€(`--path` λ° νμ±νλ μ’
λ₯λ₯Ό μ€μ). λ°λΌμ νν°λ§λμκ±°λ λ¬Έμ μ μ© μ€νμ κ΄λ ¨ μλ νμΌμ μ€λλ μνλ‘ νμνμ§ μμ΅λλ€.
|
|
415
|
+
|
|
416
|
+
### μΆλ ₯ λ μ΄μμ
|
|
417
|
+
|
|
418
|
+
`"nested"`(κΈ°λ³Έκ°, μλ΅ μ) β `{outputDir}/{locale}/` μλμ μλ³Έ νΈλ¦¬λ₯Ό κ·Έλλ‘ λ°μν©λλ€(μ: `docs/guide.md` β `i18n/de/docs/guide.md`).
|
|
419
|
+
|
|
420
|
+
`"docusaurus"` β `docsRoot` μλμ μλ νμΌμ `i18n/<locale>/docusaurus-plugin-content-docs/current/<relativeToDocsRoot>`μ λ°°μΉνλ©°, μΌλ°μ μΈ Docusaurus i18n λ μ΄μμκ³Ό μΌμΉν©λλ€. `documentations[].markdownOutput.docsRoot`λ₯Ό λ¬Έμ μμ€ λ£¨νΈλ‘ μ€μ νμΈμ(μ: `"docs"`).
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
docs/guide.md β i18n/de/docusaurus-plugin-content-docs/current/guide.md
|
|
424
|
+
i18n/en/sidebar.json β i18n/de/sidebar.json (JSON label files)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
`"flat"` - λ²μλ νμΌμ λ‘μΌμΌ μ λ―Έμ¬κ° λΆμ μλ³Έ μμ΄λ νμ λλ ν°λ¦¬μ λ°°μΉν©λλ€. νμ΄μ§ κ°μ μλ λ§ν¬λ μλμΌλ‘ λ€μ μμ±λ©λλ€.
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
docs/guide.md β i18n/guide.de.md
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
`documentations[].markdownOutput.pathTemplate`μ μ¬μ©νμ¬ κ²½λ‘λ₯Ό μμ ν μ¬μ μν μ μμ΅λλ€. μ¬μ© κ°λ₯ν μ리νμμ: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{docsRoot}"}</code>, <code>{"{relativeToDocsRoot}"}</code>.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## ν΅ν© μν¬νλ‘μ°(UI + λ¬Έμ)
|
|
438
|
+
|
|
439
|
+
λ¨μΌ μ€μ μμ λͺ¨λ κΈ°λ₯μ νμ±ννμ¬ λ μν¬νλ‘μ°λ₯Ό ν¨κ» μ€νν©λλ€:
|
|
440
|
+
|
|
441
|
+
```json
|
|
442
|
+
{
|
|
443
|
+
"sourceLocale": "en-GB",
|
|
444
|
+
"targetLocales": "src/locales/ui-languages.json",
|
|
445
|
+
"features": {
|
|
446
|
+
"extractUIStrings": true,
|
|
447
|
+
"translateUIStrings": true,
|
|
448
|
+
"translateMarkdown": true,
|
|
449
|
+
"translateJSON": false,
|
|
450
|
+
"translateSVG": false
|
|
451
|
+
},
|
|
452
|
+
"glossary": {
|
|
453
|
+
"uiGlossary": "src/locales/strings.json",
|
|
454
|
+
"userGlossary": "glossary-user.csv"
|
|
455
|
+
},
|
|
456
|
+
"ui": {
|
|
457
|
+
"sourceRoots": ["src/"],
|
|
458
|
+
"stringsJson": "src/locales/strings.json",
|
|
459
|
+
"flatOutputDir": "src/locales/"
|
|
460
|
+
},
|
|
461
|
+
"cacheDir": ".translation-cache",
|
|
462
|
+
"documentations": [
|
|
463
|
+
{
|
|
464
|
+
"contentPaths": ["docs/"],
|
|
465
|
+
"outputDir": "i18n/",
|
|
466
|
+
"markdownOutput": { "style": "flat" }
|
|
467
|
+
}
|
|
468
|
+
]
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
`glossary.uiGlossary`λ UIμ λμΌν `strings.json` μΉ΄νλ‘κ·Έλ₯Ό λ¬Έμ λ²μμ μ¬μ©νμ¬ μ©μ΄ μΌκ΄μ±μ μ μ§ν©λλ€. `glossary.userGlossary`λ μ ν μ©μ΄μ λν CSV μ¬μ μλ₯Ό μΆκ°ν©λλ€.
|
|
473
|
+
|
|
474
|
+
`npx ai-i18n-tools sync`μ μ€ννμ¬ νλμ νμ΄νλΌμΈμ μνν©λλ€: **μΆμΆ** UI λ¬Έμμ΄(`features.extractUIStrings`μΈ κ²½μ°), **λ²μ UI** λ¬Έμμ΄(`features.translateUIStrings`μΈ κ²½μ°), **λ
립ν SVG μμ° λ²μ**(`features.translateSVG` λ° `svg` λΈλ‘μ΄ μ€μ λ κ²½μ°), κ·Έ ν **λ¬Έμ λ²μ**(κ° `documentations` λΈλ‘: ꡬμ±λ λλ‘ λ§ν¬λ€μ΄/JSON). `--no-ui`, `--no-svg` λλ `--no-docs`μ μ¬μ©νμ¬ μΌλΆ λ¨κ³λ₯Ό 건λλΈ μ μμ΅λλ€. λ¬Έμ λ¨κ³λ `--dry-run`, `-p` / `--path`, `--force`, `--force-update`μ νμ©ν©λλ€(λ§μ§λ§ λ μ΅μ
μ λ¬Έμ λ²μμ΄ μ€νλ λλ§ μ μ©λλ©°, `--no-docs`λ₯Ό μ λ¬νλ©΄ 무μλ©λλ€).
|
|
475
|
+
|
|
476
|
+
`documentations[].targetLocales`λ₯Ό λΈλ‘μ μ¬μ©νμ¬ ν΄λΉ λΈλ‘ νμΌμ UIλ³΄λ€ **λ μμ νμ μ§ν©**μΌλ‘ λ²μν©λλ€(ν¨κ³Όμ μΈ λ¬Έμ λ‘μΌμΌμ λΈλ‘ κ°μ **ν©μ§ν©**μ
λλ€):
|
|
477
|
+
|
|
478
|
+
```json
|
|
479
|
+
{
|
|
480
|
+
"targetLocales": "src/locales/ui-languages.json",
|
|
481
|
+
"documentations": [
|
|
482
|
+
{
|
|
483
|
+
"contentPaths": ["docs/"],
|
|
484
|
+
"outputDir": "i18n/",
|
|
485
|
+
"targetLocales": ["de", "fr", "es"]
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## μ€μ μ°Έμ‘°
|
|
494
|
+
|
|
495
|
+
### `sourceLocale`
|
|
496
|
+
|
|
497
|
+
μμ€ μΈμ΄μ BCP-47 μ½λ(μ: `"en-GB"`, `"en"`, `"pt-BR"`). μ΄ λ‘μΌμΌμ λν΄μλ λ²μ νμΌμ΄ μμ±λμ§ μμΌλ©°, ν€ λ¬Έμμ΄ μμ²΄κ° μμ€ ν
μ€νΈμ
λλ€.
|
|
498
|
+
|
|
499
|
+
**μΌμΉν΄μΌ ν©λλ€** λ°νμ i18n μ€μ νμΌ(`src/i18n.ts` / `src/i18n.js`)μμ λ΄λ³΄λΈ `SOURCE_LOCALE`κ³Ό.
|
|
500
|
+
|
|
501
|
+
### `targetLocales`
|
|
502
|
+
|
|
503
|
+
μ΄λ€ λ‘μΌμΌλ‘ λ²μν μ§ μ§μ ν©λλ€. λ€μμ νμ©ν©λλ€:
|
|
504
|
+
|
|
505
|
+
- **λ¬Έμμ΄ κ²½λ‘**: `ui-languages.json` λ§€λνμ€νΈ νμΌ(`"src/locales/ui-languages.json"`). νμΌμ΄ λ‘λλκ³ λ‘μΌμΌ μ½λκ° μΆμΆλ©λλ€.
|
|
506
|
+
- **BCP-47 μ½λ λ°°μ΄**(`["de", "fr", "es"]`).
|
|
507
|
+
- **κ²½λ‘λ₯Ό ν¬ν¨νλ 1κ° μμ λ°°μ΄**(`["src/locales/ui-languages.json"]`) - λ¬Έμμ΄ νμκ³Ό λμΌν λμμ ν©λλ€.
|
|
508
|
+
|
|
509
|
+
`targetLocales`λ UI λ²μμ μν μ£Ό λ‘μΌμΌ λͺ©λ‘μ΄λ©° λ¬Έμ λΈλ‘μ κΈ°λ³Έ λ‘μΌμΌ λͺ©λ‘μ
λλ€. μ¬κΈ°μ λͺ
μμ λ°°μ΄μ μ μ§νλ©΄μλ λ§€λνμ€νΈ κΈ°λ° λ μ΄λΈκ³Ό λ‘μΌμΌ νν°λ§μ μνλ€λ©΄ `uiLanguagesPath`λ μ€μ νμμμ€.
|
|
510
|
+
|
|
511
|
+
### `uiLanguagesPath`(μ ν μ¬ν)
|
|
512
|
+
|
|
513
|
+
νμ μ΄λ¦, λ‘μΌμΌ νν°λ§ λ° μΈμ΄ λͺ©λ‘ νμ²λ¦¬λ₯Ό μν΄ μ¬μ©λλ `ui-languages.json` λ§€λνμ€νΈμ κ²½λ‘μ
λλ€.
|
|
514
|
+
|
|
515
|
+
λ€μκ³Ό κ°μ κ²½μ°μ μ¬μ©ν©λλ€:
|
|
516
|
+
|
|
517
|
+
- `targetLocales`κ° λͺ
μμ λ°°μ΄μ΄μ§λ§ μ¬μ ν λ§€λνμ€νΈμμ μλ¬Έ/νμ§ μΈμ΄ λ μ΄λΈμ μν λ.
|
|
518
|
+
- `markdownOutput.postProcessing.languageListBlock`μ΄ λμΌν λ§€λνμ€νΈμμ λ‘μΌμΌ λ μ΄λΈμ μμ±νλλ‘ μν λ.
|
|
519
|
+
- UI λ²μλ§ νμ±νλμ΄ μκ³ λ§€λνμ€νΈκ° ν¨κ³Όμ μΈ UI λ‘μΌμΌ λͺ©λ‘μ μ 곡νλλ‘ μν λ.
|
|
520
|
+
|
|
521
|
+
### `concurrency`(μ ν μ¬ν)
|
|
522
|
+
|
|
523
|
+
λμμ λ²μν μ μλ **λμ λ‘μΌμΌ**μ μ΅λ μ(`translate-ui`, `translate-docs`, `translate-svg` λ° `sync` λ΄μ μΌμΉνλ λ¨κ³). μλ΅νλ©΄ CLIλ UI λ²μμ **4**, λ¬Έμ λ²μμ **3**μ μ¬μ©ν©λλ€(κΈ°λ³Έκ°). μ€ν μ `-j` / `--concurrency`λ‘ μ¬μ μν μ μμ΅λλ€.
|
|
524
|
+
|
|
525
|
+
### `batchConcurrency`(μ ν μ¬ν)
|
|
526
|
+
|
|
527
|
+
**λ¬Έμ λ²μ** λ° **SVG λ²μ** (λ° `sync`μ λ¬Έμν λ¨κ³): νμΌλΉ μ΅λ λ³λ ¬ OpenRouter **λ°°μΉ** μμ² μ (κ° λ°°μΉμλ μ¬λ¬ μΈκ·Έλ¨ΌνΈκ° ν¬ν¨λ μ μμ΅λλ€). κΈ°λ³Έκ°μ μλ΅ μ **4**μ
λλ€. `translate-ui`μμλ 무μλ©λλ€. `-b` / `--batch-concurrency`λ‘ μ¬μ μν μ μμ΅λλ€. `sync`μμλ `-b`κ° λ¬Έμ λ²μ λ¨κ³μλ§ μ μ©λ©λλ€.
|
|
528
|
+
|
|
529
|
+
### `batchSize` / `maxBatchChars` (μ ν μ¬ν)
|
|
530
|
+
|
|
531
|
+
λ¬Έμ λ²μμ μν μΈκ·Έλ¨ΌνΈ λ°°μΉ: API μμ²λΉ λͺ κ°μ μΈκ·Έλ¨ΌνΈμ λ¬Έμ νκ³. κΈ°λ³Έκ°: **20** μΈκ·Έλ¨ΌνΈ, **4096** λ¬Έμ (μλ΅ μ).
|
|
532
|
+
|
|
533
|
+
### `openrouter`
|
|
534
|
+
|
|
535
|
+
| νλ | μ€λͺ
|
|
|
536
|
+
| ------------------- | ---------------------------------------------------------------------------------------- |
|
|
537
|
+
| `baseUrl` | OpenRouter API κΈ°λ³Έ URL. κΈ°λ³Έκ°: `https://openrouter.ai/api/v1`. |
|
|
538
|
+
| `translationModels` | μ νΈνλ λͺ¨λΈ IDμ μ λ ¬λ λͺ©λ‘. 첫 λ²μ§Έ λͺ¨λΈμ΄ λ¨Όμ μλλλ©°, μ΄ν νλͺ©μ μ€λ₯ λ°μ μ λ체 λͺ¨λΈμ
λλ€. `translate-ui` μ μ©μΌλ‘**, μ΄ λͺ©λ‘ μ μ μλν λͺ¨λΈμ μν΄ `ui.preferredModel`μ μ€μ ν μ μμ΅λλ€ (μμΈν λ΄μ©μ `ui` μ°Έμ‘°). |
|
|
539
|
+
| `defaultModel` | λ κ±°μ λ¨μΌ κΈ°λ³Έ λͺ¨λΈ. `translationModels`κ° μ€μ λμ§ μκ±°λ λΉμ΄ μμ λλ§ μ¬μ©λ©λλ€. |
|
|
540
|
+
| `fallbackModel` | λ κ±°μ λ¨μΌ λ체 λͺ¨λΈ. `translationModels`κ° μ€μ λμ§ μκ±°λ λΉμ΄ μμ λ `defaultModel` μ΄νμ μ¬μ©λ©λλ€. |
|
|
541
|
+
| `maxTokens` | μμ²λΉ μ΅λ μλ£ ν ν° μ. κΈ°λ³Έκ°: `8192`. |
|
|
542
|
+
| `temperature` | μνλ§ μ¨λ. κΈ°λ³Έκ°: `0.2`. |
|
|
543
|
+
|
|
544
|
+
νκ²½ λλ `.env` νμΌμ `OPENROUTER_API_KEY`λ₯Ό μ€μ νμΈμ.
|
|
545
|
+
|
|
546
|
+
### `features`
|
|
547
|
+
|
|
548
|
+
| νλ | μν¬νλ‘ | μ€λͺ
|
|
|
549
|
+
| -------------------- | -------- | ----------------------------------------------------------------- |
|
|
550
|
+
| `extractUIStrings` | 1 | μμ€λ₯Ό κ²μ¬νμ¬ `t("β¦")`μ μ°Ύκ³ `strings.json`μ μμ±/λ³ν©ν©λλ€. |
|
|
551
|
+
| `translateUIStrings` | 1 | `strings.json` νλͺ©μ λ²μνκ³ μ§μλ³ JSON νμΌμ μμ±ν©λλ€. |
|
|
552
|
+
| `translateMarkdown` | 2 | `.md` / `.mdx` νμΌμ λ²μν©λλ€. |
|
|
553
|
+
| `translateJSON` | 2 | Docusaurus JSON λ μ΄λΈ νμΌμ λ²μν©λλ€. |
|
|
554
|
+
| `translateSVG` | 2 | λ
립ν `.svg` μμ°μ λ²μν©λλ€(μ΅μμ `svg` λΈλ‘ νμ).
|
|
555
|
+
|
|
556
|
+
`features.translateSVG`μ΄ trueμ΄κ³ μ΅μμ `svg` λΈλ‘μ΄ κ΅¬μ±λ κ²½μ°, `translate-svg`μ μ¬μ©νμ¬ **λ
립ν** SVG μμ°μ λ²μν©λλ€. `sync` λͺ
λ Ήμ λ μ‘°κ±΄μ΄ λͺ¨λ μ€μ λ κ²½μ° ν΄λΉ λ¨κ³λ₯Ό μ€νν©λλ€(`--no-svg`μΈ κ²½μ° μ μΈ).
|
|
557
|
+
|
|
558
|
+
### `ui`
|
|
559
|
+
|
|
560
|
+
| νλ | μ€λͺ
|
|
|
561
|
+
| --------------------------- | ----------------------------------------------------------------------- |
|
|
562
|
+
| `sourceRoots` | `t("β¦")` νΈμΆμ μ€μΊνλ λλ ν 리 (νμ¬ μμ
λλ ν 리 κΈ°μ€). |
|
|
563
|
+
| `stringsJson` | λ§μ€ν° μΉ΄νλ‘κ·Έ νμΌμ κ²½λ‘. `extract`μ μν΄ μ
λ°μ΄νΈλ©λλ€. |
|
|
564
|
+
| `flatOutputDir` | μ§μλ³ JSON νμΌμ΄ μμ±λλ λλ ν 리 (`de.json` λ±). |
|
|
565
|
+
| `preferredModel` | μ ν μ¬ν. `translate-ui` μ μ©μΌλ‘ λ¨Όμ μλν OpenRouter λͺ¨λΈ ID; μ΄ν `openrouter.translationModels` (λλ λ κ±°μ λͺ¨λΈ) μμλλ‘, μ΄ IDλ₯Ό μ€λ³΅νμ§ μκ³ . |
|
|
566
|
+
| `reactExtractor.funcNames` | μ€μΊν μΆκ° ν¨μ μ΄λ¦ (κΈ°λ³Έκ°: `["t", "i18n.t"]`). |
|
|
567
|
+
| `reactExtractor.extensions` | ν¬ν¨ν νμΌ νμ₯μ (κΈ°λ³Έκ°: `[".js", ".jsx", ".ts", ".tsx"]`). |
|
|
568
|
+
| `reactExtractor.includePackageDescription` | `true`μΌ λ (κΈ°λ³Έκ°), `extract`λ `package.json`μ `description`μ UI λ¬Έμμ΄λ‘ ν¬ν¨ν©λλ€ (μ‘΄μ¬ν κ²½μ°). |
|
|
569
|
+
| `reactExtractor.packageJsonPath` | ν΄λΉ μ νμ μ€λͺ
μΆμΆμ μ¬μ©λλ `package.json` νμΌμ μ¬μ©μ μ μ κ²½λ‘. |
|
|
570
|
+
|
|
571
|
+
### `cacheDir`
|
|
572
|
+
|
|
573
|
+
| νλ | μ€λͺ
|
|
|
574
|
+
| ---------- | ----------------------------------------------------------------------------- |
|
|
575
|
+
| `cacheDir` | λͺ¨λ `documentations` λΈλ‘μμ 곡μ λλ SQLite μΊμ λλ ν 리. μ€ν κ° μ¬μ¬μ©λ©λλ€. |
|
|
576
|
+
|
|
577
|
+
### `documentations`
|
|
578
|
+
|
|
579
|
+
λ¬Έμν νμ΄νλΌμΈ λΈλ‘λ€μ λ°°μ΄μ
λλ€. `translate-docs`μ `sync`μ docs λ¨κ³λ **κ°κ°**μ λΈλ‘μ μμλλ‘ μ²λ¦¬ν©λλ€.
|
|
580
|
+
|
|
581
|
+
| νλ | μ€λͺ
|
|
|
582
|
+
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
583
|
+
| `description` | μ΄ λΈλ‘μ λν μ νμ μΈκ°μ΄ μ½μ μ μλ λ©λͺ¨(λ²μμλ μ¬μ©λμ§ μμ). μ€μ λ κ²½μ° `translate-docs`μ `π` ν€λλΌμΈ μμ νμλλ©°, `status` μΉμ
ν€λμλ νμλ¨. |
|
|
584
|
+
| `contentPaths` | λ²μν Markdown/MDX μμ€(`translate-docs`κ° `.md` / `.mdx` νμΌμ μ€μΊν¨). JSON λ μ΄λΈμ λμΌν λΈλ‘μ `jsonSource`μμ κ°μ Έμ΄. |
|
|
585
|
+
| `outputDir` | μ΄ λΈλ‘μ λν λ²μ μΆλ ₯μ λ£¨νΈ λλ ν°λ¦¬. |
|
|
586
|
+
| `sourceFiles` | λ‘λ μ `contentPaths`μ λ³ν©λλ μ νμ λ³μΉ. |
|
|
587
|
+
| `targetLocales` | μ΄ λΈλ‘μλ§ μ μ©λλ μ νμ λ‘μΌμΌ νμ μ§ν©(κ·Έλ μ§ μμΌλ©΄ λ£¨νΈ `targetLocales` μ¬μ©). μ ν¨ν λ¬Έμ λ‘μΌμΌμ λͺ¨λ λΈλ‘μ ν©μ§ν©μ. |
|
|
588
|
+
| `jsonSource` | μ΄ λΈλ‘μ λν Docusaurus JSON λ μ΄λΈ νμΌμ μμ€ λλ ν°λ¦¬(μ: `"i18n/en"`). |
|
|
589
|
+
| `markdownOutput.style` | `"nested"`(κΈ°λ³Έκ°), `"docusaurus"`, λλ `"flat"`. |
|
|
590
|
+
| `markdownOutput.docsRoot` | Docusaurus λ μ΄μμμ μν μμ€ docs 루νΈ(μ: `"docs"`). |
|
|
591
|
+
| `markdownOutput.pathTemplate` | μ¬μ©μ μ μ λ§ν¬λ€μ΄ μΆλ ₯ κ²½λ‘. μ리νμμ: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{docsRoot}"}</code>, <code>{"{relativeToDocsRoot}"}</code>. |
|
|
592
|
+
| `markdownOutput.jsonPathTemplate` | λ μ΄λΈ νμΌμ μ¬μ©μ μ μ JSON μΆλ ₯ κ²½λ‘. `pathTemplate`κ³Ό λμΌν μ리νμμλ₯Ό μ§μν¨. |
|
|
593
|
+
| `markdownOutput.flatPreserveRelativeDir` | `flat` μ€νμΌμ κ²½μ°, λμΌν basenameμ κ°μ§ νμΌμ΄ μΆ©λνμ§ μλλ‘ μμ€ νμ λλ ν°λ¦¬λ₯Ό μ μ§ν¨. |
|
|
594
|
+
| `markdownOutput.rewriteRelativeLinks` | λ²μ ν μλ λ§ν¬λ₯Ό λ€μ μμ±ν¨(`flat` μ€νμΌμμλ μλμΌλ‘ νμ±νλ¨). |
|
|
595
|
+
| `markdownOutput.linkRewriteDocsRoot` | νλ©΄ λ§ν¬ μ¬μμ± μ λμ¬λ₯Ό κ³μ°ν λ μ¬μ©λλ 리ν¬μ§ν°λ¦¬ 루νΈ. λ²μλ λ¬Έμκ° λ€λ₯Έ νλ‘μ νΈ λ£¨νΈ μλμ μμ§ μμ ν μΌλ°μ μΌλ‘ `"."`λ‘ λ . |
|
|
596
|
+
| `markdownOutput.postProcessing` | λ²μλ λ§ν¬λ€μ΄ **λ³Έλ¬Έ**μ λν μ νμ λ³ν(YAML front matterλ μ μ§λ¨). μΈκ·Έλ¨ΌνΈ μ¬μ‘°ν© λ° νλ©΄ λ§ν¬ μ¬μμ± ν, `addFrontmatter` μ΄μ μ μ€νλ¨. |
|
|
597
|
+
| `markdownOutput.postProcessing.regexAdjustments` | `{ "description"?, "search", "replace" }`μ μμ μλ λͺ©λ‘. `search`λ μ κ·μ ν¨ν΄μ(μΌλ° λ¬Έμμ΄μ νλκ·Έ `g` μ¬μ©, λλ `/pattern/flags`). `replace`λ `${translatedLocale}`, `${sourceLocale}`, `${sourceFullPath}`, `${translatedFullPath}`, `${sourceFilename}`, `${translatedFilename}`, `${sourceBasedir}`, `${translatedBasedir}`(μ°Έμ‘° λ¬Έμ `additional-adjustments`μ λμΌν κ°λ
) λ±μ μ리νμμλ₯Ό μ§μν¨. |
|
|
598
|
+
| `markdownOutput.postProcessing.languageListBlock` | `{ "start", "end", "separator" }` β λ²μκΈ°λ `start`λ₯Ό ν¬ν¨νλ 첫 λ²μ§Έ μ€κ³Ό μΌμΉνλ `end` μ€μ μ°Ύμ ν, ν΄λΉ λ²μλ₯Ό νμ€ μΈμ΄ μ νκΈ°λ‘ λ체ν¨. λ§ν¬λ λ²μλ νμΌμ κΈ°μ€μΌλ‘ μλ κ²½λ‘λ‘ μμ±λ¨; λ μ΄λΈμ ꡬμ±λ κ²½μ° `uiLanguagesPath` / `ui-languages.json`μμ κ°μ Έμ€κ³ , κ·Έλ μ§ μμΌλ©΄ `localeDisplayNames` λ° λ‘μΌμΌ μ½λμμ κ°μ Έμ΄. |
|
|
599
|
+
| `addFrontmatter` | `true`μΈ κ²½μ°(μλ΅ μ κΈ°λ³Έκ°), λ²μλ λ§ν¬λ€μ΄ νμΌμλ YAML ν€κ° ν¬ν¨λ¨: `translation_last_updated`, `source_file_mtime`, `source_file_hash`, `translation_language`, `source_file_path`, κ·Έλ¦¬κ³ μΈκ·Έλ¨ΌνΈ μ€ νλ μ΄μμ λͺ¨λΈ λ©νλ°μ΄ν°κ° μλ κ²½μ° `translation_models`(μ¬μ©λ OpenRouter λͺ¨λΈ IDμ μ λ ¬λ λͺ©λ‘). μλ΅νλ €λ©΄ `false`λ‘ μ€μ . |
|
|
600
|
+
|
|
601
|
+
μμ (λ¨μν README νμ΄νλΌμΈ β μ€ν¬λ¦°μ· κ²½λ‘ + μ νμ μΈμ΄ λͺ©λ‘ λνΌ):
|
|
602
|
+
|
|
603
|
+
```json
|
|
604
|
+
"markdownOutput": {
|
|
605
|
+
"style": "flat",
|
|
606
|
+
"postProcessing": {
|
|
607
|
+
"regexAdjustments": [
|
|
608
|
+
{
|
|
609
|
+
"description": "Per-locale screenshot folders",
|
|
610
|
+
"search": "images/screenshots/[^/]+/",
|
|
611
|
+
"replace": "images/screenshots/${translatedLocale}/"
|
|
612
|
+
}
|
|
613
|
+
],
|
|
614
|
+
"languageListBlock": {
|
|
615
|
+
"start": "<small id=\"lang-list\">",
|
|
616
|
+
"end": "</small>",
|
|
617
|
+
"separator": " Β· "
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### `svg` (μ ν μ¬ν)
|
|
624
|
+
|
|
625
|
+
λ
립ν SVG μμ°μ μν μ΅μμ κ²½λ‘ λ° λ μ΄μμ. λ²μμ **`features.translateSVG`** μ΄ trueμΌ λλ§ μ€νλ©λλ€(`translate-svg` λλ `sync`μ SVG λ¨κ³λ₯Ό ν΅ν΄).
|
|
626
|
+
|
|
627
|
+
| νλ | μ€λͺ
|
|
|
628
|
+
| --------------------------- | ----------- |
|
|
629
|
+
| `sourcePath` | `.svg` νμΌμ μ¬κ·μ μΌλ‘ κ²μν νλμ λλ ν°λ¦¬ λλ λλ ν°λ¦¬ λ°°μ΄μ
λλ€. |
|
|
630
|
+
| `outputDir` | λ²μλ SVG μΆλ ₯μ λ£¨νΈ λλ ν°λ¦¬μ
λλ€. |
|
|
631
|
+
| `style` | `pathTemplate`μ΄ μ€μ λμ§ μμ κ²½μ° `"flat"` λλ `"nested"`μ
λλ€. |
|
|
632
|
+
| `pathTemplate` | μ¬μ©μ μ μ SVG μΆλ ₯ κ²½λ‘μ
λλ€. μ리νμμ: <code>{"{outputDir}"}</code>, <code>{"{locale}"}</code>, <code>{"{LOCALE}"}</code>, <code>{"{relPath}"}</code>, <code>{"{stem}"}</code>, <code>{"{basename}"}</code>, <code>{"{extension}"}</code>, <code>{"{relativeToSourceRoot}"}</code>. |
|
|
633
|
+
| `svgExtractor.forceLowercase` | SVG μ¬μ‘°ν© μ λ²μλ ν
μ€νΈλ₯Ό μλ¬Έμλ‘ λ³νν©λλ€. λͺ¨λ μλ¬Έμ λ μ΄λΈμ μμ‘΄νλ λμμΈμ μ μ©ν©λλ€. |
|
|
634
|
+
|
|
635
|
+
### `glossary`
|
|
636
|
+
|
|
637
|
+
| νλ | μ€λͺ
|
|
|
638
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
639
|
+
| `uiGlossary` | `strings.json`μ λν κ²½λ‘ - κΈ°μ‘΄ λ²μμ κΈ°λ°μΌλ‘ μ©μ΄μ§μ μλ μμ±ν©λλ€. |
|
|
640
|
+
| `userGlossary` | `Original language string`(λλ `en`), `locale`, `Translation` μ΄μ κ°μ§ CSV νμΌμ λν κ²½λ‘ - κ° μλ³Έ μ©μ΄μ λμ λ‘μΌμΌ(`locale`μ λͺ¨λ λμμ λν΄ `*`μΌ μ μμ) λΉ ν νμ© μ‘΄μ¬ν©λλ€. |
|
|
641
|
+
|
|
642
|
+
λ κ±°μ ν€ `uiGlossaryFromStringsJson`λ μ¬μ ν νμ©λλ©° μ€μ λ‘λ μ `uiGlossary`μ λ§€νλ©λλ€.
|
|
643
|
+
|
|
644
|
+
λΉ μ©μ΄μ§ CSV μμ±:
|
|
645
|
+
|
|
646
|
+
```bash
|
|
647
|
+
npx ai-i18n-tools glossary-generate
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## CLI μ°Έμ‘°
|
|
653
|
+
|
|
654
|
+
| λͺ
λ Ή | μ€λͺ
|
|
|
655
|
+
| --- | --- |
|
|
656
|
+
| `init [-t ui-markdown|ui-docusaurus] [-o path] [--with-translate-ignore]` | μμ κ΅¬μ± νμΌμ μμ±ν©λλ€ (`concurrency`, `batchConcurrency`, `batchSize`, `maxBatchChars`, `documentations[].addFrontmatter` ν¬ν¨). `--with-translate-ignore`λ μμμ© `.translate-ignore`μ μμ±ν©λλ€. |
|
|
657
|
+
| `extract` | μμ€μμ `t("β¦")` νΈμΆμ μ€μΊνκ³ `strings.json`μ μ
λ°μ΄νΈν©λλ€. `features.extractUIStrings`μ΄ νμν©λλ€. |
|
|
658
|
+
| `translate-docs β¦` | κ° `documentations` λΈλ‘(νμ `contentPaths`, μ νμ `jsonSource`)μ λ§ν¬λ€μ΄/MDX λ° JSONμ λ²μν©λλ€. `-j`: μ΅λ λ³λ ¬ λ‘μΌμΌ μ; `-b`: νμΌλΉ μ΅λ λ³λ ¬ λ°°μΉ API νΈμΆ μ. `--prompt-format`: λ°°μΉ μ μ‘ νμ (`xml` \| `json-array` \| `json-object`). [μΊμ λμ λ° `translate-docs` νλκ·Έ](#cache-behaviour-and-translate-docs-flags) λ° [λ°°μΉ ν둬ννΈ νμ](#batch-prompt-format) μ°Έμ‘°. |
|
|
659
|
+
| `translate-svg β¦` | `config.svg`μμ ꡬμ±λ λ
립ν SVG μμ°μ λ²μν©λλ€(λ¬Έμμ λ³λ). `features.translateSVG`κ° νμν©λλ€. λ¬Έμμ λμΌν μΊμ κ°λ
μ μ¬μ©νλ©°, ν΄λΉ μ€νμμ SQLite μ½κΈ°/μ°κΈ°λ₯Ό 건λλ°κΈ° μν΄ `--no-cache`λ₯Ό μ§μν©λλ€. `-j`, `-b`, `--force`, `--force-update`, `-p` / `--path`, `--dry-run`. |
|
|
660
|
+
| `translate-ui [--locale <code>] [--force] [--dry-run] [-j <n>]` | UI λ¬Έμμ΄λ§ λ²μν©λλ€. `--force`: κΈ°μ‘΄ λ²μμ 무μνκ³ λ‘μΌμΌλ³λ‘ λͺ¨λ νλͺ©μ λ€μ λ²μν©λλ€. `--dry-run`: μ°κΈ° μμ, API νΈμΆ μμ. `-j`: μ΅λ λ³λ ¬ λ‘μΌμΌ μ. `features.translateUIStrings`μ΄ νμν©λλ€. |
|
|
661
|
+
| `export-ui-xliff [-l <codes>] [-o <dir>] [--untranslated-only] [--dry-run]` | `strings.json`μ XLIFF 2.0 νμμΌλ‘ λ΄λ³΄λ
λλ€(λμ λ‘μΌμΌλΉ νλμ `.xliff`). `-o` / `--output-dir`: μΆλ ₯ λλ ν°λ¦¬(κΈ°λ³Έκ°: μΉ΄νλ‘κ·Έμ λμΌν ν΄λ). `--untranslated-only`: ν΄λΉ λ‘μΌμΌμμ λ²μμ΄ λλ½λ νλͺ©λ§ ν¬ν¨ν©λλ€. μ½κΈ° μ μ©; API μμ. |
|
|
662
|
+
| `sync β¦` | νμ±νλ κ²½μ° μΆμΆ ν UI λ²μ, `features.translateSVG` λ° `config.svg`μ΄ μ€μ λ κ²½μ° `translate-svg`, κ·Έ ν λ¬Έμ λ²μμ μνν©λλ€. λ¨, `--no-ui`, `--no-svg`, λλ `--no-docs`λ‘ κ±΄λλΈ μ μμ΅λλ€. 곡μ νλκ·Έ: `-l`, `-p`, `--dry-run`, `-j`, `-b` (λ¬Έμ λ°°μΉ μ μ©), `--force` / `--force-update` (λ¬Έμ μ μ©; λ¬Έμ μ€ν μ μνΈ λ°°νμ ). |
|
|
663
|
+
| `status` | νμΌ Γ λ‘μΌμΌλ³ λ§ν¬λ€μ΄ λ²μ μνλ₯Ό νμν©λλ€(`--locale` νν° μμ; λ‘μΌμΌμ ꡬμ±μμ κ°μ Έμ΄). |
|
|
664
|
+
| `cleanup [--dry-run] [--no-backup] [--backup <path>]` | λ¨Όμ `sync --force-update`λ₯Ό μ€νν ν(μΆμΆ, UI, SVG, λ¬Έμ), κ³ μ₯λ μΈκ·Έλ¨ΌνΈ ν(null `last_hit_at` / λΉμ΄ μλ νμΌ κ²½λ‘)μ μ κ±°νκ³ , λμ€ν¬μμμ ν΄κ²°λ μμ€ κ²½λ‘κ° μλ `file_tracking` νμ μμ νλ©°, μ‘΄μ¬νμ§ μλ νμΌμ κ°λ¦¬ν€λ `filepath` λ©νλ°μ΄ν°κ° μλ λ²μ νμ μ κ±°ν©λλ€. μΈ κ°μ§ μΉ΄μ΄νΈ(κ³ μ₯λ, κ³ μλ `file_tracking`, κ³ μλ λ²μ)λ₯Ό κΈ°λ‘ν©λλ€. `--no-backup`μ΄ μ€μ λμ§ μμ κ²½μ° μΊμ λλ ν°λ¦¬ μλμ νμμ€ν¬νκ° λΆμ SQLite λ°±μ
μ μμ±ν©λλ€. |
|
|
665
|
+
| `editor [-p <port>] [--no-open]` | μΊμ, `strings.json`, μ©μ΄μ§ CSVλ₯Ό μν λ‘컬 μΉ νΈμ§κΈ°λ₯Ό μ€νν©λλ€. `--no-open`: κΈ°λ³Έ λΈλΌμ°μ λ₯Ό μλμΌλ‘ μ΄μ§ μμ΅λλ€.<br><br>**μ°Έκ³ :** μΊμ νΈμ§κΈ°μμ νλͺ©μ νΈμ§ν κ²½μ°, μ
λ°μ΄νΈλ μΊμ νλͺ©μΌλ‘ μΆλ ₯ νμΌμ λ€μ μμ±νκΈ° μν΄ `sync --force-update`μ μ€νν΄μΌ ν©λλ€. λν λμ€μ μμ€ ν
μ€νΈκ° λ³κ²½λλ©΄ μλ‘μ΄ μΊμ ν€κ° μμ±λκΈ° λλ¬Έμ μλ νΈμ§ λ΄μ©μ μ¬λΌμ§λλ€. |
|
|
666
|
+
| `glossary-generate [-o <path>]` | λΉ `glossary-user.csv` ν
νλ¦Ώμ μμ±ν©λλ€. `-o`: μΆλ ₯ κ²½λ‘λ₯Ό μ¬μ μν©λλ€(κΈ°λ³Έκ°: ꡬμ±μ `glossary.userGlossary` λλ `glossary-user.csv`). |
|
|
667
|
+
|
|
668
|
+
λͺ¨λ λͺ
λ Ήμ΄λ λΉκΈ°λ³Έ μ€μ νμΌμ μ§μ νκΈ° μν `-c <κ²½λ‘>`, μμΈν μΆλ ₯μ μν `-v`, κ·Έλ¦¬κ³ μ½μ μΆλ ₯μ λ‘κ·Έ νμΌλ‘ 볡μ νκΈ° μν `-w` / `--write-logs [κ²½λ‘]`λ₯Ό μ§μν©λλ€(κΈ°λ³Έ κ²½λ‘: λ£¨νΈ `cacheDir` μλ).
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
## νκ²½ λ³μ
|
|
673
|
+
|
|
674
|
+
| λ³μ | μ€λͺ
|
|
|
675
|
+
| ------------------------ | ------------------------------------------------------------ |
|
|
676
|
+
| `OPENROUTER_API_KEY` | **νμ.** OpenRouter API ν€μ
λλ€. |
|
|
677
|
+
| `OPENROUTER_BASE_URL` | API κΈ°λ³Έ URLμ μ¬μ μν©λλ€. |
|
|
678
|
+
| `I18N_SOURCE_LOCALE` | λ°νμ μ `sourceLocale`λ₯Ό μ¬μ μν©λλ€. |
|
|
679
|
+
| `I18N_TARGET_LOCALES` | μΌνλ‘ κ΅¬λΆλ λ‘μΌμΌ μ½λλ‘ `targetLocales`λ₯Ό μ¬μ μν©λλ€. |
|
|
680
|
+
| `I18N_LOG_LEVEL` | λ‘κ±° λ 벨(`debug`, `info`, `warn`, `error`, `silent`). |
|
|
681
|
+
| `NO_COLOR` | `1`μΌ κ²½μ° λ‘κ·Έ μΆλ ₯μμ ANSI μμμ λΉνμ±νν©λλ€. |
|
|
682
|
+
| `I18N_LOG_SESSION_MAX` | λ‘κ·Έ μΈμ
λΉ μ μ§λλ μ΅λ μ€ μ(κΈ°λ³Έκ° `5000`). |
|