Files
deepseek-harness/docs/i18n
Ziya 4d89bb3e74 docs: bilingual docs contract, translation skill, and pairing gate
Establish EN->ZH bilingual documentation for the README and docs tree:

- docs/i18n/README.md — the pairing contract: sibling foo.md <-> foo.zh.md,
  English canonical, blob-hash source fingerprints, language switchers,
  scope/exclusions, and a manifest-driven rollout ratchet.
- docs/i18n/translation-rules.md — how to translate: faithfulness, structure
  preservation, terminology discipline over docs/i18n/terminology.md, and
  typography rules grounded in MDN/K8s/Vue/clreq conventions.
- .agents/skills/dsh-translate-docs — the committed agent workflow, following
  the dsh-code-review pattern of deferring to docs as sources of truth.
- scripts/verify-translation-pairing.ts + manifest — a doc-sync gate: required
  pairs exist; every existing .zh.md is fresh (fingerprint = current source
  blob), switcher-linked, structure-matched, and non-orphaned; excluded
  (generated) docs stay unpaired. --list prints the translation work list.
- RFC (implemented/process) recording the decision and the alternatives.
- Dogfood: README.zh.md and the two i18n docs translated under their own rules.

Gates: doc-sync green including the new gate; red/green proven for stale
fingerprint, orphan, and excluded-file violations.
2026-07-02 23:12:25 -07:00
..

Bilingual documentation

English | 中文

This repo's documentation is read by people and agents both inside and outside the company, so the README and the docs tree are maintained in English and Simplified Chinese. This page defines the pairing contract, the enforcement gate, and the rollout policy; 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

  • English is canonical. Every document is authored in English at its existing path, and the Chinese file is derived from it — translation flows EN → ZH only. A content change starts in the English file; the Chinese file never carries information its English source lacks.

  • Paired sibling files. The translation of foo.md is foo.zh.md in the same directory. No locale directories, no separate translation repo, no interleaved bilingual files.

  • Source fingerprint. The FIRST line of every .zh.md file is an HTML comment recording the repo-relative path and the git blob hash (first 12 hex digits of git hash-object) of the English source it was translated from:

    <!-- i18n-source: docs/architecture.md@8a9f0c21d3e4 -->
    

    A blob hash, not a commit hash, so the fingerprint is computable for an English file edited in the same PR (git hash-object docs/foo.md), and so staleness is a pure content comparison. The fingerprint is also the update tool: git cat-file -p <hash> recovers the exact source text a stale translation was based on, and git diff <hash> <current-blob> isolates what changed so the translation can be updated minimally instead of re-translated.

  • 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 source. Heading hierarchy, list shape, table columns, and code blocks match the English file one to one — see translation-rules.md for the full preservation rules. Existing Markdown gates apply to .zh.md files unchanged (verify-md-wrap, verify-md-links).

The gate: verify-translation-pairing

pnpm run verify-translation-pairing (part of doc-sync, so CI and the pre-push hook run it) enforces the contract mechanically:

  1. Every English file listed as required in scripts/translation-pairing.manifest.json has a .zh.md sibling.
  2. Every existing .zh.md file — required or not — passes all of: its English source exists (no orphans), its fingerprint matches the source's current blob hash (no stale translations), both sides carry the language switcher, and its fenced-code-block and heading counts equal the source's.
  3. Files listed as excluded have no .zh.md sibling at all.

pnpm run verify-translation-pairing --list prints the current translation state of every document in scope — missing, stale, or ok — and is the work list for translation batches. It never fails; it reports.

The practical rule this gate creates: when a PR edits an English document that has a .zh.md sibling, the same PR updates the translation (run the dsh-translate-docs skill), exactly like the repo's existing doc-sync rule for code and READMEs. A PR that leaves a translation stale goes red in CI.

Scope, exclusions, and rollout

Scope: the root README.md and everything under docs/**. Package READMEs (packages/**) join the scope in a later batch.

Excluded (never paired, and the gate rejects a .zh.md for them):

  • docs/cordis-catalog/, docs/tool-catalog/, docs/module-graph.md — generated files; their generators emit English only, so a translation would go stale on every regeneration.
  • docs/AGENTS.md — agent instructions, maintained in English only like the root AGENTS.md.
  • docs/i18n/terminology.md — the terminology table is itself bilingual by construction.

Rollout: the required list in the manifest is the enforcement frontier, not the goal. The goal is full bilingual coverage of the scope. Translation lands in reviewable batches (core entry docs, cookbook, RFCs, postmortems, …); each merged batch adds its files to required, so the gate ratchets forward and never regresses. Documents not yet in required are backlog — visible in --list — but any translation that already exists is held to the full contract regardless of the list.

Division of labor

Translations 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 exists so that neither the agent nor the reviewer has to remember the contract: pairing, freshness, and structure are checked mechanically, and review attention goes to translation quality and terminology, where human judgment is the whole point.