Internationalization¶
The documentation treats English and Simplified Chinese as reviewed canonical
sources. Every other enabled locale is a generated derivative. The language
registry, source routing, model configuration, and API limits live in
i18n/config.toml.
1. Language coverage and source routing¶
The registry intentionally enables a focused set of 12 site locales. It covers all six United Nations official languages: Arabic, Chinese, English, French, Russian, and Spanish. It additionally covers Japanese, Korean, and Traditional Chinese for East Asia, plus German, Italian, and Portuguese for Europe. English and Simplified Chinese are canonical, so 10 locales are machine translated.
Japanese, Korean, and Traditional Chinese use Simplified Chinese as their source. All other generated locales use English. Source selection is explicit per locale; the translator never guesses from a locale name or from document characters.
Adding a locale requires matching entries in i18n/config.toml and the MkDocs
i18n language list. The documentation audit rejects inconsistent registries.
2. Canonical-document contract¶
Every MkDocs page has an English file and a .zh-CN.md file. A pull request,
push to main, or manually dispatched quality run that changes one canonical
version must include its counterpart in the checked commit range. The quality
workflow checks:
- canonical pairs and changed-pair coupling;
- heading-level and code-fence parity;
- local links and source references;
- fixture and test inventories;
- a strict build of every configured locale.
Canonical prose may be written manually or with AI assistance, but it must be committed and reviewed as ordinary source. The translation API is never called from a pull-request workflow.
3. Heading numbering and fragment stability¶
Markdown source stores descriptive heading text without outline numbers.
During every MkDocs build, scripts/mkdocs_heading_numbers.py adds page-local
numbers to H2–H6 headings. User Guide pages use lowercase letters at H2
(a., b.) and letter-plus-decimal descendants (a.1, a.1.1); other pages
retain decimal page outlines. Separately, the left User Guide navigation uses
hierarchical decimal numbers such as 1.1. H1 page titles and top-level
navigation sections remain unnumbered. Generated numbers are presentation
metadata: moving a section changes its visible number without changing its
fragment identifier.
The build hook makes every heading identifier explicit before adding the
visible number. i18n/legacy-heading-anchors.json retains aliases for fragments
that were published before stored outline numbers were removed. Do not edit
that generated compatibility map casually, and do not add manual outline
numbers back to canonical or generated Markdown; the documentation audit
rejects them.
4. Generated-document contract¶
Generated pages use MkDocs suffix mode, such as index.fr.md or
guide/configuration.ja.md. Each page contains deterministic front matter
recording:
- the canonical source locale and path;
- the source SHA-256 digest;
- the resolved model and prompt version;
- that the page is a machine translation.
i18n/manifest.json additionally records output digests and translation-input
fingerprints. A page becomes stale when its source, glossary, prompt, model, or
generated output changes. The translator only requests stale units unless a
full rebuild is explicitly requested.
Translated headings keep their natural localized slugs and receive hidden aliases for the canonical source slugs. Because Markdown link destinations are otherwise protected from model changes, these aliases keep same-page and cross-page fragment links valid in every locale. The aliases can be refreshed offline without another translation API call.
Generated files must not be edited manually. The main-branch translation
workflow regenerates them and checkpoints each completed locale as one commit
on a generated-only branch derived from the exact quality-validated SHA. A
later run can verify and reuse that branch, so an interruption only discards
the locale still in progress. main remains unchanged until the workflow has
run the required generated-language audit, complete test suite, and strict
all-locale build. It then verifies that main has not advanced, promotes the
validated checkpoint by one fast-forward push, and deploys that same validated
site artifact.
5. Protected Markdown and prompt contract¶
Before an API request, the translator replaces front matter, fenced code, inline code, link destinations, HTML tags, and bare URLs with immutable placeholders. A response is rejected if any placeholder is missing, duplicated, invented, or moved outside the recoverable output contract.
The prompt also requires identical heading levels and code-fence languages. The implementation independently verifies those properties after restoring the protected content. Translation output must be a JSON object; prose around the JSON, empty content, abnormal completion reasons, or incompatible schemas are failures.
The Markdown and navigation-catalog prompts are versioned under
i18n/prompts/. i18n/glossary.json carries stable product and command
terminology.
6. Model configuration and credentials¶
The default model is configured as deepseek-v4-flash. The implementation does
not branch on that name. A future model change only requires updating
i18n/config.toml, passing --model, or setting the
DEEPSEEK_TRANSLATION_MODEL workflow variable. The resolved model is recorded
in every generated page and manifest entry.
GitHub Actions reads the API credential only from the repository secret named
DEEKSEEK_API_KEY. It is injected only into the generation step when the
offline plan reports pending API-backed units. It is never available to
untrusted pull-request code or no-API planning, cleanup, and validation steps.
Authentication values are never written to logs, generated files, artifacts,
or the manifest.
7. Page notice and language preference¶
Machine-generated pages receive a localized warning at render time. The warning identifies the page as an AI translation, links to the authoritative English or Simplified Chinese source, and links to a pre-filled translation issue. It is not part of the translated Markdown and does not create a table of contents entry.
On a visitor's first root-page visit, the site compares navigator.languages
with the configured language alternatives. A compatible locale is selected
when available. A manual language selection is saved locally and takes
precedence on later visits.
8. Maintainer commands¶
Show the number of pending translation units without making network calls:
uv run python scripts/translate_docs.py --plan
Verify that every generated page and catalog is current:
uv run python scripts/translate_docs.py --check
uv run python scripts/audit_docs.py --machine-mode required
Refresh stable source-heading aliases without API calls:
uv run python scripts/translate_docs.py --refresh-heading-anchors
Force a complete regeneration with an explicit model:
DEEKSEEK_API_KEY=... uv run python scripts/translate_docs.py \
--force --model deepseek-v4-flash
The automated workflow uses the repository secret instead of placing a key on the command line.