champollion 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE +133 -0
  2. package/README.md +387 -0
  3. package/bin/cli.js +278 -0
  4. package/index.js +135 -0
  5. package/lib/api-key.js +127 -0
  6. package/lib/autofix.js +432 -0
  7. package/lib/bridge/method_bridge.py +430 -0
  8. package/lib/card-source-resolution.mjs +284 -0
  9. package/lib/cards/cache.js +169 -0
  10. package/lib/cards/env.js +82 -0
  11. package/lib/cards/fetch-card-child.js +38 -0
  12. package/lib/cards/reader.js +435 -0
  13. package/lib/cards/refresh.js +111 -0
  14. package/lib/cards/remote.js +387 -0
  15. package/lib/cldf-export.mjs +540 -0
  16. package/lib/cldf-terms.mjs +62 -0
  17. package/lib/command-help.js +790 -0
  18. package/lib/commands/audit.js +49 -0
  19. package/lib/commands/card.js +454 -0
  20. package/lib/commands/doctor.js +559 -0
  21. package/lib/commands/fonts.js +489 -0
  22. package/lib/commands/help.js +91 -0
  23. package/lib/commands/init.js +1259 -0
  24. package/lib/commands/integrity.js +148 -0
  25. package/lib/commands/leaderboard.js +478 -0
  26. package/lib/commands/lint.js +30 -0
  27. package/lib/commands/models.js +177 -0
  28. package/lib/commands/plugin.js +103 -0
  29. package/lib/commands/provenance.js +45 -0
  30. package/lib/commands/recommend.js +75 -0
  31. package/lib/commands/register-corpus.js +678 -0
  32. package/lib/commands/repair-script.js +42 -0
  33. package/lib/commands/seal-corpus.js +355 -0
  34. package/lib/commands/seo.js +72 -0
  35. package/lib/commands/serve.js +147 -0
  36. package/lib/commands/status.js +265 -0
  37. package/lib/commands/submit.js +332 -0
  38. package/lib/commands/sync.js +89 -0
  39. package/lib/commands/tm.js +573 -0
  40. package/lib/commands/verify.js +39 -0
  41. package/lib/commands/watch.js +20 -0
  42. package/lib/commands/wrap.js +138 -0
  43. package/lib/commands/xliff.js +327 -0
  44. package/lib/commercial-eligibility.js +235 -0
  45. package/lib/concurrent.js +87 -0
  46. package/lib/config.js +523 -0
  47. package/lib/contamination-lane.js +76 -0
  48. package/lib/content-sync.js +731 -0
  49. package/lib/content.js +733 -0
  50. package/lib/corpus-registration.mjs +608 -0
  51. package/lib/cost-report.js +346 -0
  52. package/lib/diff.js +155 -0
  53. package/lib/docusaurus-sync.js +1256 -0
  54. package/lib/flatten.js +55 -0
  55. package/lib/format.js +954 -0
  56. package/lib/hash.js +159 -0
  57. package/lib/icu.js +473 -0
  58. package/lib/integrity.js +689 -0
  59. package/lib/license-gate.mjs +478 -0
  60. package/lib/license-identify.mjs +229 -0
  61. package/lib/lint.js +629 -0
  62. package/lib/method-manifest.js +60 -0
  63. package/lib/methods/anthropic.js +140 -0
  64. package/lib/methods/apertium.js +163 -0
  65. package/lib/methods/api.js +316 -0
  66. package/lib/methods/base.js +184 -0
  67. package/lib/methods/content-separator.js +45 -0
  68. package/lib/methods/deepl.js +426 -0
  69. package/lib/methods/direct-llm.js +586 -0
  70. package/lib/methods/external.js +332 -0
  71. package/lib/methods/fetch-with-retry.js +124 -0
  72. package/lib/methods/gemini.js +147 -0
  73. package/lib/methods/google-translate.js +402 -0
  74. package/lib/methods/http-utils.js +122 -0
  75. package/lib/methods/libretranslate.js +314 -0
  76. package/lib/methods/llm-coached.js +670 -0
  77. package/lib/methods/llm.js +592 -0
  78. package/lib/methods/local.js +76 -0
  79. package/lib/methods/microsoft-translator.js +331 -0
  80. package/lib/methods/openai.js +131 -0
  81. package/lib/methods/openrouter-client.js +327 -0
  82. package/lib/methods/openrouter-pricing.js +156 -0
  83. package/lib/methods/provider-env.js +115 -0
  84. package/lib/methods/provider-pricing.js +310 -0
  85. package/lib/methods/tilde.js +150 -0
  86. package/lib/methods/translated.js +229 -0
  87. package/lib/methods/translation-error.js +80 -0
  88. package/lib/models.js +258 -0
  89. package/lib/no-translate.js +233 -0
  90. package/lib/output.js +238 -0
  91. package/lib/pairs.js +547 -0
  92. package/lib/plugins.js +447 -0
  93. package/lib/provenance.js +323 -0
  94. package/lib/recommend.js +648 -0
  95. package/lib/registers.js +1185 -0
  96. package/lib/repair-script.js +266 -0
  97. package/lib/scripts.js +994 -0
  98. package/lib/seal.mjs +464 -0
  99. package/lib/sealed-qualifier.mjs +211 -0
  100. package/lib/security.js +59 -0
  101. package/lib/segment.js +369 -0
  102. package/lib/seo.js +275 -0
  103. package/lib/serve.js +854 -0
  104. package/lib/string-classify.js +85 -0
  105. package/lib/submit.mjs +344 -0
  106. package/lib/sync.js +969 -0
  107. package/lib/tags/bcp47.js +202 -0
  108. package/lib/tags/resolve.js +314 -0
  109. package/lib/terminology.js +111 -0
  110. package/lib/tm-seed.js +294 -0
  111. package/lib/tm.js +515 -0
  112. package/lib/translate-pair.js +197 -0
  113. package/lib/translate.js +203 -0
  114. package/lib/types.js +230 -0
  115. package/lib/validate.js +510 -0
  116. package/lib/verify.js +451 -0
  117. package/lib/watch.js +145 -0
  118. package/lib/xliff.js +184 -0
  119. package/package.json +93 -0
  120. package/shared/ATTRIBUTION.md +145 -0
  121. package/shared/CORPORA-CARDS.md +288 -0
  122. package/shared/DATA-SOVEREIGNTY.md +500 -0
  123. package/shared/LANGUAGE-CARD-FIELDS.md +532 -0
  124. package/shared/card-lint-baseline.json +3189 -0
  125. package/shared/cards-fallback.json +1 -0
  126. package/shared/catalogue/card-config.json +6091 -0
  127. package/shared/catalogue/external-results.json +3888 -0
  128. package/shared/catalogue/gender-guidance.json +1038 -0
  129. package/shared/catalogue/method-coverage.json +1751 -0
  130. package/shared/catalogue/metric-coverage.json +170 -0
  131. package/shared/catalogue/metric-reliability.json +1 -0
  132. package/shared/catalogue/register-presets.json +3180 -0
  133. package/shared/catalogue/vitality-scales.json +55 -0
  134. package/shared/cldr-index.json +1115 -0
  135. package/shared/code-bridge.json +253 -0
  136. package/shared/corpora-cards-v1-reference.md +281 -0
  137. package/shared/curated-dictionary-flags.json +35 -0
  138. package/shared/curated-endonyms.json +35 -0
  139. package/shared/curated-fsts.json +51 -0
  140. package/shared/curated-orthography-conventions.json +26 -0
  141. package/shared/curated-sil-resources.json +374 -0
  142. package/shared/curated-tools.json +41 -0
  143. package/shared/docent/corpus.json +11333 -0
  144. package/shared/docent/faq.en.json +564 -0
  145. package/shared/docent/register-blocks.json +60 -0
  146. package/shared/docent/system-prompt.md +144 -0
  147. package/shared/domain-taxonomy.json +35 -0
  148. package/shared/explainers/glossary.json +2975 -0
  149. package/shared/explainers/tc-features.json +20112 -0
  150. package/shared/explainers/term-watchlist.json +147 -0
  151. package/shared/human-services.json +59 -0
  152. package/shared/license-corrections.json +261 -0
  153. package/shared/license-evidence.json +13452 -0
  154. package/shared/licenses.json +6781 -0
  155. package/shared/method-registry.json +236 -0
  156. package/shared/metric-registry.json +620 -0
  157. package/shared/model-aliases.json +7 -0
  158. package/shared/schemas/champollion-plugin.schema.json +206 -0
  159. package/shared/schemas/corpora-card.schema.json +957 -0
  160. package/shared/schemas/domain-taxonomy.schema.json +64 -0
  161. package/shared/schemas/external-results.schema.json +314 -0
  162. package/shared/schemas/human-services.schema.json +90 -0
  163. package/shared/schemas/language-card.schema.json +1308 -0
  164. package/shared/schemas/licenses.schema.json +155 -0
  165. package/shared/schemas/method-card.schema.json +412 -0
  166. package/shared/schemas/method-registry.schema.json +85 -0
  167. package/shared/schemas/metric-registry.schema.json +96 -0
  168. package/shared/schemas/metric-reliability.schema.json +178 -0
  169. package/shared/schemas/model-aliases.schema.json +27 -0
  170. package/shared/schemas/source-snapshot.schema.json +96 -0
