Bilingual documentation
English | 中文
This repo's documentation is read by people and agents both inside and outside the company, so every document in scope is maintained in English and Simplified Chinese. This page defines the pairing contract, enforcement gate, scope, and exclusions; translation-rules.md defines how to translate; terminology.md is the terminology source of truth. The committed agent workflow lives in .agents/skills/dsh-translate-docs.
The pairing contract
-
Both languages carry equal authority. A document may be authored and reviewed in either language first — a Chinese-first Agent Note is as legitimate as an English-first one — and the counterpart is translated from it. Neither file outranks the other; what binds them is that they must say the same thing.
-
A pair is three sibling files. The English
foo.md, the Chinesefoo.zh.md, and a consistency recordfoo.i18n.yaml, all in the same directory. No locale directories, no separate translation repo, no interleaved bilingual files. Pairs merge whole: a PR never lands one language without the other two files. -
The consistency record.
foo.i18n.yamlholds the full git blob hash of each side as of the last time the two were confirmed to say the same thing:foo.md: 3f786850e387550fdab836ed7e6dc881de23001b foo.zh.md: 89e6c98d92887913cadf06b2adb97f26cde4849bBlob hashes, not commit hashes, so the record is computable for files edited in the same PR (
git hash-object foo.md) and consistency is a pure content comparison. The recorded hash also recovers the exact last-confirmed text of either side (git cat-file -p <hash>), so an out-of-sync pair is updated by diffing the edited side against its last-confirmed state and patching the counterpart minimally — never by re-translating whole files. After bringing the pair back in line,pnpm run verify-translation-pairing --writere-records both hashes; that yaml diff is the reviewable act of confirming consistency. -
Language switcher. Both files link to each other immediately after their H1 heading: the English file carries
English | [中文](foo.zh.md)and the Chinese file carries[English](foo.md) | 中文. -
Structure mirrors the counterpart. Heading depths and order, list kinds, ordered-list starts, list item counts, table row and column counts, link targets, and verbatim code blocks match one to one across the pair — see translation-rules.md for the full preservation rules. Existing Markdown gates apply to
.zh.mdfiles unchanged (verify-md-wrap,verify-md-links).
The gate: verify-translation-pairing
pnpm run verify-translation-pairing (part of doc-sync, which contributors run locally for documentation changes and CI runs exhaustively) enforces the contract mechanically:
- Every document in scope has a complete pair. README discovery is case-insensitive on the basename, so
missions/readme.mdis in scope alongside the other documentation roots. - Every pair artifact that exists at all is complete and consistent: all three files present, each side's current blob hash equals the recorded one (editing either side without re-confirming the pair goes red), both sides carry the language switcher, and the structural signatures match in order — heading depths, verbatim code blocks (info string and content), table row and column counts, list kinds, ordered-list starts, item counts, and every link target apart from the switcher.
- Files listed as
excludedhave no.zh.mdand no.i18n.yamlat all. Frozen Agent Notes under.agents/notes/archived/are outside this evolving gate; their dedicated verifier requires and seals the complete existing triplet instead.
Source-oriented code gates consume an exact .zh.md fence sequence as a derivative of its unsuffixed sibling instead of compiling or manifesting the same code twice. The sequence must match in length, order, fence kind, and byte-exact body; otherwise both copies remain independently checked and the pairing gate reports the structural mismatch.
pnpm run verify-translation-pairing --list prints the current pairing state of every document in scope — missing, out-of-sync, or ok. It never fails; missing and out-of-sync rows identify violations that the normal check rejects.
The practical rule this gate creates: when a PR edits either side of a paired document, the same PR updates the counterpart and re-records the pair (run the dsh-translate-docs skill, then --write), exactly like the repo's existing doc-sync rule for code and READMEs. A PR that leaves a pair out of sync goes red in CI.
The gate's limit, stated plainly: a green gate means the pair was confirmed consistent at these exact contents, not that the confirmation was sound. It checks hashes and shape; it cannot judge whether the two sides actually say the same thing, or whether the wording is accurate, well-termed, and natural — that is the reviewer's half of the contract, per translation-rules.md. A re-recorded pair with a sloppy counterpart passes the gate; it must not pass review.
Scope and exclusions
Scope: every non-vendor README, plus every active document under .agents/notes/**, docs/**, and python/**. README matching is case-insensitive on the basename and covers future directories without another manifest edit. Dependency and ignored build-output trees and the frozen .agents/notes/archived/ tree are discovery exclusions, not evolving translation source.
Excluded (never paired, and the gate rejects a .zh.md or .i18n.yaml for them):
docs/cordis-catalog/,docs/tool-catalog/,docs/config-catalog.md,docs/persistence-catalog.md,docs/module-graph.md,docs/agent-lifecycle.md,docs/capability-seams.md,docs/event-producer-consumer.md,docs/graph-atlas.md, anddocs/tool-execution-pipeline.md— generated files; their generators emit English only today, so a hand-written translation would go stale on every regeneration. The planned follow-up is to teach the generators to emit Chinese alongside English, at which point these leave the exclusion list.docs/AGENTS.md,.agents/notes/**/AGENTS.md, and theirCLAUDE.mdinstruction symlinks — agent instructions, maintained in English only like the rootAGENTS.md.docs/i18n/terminology.mdand style-samples.md — both are bilingual by construction.- translation-prompt.md — the automated pipeline's prompt template; its body is machine-consumed verbatim, so a paired translation would change pipeline behavior.
.agents/notes/archived/— frozen historical triplets.verify-archived-agent-notesvalidates their completeness and content seals; translation maintenance must never rewrite them.
Universal requirement: every current or future document in scope must merge as a complete bilingual pair. scripts/translation-pairing.manifest.json contains only explicit exclusions; there is no per-file rollout list, date cutoff, or README-specific policy class.
Division of labor
Counterparts here are produced by an agent running dsh-translate-docs and reviewed by a human — inference is cheap here, review attention is the scarce resource. The gate checks pair completeness, recorded hashes, switchers, and its documented structural signature. Review still owns translation quality, terminology, and structural requirements that the signature does not encode. The prompt contract is executable: scripts/translation-prompt.ts renders the committed template (terminology injected; the template carries its own calibrated rules) into either direction and parses the three-section response, while verify-translation-prompt exercises both render directions and the checked-in example in doc-sync.