# Translate documentation {#root}

@status:doc/work @audience:author

[p01] A translation is a separate package in the same shape as the original: same pages, same section names, same examples by reference, in another language. This page creates one and explains what makes it official.

[p02]
```prompt
Create the package org.acme/notes-flow-docs-ru in the current VibeVM project, as an in-tree package under vibevm/vibepacks/, as the Russian translation of org.acme/notes-flow-docs. Mirror its page tree file for file, keep every anchor and block, and replace each example with a reference to the source example. Write the manifest with [translates] and the same [[documents]] subject. Run vibe doc check --translations.
```

- needs: the vibevm skill installed for your agent; the source documentation package in the same project

outcome: the translation has the same files and anchors as the source, `[i18n] canonical = "ru"`, `[translates]` pointing at the source, and `vibe doc check --translations` reports no structural difference

- assert: `grep -q "canonical = \"ru\"" vibevm/vibepacks/org.acme/notes-flow-docs-ru/v0.1.0/vibe.toml`
- assert: `vibe doc check --translations --path vibevm/vibepacks/org.acme/notes-flow-docs-ru/v0.1.0`

## What happens {#what-happens}

[p03] The agent copies the source's page tree and translates the prose of each block in place, without adding or removing a block. It replaces every `example` with `example ref="<id>"` pointing at the source's example. It sets the package language, names the source in `[translates]` and the same [subject](../glossary/index.xml#subject) in `[[documents]]`. `vibe doc check --translations` then compares the two trees: the same paths, the same [anchors](../glossary/index.xml#anchor), the same number and kinds of blocks; a difference is an error. The site, seeing a `translates` edge from a package in the source's group named `<source>-ru`, shows the translation as official and offers it in the language selector.

> [p04] A translation MUST mirror the source tree file for file: the same paths, the same anchors, the same fact identifiers, the same number and kinds of blocks. Adding or removing an anchor is forbidden. A set difference of anchors is a check error, not a warning.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-MIRROR>

## The manifest {#the-manifest}

[p05] The language of the package is the existing `[i18n] canonical` field, a BCP-47 tag in lower case; there is no separate language field. `[translates]` names the source and a version range; `[[documents]]` repeats the source's subject, and vibe checks that the two agree.

> [p06] The language of a `doc` package is the existing `[i18n].canonical` of PROP-003 §2.7 (default `en`); there is no separate `lang` field. `[i18n].available` of a `doc` package is empty by construction: a translation is another package.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-LANGUAGE-FIELD>

> [p07] The `documents` of a translation MUST equal the `documents` of its source; `vibe check` verifies it.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-DOCUMENTS-MATCH>

[p08] The name `<source>-<lang>` in the source's group is what makes the translation official by default. A translation from another group is found and shown as a community translation, with its publisher.

> [p09] An **official** translation is one that declared `translates` on the source and is published by the **same group** as the source under the name `<docname>-<lang>`; everything else is a community translation (§6).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-OFFICIAL-TRANSLATION>

[p10] The default name of a translation is the documentation's name with the language tag in lower case, `vibevm-docs-ru` or `vibevm-docs-pt-br`, in the same group.

> [p11] The official-by-default translation of a documentation `<group>/<docname>` into a language `<lang>` is named `<group>/<docname>-<lang>`, where `<lang>` is a BCP-47 tag in lower case (`ru`, `pt-br`, `zh-hans`).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#COMPANION-TRANSLATION-NAME>

## The rules of a translation {#the-rules}

[p12] A translation follows the source block for block, not sentence for sentence: within a block the translator writes what a native editor would write, replaces a joke with one that works in the language or drops it, and follows the glossary of the translation. It never authors examples: an example's output is checked once, on the source, and a translation points at it. It never adds an anchor, because a link into the source must land on the same block in every language, which is also what lets the reader switch languages without losing the place.

> [p13] A translation MUST NOT author examples: it uses `example ref="<id>"` pointing at the source's example, so that command output is checked once, on the source (PROP-045 `##ROW-DOCVOCAB-EXAMPLE-REF`).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-EXAMPLE-REF>

> [p14] **Switching the language keeps the place.** The language selector leads to the same page in the other language **with the same fragment** (`#pNN` or `#id`), which the block-for-block mirror of §5 makes possible. When the page does not exist in the chosen language, the site serves the source language under the chosen language's address as a statically materialised fallback (`<html lang>` of the source, `rel=canonical` to the source page, `noindex`), shows a bilingual notice «this page is only in … so far» once per session, and rewrites internal links so navigation stays in the chosen language. The chosen language is remembered in the cookie `lang` for 365 days — the same name the landing uses, so the domain root and `/doc/` remember one choice.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#READER-LANGUAGE-SWITCH-KEEPS-PLACE>

[p15] Rules quoted from a [specification](../glossary/index.xml#specification) stay in the specification's language, marked as such; translating normative text is not part of a documentation translation.

> [p16] Normative specifications stay in the specification's language: a `rule` shows the rule's text in the source language with a mark; translating normative text is outside this wave.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-NORMATIVE-STAYS>

## When the source moves {#staleness}

[p17] A translation records no revision or hash of the source. When the source changes, the structural check still passes as long as the shape did, and whether the translation's meaning lags is a human's question, answered at the periodic reconciliation and shown on the page as the date it was last read. The site shows a page that has no translation yet in the source language under the translation's address, with a note, never as missing.

> [p18] A translation stores neither a revision nor a hash of the source page (§14: a «since then» comparison needs a history the product does not keep). `vibe doc check --translations` verifies structure only — paths, anchors, count and kinds of blocks; whether the adaptation lags in meaning is a human's question at full reconciliation, and the site shows the adaptation's last read-aloud date from `reviews.toml`.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-NO-REVISION>

## Edge cases and rules {#edge-cases}

[p19] Sidecar files inside the source package, `README.ru.md` beside `README.md`, are how specifications carry translations; documentation does not use them, because a manual's translation has its own author and its own rhythm.

> [p20] **Amendment 2026-09-11 ([PROP-057 §5](../../common/PROP-057-documentation-packages-and-site.xml)).** Packages of kind `doc` reuse this section's BCP-47 tags, the `[i18n].canonical` field as the package's own language, and the preference chain of §2.7.2–§2.7.3 (`I18nDecl`, `project_preference_chain`, the lockfile's `language_chain`) — but they do **not** take part in the sidecar layout of §2.7.1: a translation of documentation is a **separate package** of kind `doc`, named `<documentation-name>-<lang>` in the same group for the official-by-default case, declaring the source through the `[translates]` table and mirroring its tree file for file. `[i18n].available` of a `doc` package is therefore empty by construction, and the coverage check of §2.7 that expects sidecars does not apply to it. The reason is ownership: a translation has its own author, its own rhythm and its own officiality, and the unit of ownership in this project is the package.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003#I18N-DOC-PACKAGES>

[p21] A translation inherits the source's images unless it declares its own.

> [p22] A translation inherits the images of its source unless it declares its own.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#CARD-TRANSLATION-INHERITS>