package/LICENSE ADDED
@@ -0,0 +1,133 @@
1
+ # PolyForm Noncommercial License 1.0.0
2
+
3
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
4
+
5
+ ## Acceptance
6
+
7
+ In order to get any license under these terms, you must agree
8
+ to them as both strict obligations and conditions to all
9
+ your licenses.
10
+
11
+ ## Copyright License
12
+
13
+ The licensor grants you a copyright license for the
14
+ software to do everything you might do with the software
15
+ that would otherwise infringe the licensor's copyright
16
+ in it for any permitted purpose. However, you may
17
+ only distribute the software according to [Distribution
18
+ License](#distribution-license) and make changes or new works
19
+ based on the software according to [Changes and New Works
20
+ License](#changes-and-new-works-license).
21
+
22
+ ## Distribution License
23
+
24
+ The licensor grants you an additional copyright license
25
+ to distribute copies of the software. Your license
26
+ to distribute covers distributing the software with
27
+ changes and new works permitted by [Changes and New Works
28
+ License](#changes-and-new-works-license).
29
+
30
+ ## Notices
31
+
32
+ You must ensure that anyone who gets a copy of any part of
33
+ the software from you also gets a copy of these terms or the
34
+ URL for them above, as well as copies of any plain-text lines
35
+ beginning with `Required Notice:` that the licensor provided
36
+ with the software. For example:
37
+
38
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
39
+
40
+ ## Changes and New Works License
41
+
42
+ The licensor grants you an additional copyright license to
43
+ make changes and new works based on the software for any
44
+ permitted purpose.
45
+
46
+ ## Patent License
47
+
48
+ The licensor grants you a patent license for the software that
49
+ covers patent claims the licensor can license, or becomes able
50
+ to license, that you would infringe by using the software.
51
+
52
+ ## Noncommercial Purposes
53
+
54
+ Any noncommercial purpose is a permitted purpose.
55
+
56
+ ## Personal Uses
57
+
58
+ Personal use for research, experiment, and testing for
59
+ the benefit of public knowledge, personal study, private
60
+ entertainment, hobby projects, amateur pursuits, or religious
61
+ observance, without any anticipated commercial application,
62
+ is use for a permitted purpose.
63
+
64
+ ## Noncommercial Organizations
65
+
66
+ Use by any charitable organization, educational institution,
67
+ public research organization, public safety or health
68
+ organization, environmental protection organization,
69
+ or government institution is use for a permitted purpose
70
+ regardless of the source of funding or obligations resulting
71
+ from the funding.
72
+
73
+ ## Fair Use
74
+
75
+ You may have "fair use" rights for the software under the
76
+ law. These terms do not limit them.
77
+
78
+ ## No Other Rights
79
+
80
+ These terms do not allow you to sublicense or transfer any of
81
+ your licenses to anyone else, or prevent the licensor from
82
+ granting licenses to anyone else. These terms do not imply
83
+ any other licenses.
84
+
85
+ ## Patent Defense
86
+
87
+ If you make any written claim that the software infringes or
88
+ contributes to infringement of any patent, your patent license
89
+ for the software granted under these terms ends immediately. If
90
+ your company makes such a claim, your patent license ends
91
+ immediately for work on behalf of your company.
92
+
93
+ ## Violations
94
+
95
+ The first time you are notified in writing that you have
96
+ violated any of these terms, or done anything with the software
97
+ not covered by your licenses, your licenses can nonetheless
98
+ continue if you come into full compliance with these terms,
99
+ and take practical steps to correct past violations, within
100
+ 32 days of receiving notice. Otherwise, all your licenses
101
+ end immediately.
102
+
103
+ ## No Liability
104
+
105
+ ***As far as the law allows, the software comes as is, without
106
+ any warranty or condition, and the licensor will not be liable
107
+ to you for any damages arising out of these terms or the use
108
+ or nature of the software, under any kind of legal claim.***
109
+
110
+ ## Definitions
111
+
112
+ The **licensor** is the individual or entity offering these
113
+ terms, and the **software** is the software the licensor makes
114
+ available under these terms.
115
+
116
+ **You** refers to the individual or entity agreeing to these
117
+ terms.
118
+
119
+ **Your company** is any legal entity, sole proprietorship,
120
+ or other kind of organization that you work for, plus all
121
+ organizations that have control over, are under the control of,
122
+ or are under common control with that organization. **Control**
123
+ means ownership of substantially all the assets of an entity,
124
+ or the power to direct its management and policies by vote,
125
+ contract, or otherwise. Control can be direct or indirect.
126
+
127
+ **Your licenses** are all the licenses granted to you for the
128
+ software under these terms.
129
+
130
+ **Use** means anything you do with the software requiring one
131
+ of your licenses.
132
+
133
+ Required Notice: Copyright Curtis Forbes — Champollion (https://champollion.dev)
package/README.md ADDED
@@ -0,0 +1,387 @@
1
+ # Champollion
2
+
3
+ [![npm version](https://img.shields.io/npm/v/champollion.svg)](https://www.npmjs.com/package/champollion)
4
+ [![License: PolyForm Noncommercial 1.0.0](https://img.shields.io/badge/license-PolyForm--Noncommercial--1.0.0-blue.svg)](#license)
5
+
6
+ <!-- readme-i18n-banner-start -->
7
+ 🌐 **README translations** — *translated by champollion, of course:*
8
+ [Français](docs/README.fr.md) · [Deutsch](docs/README.de.md) · [Español](docs/README.es.md) · [Português](docs/README.pt.md) · [Nederlands](docs/README.nl.md) · [日本語](docs/README.ja.md) · [한국어](docs/README.ko.md) · [简体中文](docs/README.zh.md) · [ไทย](docs/README.th.md) · [Tiếng Việt](docs/README.vi.md) · [Filipino](docs/README.fil.md) · [العربية](docs/README.ar.md)
9
+ <!-- readme-i18n-banner-end -->
10
+
11
+ Translate your locale files with one command:
12
+
13
+ ```bash
14
+ npx champollion sync
15
+ ```
16
+
17
+ Champollion auto-detects your locale files, their format, and the target languages. It translates missing keys, skips what's already done, and writes the results. That's it.
18
+
19
+ > **Part of Champollion** — infrastructure for trustworthy machine translation
20
+ > across every language, source-available and free for noncommercial use (the
21
+ > evaluation harness and shared registries are open source). This CLI is the
22
+ > deployment end of a larger
23
+ > project that builds the test sets and the map showing who can translate what,
24
+ > how good each method is on each kind of text, and where the gaps still are. It
25
+ > runs on two kinds of benchmark: public benchmarks on open data (broad, cheap,
26
+ > every method welcome) and sovereign benchmarks — secret test sets that
27
+ > communities create, own, and control, and that we never see. The infrastructure
28
+ > is source-available and singly stewarded; the test sets and the methods for a
29
+ > community's language belong to that community. Built with communities, never
30
+ > scraped from them — they hold the keys. Every method is welcome, human and
31
+ > machine. Explore the network at
32
+ > [champollion.dev/docs/network](https://champollion.dev/docs/network/).
33
+
34
+ ## Why Not Just Script It Yourself?
35
+
36
+ You could write a quick script that loops through your English keys and calls Google Translate. Most developers do — it takes about 30 lines. Here's why it breaks:
37
+
38
+ - **No change detection.** When you update an English string, the translation stays stale forever. Champollion tracks every source value with SHA-256 hashes and re-translates only what changed.
39
+ - **No batching.** One API call per key means 200 keys = 200 round trips. Champollion batches intelligently (configurable, default 80 keys/batch for LLM, 128 for Google).
40
+ - **No quality gate.** Machine translation hallucinates, echoes the source back, or outputs in the wrong script. Champollion validates every translation before writing it — wrong-script, length inflation, and source echoes are caught and rejected.
41
+ - **No format awareness.** Hardcoded to JSON? Champollion handles JSON, TOML, YAML, and Hugo Markdown (frontmatter + body) with auto-detection.
42
+ - **No safety.** Champollion guards against prototype pollution, path traversal via crafted locale codes, and code block corruption during Markdown translation.
43
+
44
+ Champollion is the production version of that script.
45
+
46
+ > [!NOTE]
47
+ > **What Champollion translates.** Champollion targets **locale files and structured content** — JSON key-value pairs, TOML/YAML configuration, Hugo Markdown pages, XLIFF interchange documents. It is optimized for formal written text: UI strings, documentation, official communications, educational materials. It is not a chatbot, real-time speech translator, or general-purpose conversational AI. For each language pair, the translation method is configurable — from commercial APIs (Google Translate, DeepL) to community-developed plugins benchmarked through the [MT Eval Arena](https://champollion.dev/arena).
48
+
49
+ ## Quick Start
50
+
51
+ ```bash
52
+ npm install --save-dev champollion
53
+ ```
54
+
55
+ ### Get an API Key
56
+
57
+ Champollion needs a translation backend. Pick one:
58
+
59
+ | Provider | Key | Best for |
60
+ |----------|-----|----------|
61
+ | **OpenRouter** (recommended) | `OPENROUTER_API_KEY` | Content-heavy projects, Markdown, 200+ models |
62
+ | **OpenAI** | `OPENAI_API_KEY` | Direct GPT-4o access |
63
+ | **Anthropic** | `ANTHROPIC_API_KEY` | Direct Claude access |
64
+ | **Gemini** | `GEMINI_API_KEY` | Free tier available |
65
+ | **DeepL** | `DEEPL_API_KEY` | European languages, glossary support |
66
+ | **Google Translate** | `GOOGLE_TRANSLATE_API_KEY` | 130+ languages, high volume |
67
+
68
+ **Fastest start** (free): Sign up at [aistudio.google.com](https://aistudio.google.com/apikey) for a free Gemini key:
69
+
70
+ ```bash
71
+ export GEMINI_API_KEY=AI...
72
+ npx champollion sync --method gemini
73
+ ```
74
+
75
+ **OpenRouter** (200+ models): Sign up at [openrouter.ai](https://openrouter.ai), then:
76
+
77
+ ```bash
78
+ export OPENROUTER_API_KEY=sk-or-v1-...
79
+ npx champollion sync
80
+ ```
81
+
82
+ **Google Translate** alternative (key-value pairs only — no Markdown awareness):
83
+
84
+ ```bash
85
+ export GOOGLE_TRANSLATE_API_KEY=...
86
+ npx champollion sync --method google-translate
87
+ ```
88
+
89
+ > **Note**: If only `GOOGLE_TRANSLATE_API_KEY` is set, champollion auto-switches to Google Translate. No config change needed. Uses the REST API directly — no SDK, no service account, no `pip install`. Just the key.
90
+
91
+ That's it. For more control, create a config file:
92
+
93
+ ```bash
94
+ npx champollion init # guided wizard — walks you through registers, methods, and content
95
+ npx champollion init --yes --langs fr,de,ja # quick setup with specific languages and default registers
96
+ ```
97
+
98
+ Each language comes with **register presets** — pre-built tone/formality instructions tuned to its linguistic system (vouvoiement for French, Siezen for German, です/ます for Japanese, 해요체 for Korean). The init wizard lets you browse and pick presets, or pass `--yes` to accept the defaults.
99
+
100
+ ### Non-English Source
101
+
102
+ If your source language isn't English:
103
+
104
+ ```bash
105
+ champollion sync --source fr # CLI flag
106
+ ```
107
+
108
+ Or set it permanently in your config:
109
+
110
+ ```json
111
+ { "inputLocale": "fr" }
112
+ ```
113
+
114
+ ## What It Does
115
+
116
+ You handle the i18n framework (next-intl, i18next, Hugo). Champollion handles the translation files.
117
+
118
+ - **Multi-format** — JSON, TOML, YAML, Hugo Markdown (front matter + body), and XLIFF 1.2
119
+ - **Incremental** — Only translates what changed (SHA-256 hash tracking)
120
+ - **Cached** — Translation Memory stores previous results; re-running sync costs nothing for unchanged keys
121
+ - **Quality-gated** — Validates every translation: catches hallucinations, wrong-script output, source echoes, and length inflation
122
+ - **Content-aware** — LLM methods shield code blocks, shortcodes, links, and interpolation variables during Markdown translation
123
+ - **Pipeline tools** — `lint`, `audit`, `integrity`, `seo` for CI gates
124
+ - **XLIFF interop** — Export translations for professional review in CAT tools (memoQ, SDL Trados, Phrase), import them back
125
+ - **Minimal dependencies** — two runtime dependencies (better-sqlite3 for the bundled language database, CLDR locale names); no provider SDKs. Requires Node 20+
126
+
127
+ ## Beyond Google Translate
128
+
129
+ The quick start gets you running with an LLM or Google Translate. But Google Translate supports ~130 languages. There are over 7,000.
130
+
131
+ **Champollion's core idea: the translation method is configurable per language pair.** Use Google Translate for French, an LLM with morphological coaching for Plains Cree, and a community-hosted API for Quechua — all in the same project, all with the same CLI.
132
+
133
+ ```json
134
+ {
135
+ "version": 3,
136
+ "pairs": {
137
+ "en:fr": { "method": "google-translate" },
138
+ "en:ja": { "method": "llm" },
139
+ "en:crk": { "methodPlugin": "crk-coached-v1" }
140
+ }
141
+ }
142
+ ```
143
+
144
+ If you can figure out how to translate a language pair — through prompt engineering, community dictionaries, FST pipelines, or fine-tuned models — champollion lets you package that method as a plugin and deploy it alongside everything else.
145
+
146
+ > Born from translating a production website into Plains Cree, where no off-the-shelf API exists. The per-pair architecture isn't theoretical — it exists because one project needed Google Translate for French and a coached FST pipeline for an Indigenous language, running side by side in the same sync command.
147
+
148
+ The companion [MT Eval Harness](https://github.com/gamedaysuits/Champollion) lets you benchmark and compare translation approaches, then export working methods as champollion plugins. Anyone who speaks both languages can develop, test, and share a translation method — no proprietary platform required.
149
+
150
+ ### Choose Your Method
151
+
152
+ Champollion supports 10 translation methods. Each language pair can use a different method.
153
+
154
+ **LLM providers** — best for quality, Markdown-aware, coaching-compatible:
155
+
156
+ | Method | Key | What It Does |
157
+ |--------|-----|-------------|
158
+ | `llm` (default) | `OPENROUTER_API_KEY` | LLM via OpenRouter — 200+ models, auto-routing |
159
+ | `llm-coached` | `OPENROUTER_API_KEY` | LLM + grammar rules, dictionaries, style notes |
160
+ | `openai` | `OPENAI_API_KEY` | Direct OpenAI API (gpt-4o, gpt-4o-mini) |
161
+ | `anthropic` | `ANTHROPIC_API_KEY` | Direct Anthropic API (Claude Sonnet, Haiku, Opus) |
162
+ | `gemini` | `GEMINI_API_KEY` | Direct Google Gemini API (Flash, Pro) — free tier available |
163
+
164
+ **Traditional MT** — best for speed, cost, and high-volume key-value pairs:
165
+
166
+ | Method | Key | What It Does |
167
+ |--------|-----|-------------|
168
+ | `google-translate` | `GOOGLE_TRANSLATE_API_KEY` | Google Cloud Translation API v2 (130+ languages) |
169
+ | `deepl` | `DEEPL_API_KEY` | DeepL API with glossary support (30+ languages) |
170
+ | `microsoft-translator` | `MICROSOFT_TRANSLATOR_API_KEY` | Azure Cognitive Services Translator (100+ languages) |
171
+ | `libretranslate` | *(self-hosted)* | Self-hosted LibreTranslate (AGPL, free) |
172
+
173
+ **Infrastructure** — for custom or community-hosted endpoints:
174
+
175
+ | Method | Key | What It Does |
176
+ |--------|-----|-------------|
177
+ | `api` | *(per provider)* | Thin HTTP client for any REST endpoint |
178
+
179
+ ```bash
180
+ # Force a specific method for one run
181
+ champollion sync --method deepl
182
+
183
+ # Or configure per pair
184
+ ```
185
+
186
+ ```json
187
+ {
188
+ "pairs": {
189
+ "en:fr": { "method": "deepl" },
190
+ "en:ja": { "method": "openai", "model": "gpt-4o" },
191
+ "en:crk": { "methodPlugin": "crk-coached-v1" }
192
+ }
193
+ }
194
+ ```
195
+
196
+ > **Note**: Traditional MT methods (Google Translate, DeepL, Microsoft Translator, LibreTranslate) handle key-value pairs well but cannot safely translate Markdown content. For content-heavy projects, LLM methods are recommended — they explicitly shield code blocks, shortcodes, and interpolation variables.
197
+
198
+ ## Plugins
199
+
200
+ Plugins are pre-packaged translation recipes for specific language pairs. They're JSON manifests — not code — that tell champollion which method to use, with what settings, and what quality has been benchmarked.
201
+
202
+ ```bash
203
+ champollion plugin install ./french-formal-v1/ # install from directory
204
+ champollion plugin list # see installed plugins
205
+ champollion plugin remove french-formal-v1 # uninstall
206
+ champollion status # shows quality tiers + benchmarks
207
+ ```
208
+
209
+ See [the reference docs](https://champollion.dev/docs/reference/plugin-spec) for the manifest format.
210
+
211
+ ## Commands
212
+
213
+ | Command | Purpose |
214
+ |---------|---------|
215
+ | `init` | Interactive setup wizard (or `--yes` for quick defaults) |
216
+ | `sync` | Translate & sync all locale files |
217
+ | `serve` | Serve this project's translation stack over HTTP (api-method contract) |
218
+ | `watch` | Auto-sync on file changes |
219
+ | `audit` | Flag incomplete locales (CI gate) |
220
+ | `card` | Pretty-print a language card (`card <code>`, `--json` for raw) |
221
+ | `register-corpus` | Register an evaluation corpus: pick a license + exposure tier (local-only/private/public/sealed) |
222
+ | `seal-corpus` | Sealed-tier crypto verbs: `keygen` / `seal` / `open` (organizer-node bridge) |
223
+ | `submit` | Propose an index entry (review-gated) — prints a pre-filled GitHub issue |
224
+ | `lint` | Find hardcoded strings in source code |
225
+ | `status` | Show pair configuration, methods, registers, and quality tiers |
226
+ | `provenance` | Audit translation resource licensing |
227
+ | `wrap` | Auto-wrap hardcoded strings in `t()` calls (with undo) |
228
+ | `seo` | Generate hreflang, sitemap.xml, or JSON-LD schema |
229
+ | `integrity` | Check for placeholder corruption, encoding, and ICU plural completeness |
230
+ | `plugin` | Install, remove, or list method plugins |
231
+ | `fonts` | Download web fonts for PUA script converters |
232
+ | `tm` | Manage Translation Memory cache (stats, clear, seed, prune) |
233
+ | `xliff` | Export/import XLIFF 1.2 for professional translator review |
234
+ | `models` | List available models for a provider (`--method gemini`) |
235
+ | `verify` | Re-read written locale files and confirm translations are present and correct (CI gate) |
236
+ | `leaderboard` | Show the MT leaderboard (`--pair`, `--sort`, `--install N`) |
237
+ | `recommend` | Method guidance for a pair — availability + cited evidence (`--use`, `--json`) |
238
+ | `doctor` | System health check: cards, config, methods, and converters |
239
+
240
+ Run `champollion <command> --help` for detailed help on any command.
241
+
242
+ Full reference: [the reference docs](https://champollion.dev/docs/reference/cli)
243
+
244
+ ### Pre-commit gate
245
+
246
+ `champollion lint` is built to be a commit gate: it exits `1` when it finds hardcoded user-facing strings and `0` when clean (`--warn-only` reports without blocking). Wire it into a tracked hooks directory in your project:
247
+
248
+ ```bash
249
+ mkdir -p .githooks
250
+ printf '#!/bin/sh\nnpx champollion lint\n' > .githooks/pre-commit
251
+ chmod +x .githooks/pre-commit
252
+ git config core.hooksPath .githooks # once per clone
253
+ ```
254
+
255
+ Or trigger it from [lint-staged](https://github.com/lint-staged/lint-staged) so it only runs when source files are staged:
256
+
257
+ ```json
258
+ {
259
+ "lint-staged": {
260
+ "src/**/*.{js,jsx,ts,tsx}": "champollion lint"
261
+ }
262
+ }
263
+ ```
264
+
265
+ Keep `champollion sync` out of pre-commit — it makes network API calls, so it's slow at best and blocks commits offline at worst. Run it in CI or a pre-push hook instead, with `champollion audit` / `champollion verify` as the gate.
266
+
267
+ ## Configuration
268
+
269
+ Create `champollion.config.json` or run `champollion init`:
270
+
271
+ ```json
272
+ {
273
+ "version": 3,
274
+ "inputLocale": "en",
275
+ "localesDir": "./locales",
276
+ "model": "google/gemini-3.5-flash",
277
+ "pairs": {
278
+ "en:fr": { "qualityTier": "high" },
279
+ "en:ja": { "method": "google-translate" }
280
+ }
281
+ }
282
+ ```
283
+
284
+ | Option | Default | Description |
285
+ |--------|---------|-------------|
286
+ | `inputLocale` | `"en"` | Source language code |
287
+ | `localesDir` | `"./locales"` | Path to locale files |
288
+ | `contentDir` | `null` | Hugo content directory (enables Markdown translation) |
289
+ | `format` | `"auto"` | File format: `json`, `toml`, `yaml`, or `auto` |
290
+ | `model` | `"google/gemini-3.5-flash"` | Default model (OpenRouter slug). Direct providers resolve their own default at runtime. Run `champollion models --method gemini` to discover available models. |
291
+ | `defaultMethod` | `"llm"` | Default translation method (overridden by `--method` flag) |
292
+ | `batchSize` | `80` | Keys per translation batch |
293
+ | `pairs` | `{}` | Per-pair method, model, and quality overrides |
294
+
295
+ **Per-language overrides**: Each language has a [Language Card](https://champollion.dev/docs/reference/language-card-spec) — one of 50 curated cards containing register presets, formality systems, typography rules, and method support flags. Cards use a [two-tier architecture](https://champollion.dev/docs/concepts/architecture) (runtime + reference) for performance at scale. Scaffold a new card with `node scripts/generate-language-card.mjs <code>`. Use preset keys as shorthand, or write custom register text:
296
+
297
+ ```json
298
+ {
299
+ "languages": {
300
+ "fr": "casual-tu",
301
+ "ko": "formal-hapsyo",
302
+ "crk": {
303
+ "name": "Plains Cree",
304
+ "register": "SRO syllabics with grammatical precision.",
305
+ "model": "google/gemini-2.5-pro",
306
+ "batchSize": 5,
307
+ "maxRetries": 5,
308
+ "script": "Cans"
309
+ }
310
+ }
311
+ }
312
+ ```
313
+
314
+ **Zero-config mode**: No config file? Champollion auto-detects locale files, format, and target languages from your project.
315
+
316
+ Language values can be a preset key (e.g., `"casual-tu"`), custom register text, or an object (full control). Pair-level overrides in `pairs` take priority over language-level settings. Run `npx champollion init` to browse available presets for each language.
317
+
318
+ See the [CLI Reference](https://champollion.dev/docs/reference/cli) for framework-specific setup details.
319
+
320
+ ## CLI Output
321
+
322
+ When you run `sync`, champollion shows exactly what's happening:
323
+
324
+ ```
325
+ champollion v0.1.0
326
+
327
+ [INFO] Detected format: json (auto)
328
+ [INFO] Detected framework: Hugo
329
+ [INFO] Source: en.json (2,847 keys)
330
+ [INFO] Pairs: es-MX:llm, fr:deepl, it:llm
331
+ [INFO] Estimated translation cost:
332
+
333
+ Pair Method Keys Est. Cost
334
+ ──────── ────── ──── ─────────
335
+ en:es-MX llm 2847 ~$0.8400
336
+ en:fr deepl 2847 ~$0.5694
337
+ en:it llm 2847 ~$0.8400
338
+
339
+ Total: ~$2.2494
340
+
341
+ [INFO] es-MX.json — 2,847 missing
342
+ ████████████████████████████████ 2,847/2,847 keys
343
+ [INFO] fr.json — 2,847 missing
344
+ ████████████████████████████████ 2,847/2,847 keys
345
+ [OK] Synced 5,694 keys total.
346
+ ```
347
+
348
+ The progress bar updates in-place as each batch completes (~80 keys per update). Framework detection shows `Hugo` when `contentDir` is set. Format detection distinguishes `(auto)` from `(config)` to clarify how the format was resolved.
349
+
350
+ **Output modes**: `--quiet` suppresses informational output (errors and warnings only). `--json` emits machine-readable NDJSON for CI/CD pipelines.
351
+
352
+ ## Hardening
353
+
354
+ - **Exponential backoff** — 3 retries with jitter on 429/5xx errors
355
+ - **30s request timeout** — AbortController prevents hanging
356
+ - **Response validation** — only accepts keys that were sent for translation
357
+ - **Quality gate** — catches hallucination loops, wrong-script output, length inflation, and source echoes
358
+ - **Retry cascade** — on JSON parse failure, retries batch → half-batch → individual keys (budget-capped via `maxRetries`)
359
+ - **Translation Memory** — `.champollion/tm.json` caches translations keyed by source text + locale + method; unchanged keys are served from cache on subsequent syncs, eliminating redundant API calls
360
+ - **Prompt caching** — system/user message split enables provider-level caching, reducing token cost across batches
361
+ - **Terminology enforcement** — coached translations are verified against dictionary terms after the LLM responds
362
+ - **Prototype pollution guard** — blocks `__proto__`, `constructor`, `prototype`
363
+ - **Path containment** — file writes validated to stay within configured directories
364
+ - **Block protection** — code blocks, shortcodes, HTML shielded during content translation
365
+ - **Fail-loud architecture** — translation failures always throw with actionable error messages, never silently write garbage
366
+ - **Post-sync verification** — `verify` command re-reads written files and confirms translations are present, correct script, and placeholder-intact
367
+ - **Partial success** — one failed batch doesn't block the rest
368
+
369
+ ## Testing
370
+
371
+ ```bash
372
+ npm test # all tests
373
+ npm run test:unit # core sync pipeline
374
+ npm run test:redteam # adversarial edge cases
375
+ npm run test:format # TOML/YAML adapters
376
+ npm run test:content # Markdown content parser
377
+ npm run test:hugo # full Hugo E2E
378
+ npm run test:lint # hardcoded string detection
379
+ npm run test:pairs # pair graph resolution
380
+ npm run test:methods # translation method suite
381
+ ```
382
+
383
+ **Minimal dependencies** — see above.
384
+
385
+ ## License
386
+
387
+ PolyForm Noncommercial 1.0.0. The Champollion CLI is source-available — free to install, use, and modify for noncommercial purposes (research, education, community work) under the [PolyForm Noncommercial License 1.0.0](LICENSE); commercial use requires the licensor's permission. The published `champollion` npm package is PolyForm-Noncommercial-1.0.0; `cli/LICENSE` is the authoritative license for the distributed package. The companion MT Eval Harness and specs are open source, licensed AGPL-3.0-or-later — with a §7 eval-standard-plugin exception — at the public [harness repository](https://github.com/gamedaysuits/Champollion).