Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Generated
uv.lock linguist-generated=true
i18n/*/pages/** linguist-generated=true
i18n/*/state.json linguist-generated=true
57 changes: 57 additions & 0 deletions .github/ISSUE_TEMPLATE/translation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: 🌐 Translation problem
description: Report a wrong, awkward, or misleading passage in a translated docs page
labels: ["translation"]

body:
- type: markdown
attributes:
value: |
The translated docs are machine-generated from the English pages; https://py.sdk.modelcontextprotocol.io/translations/ explains how.
Fixes never go into the translated text directly. They go into that language's glossary or style guide under `i18n/`, so you can also open a PR there instead of an issue.

- type: dropdown
id: language
attributes:
label: Language
options:
- Simplified Chinese (zh-CN)
- Japanese (ja)
- Korean (ko)
- Brazilian Portuguese (pt-BR)
validations:
required: true

- type: input
id: page
attributes:
label: Page URL
description: The translated page where you found the problem.
placeholder: https://py.sdk.modelcontextprotocol.io/ja/servers/tools/
validations:
required: true

- type: textarea
id: passage
attributes:
label: The passage
description: Quote the translated text that's wrong, and the English it corresponds to if you have it.
validations:
required: true

- type: textarea
id: problem
attributes:
label: What's wrong, or how it should read
description: A wrong term, awkward phrasing, meaning that drifted from the English, tone that's off. If you know the better rendering, give it.
validations:
required: true

- type: dropdown
id: native-speaker
attributes:
label: Are you a native or fluent speaker of this language?
options:
- "Yes"
- "No"
validations:
required: true
2 changes: 2 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ on:
# docs pages include their code blocks from these files via `--8<--`, so a
# change here changes the rendered site even when no .md file moves.
- docs_src/**
# the translated pages and the language registry feed the language sites
- i18n/**
- mkdocs.yml
- src/mcp/**
- src/mcp-types/**
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/docs-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ on:
paths:
- docs/**
- docs_src/**
- i18n/**
- mkdocs.yml
- scripts/docs/**
- pyproject.toml
Expand Down Expand Up @@ -137,7 +138,17 @@ jobs:
# /preview-docs, still build with MkDocs. Both arms must write the site
# to site/. Keep the detection in sync with build_site() in
# scripts/build-docs.sh.
- run: |
#
# DOCS_SITE_URL is the preview's Cloudflare branch-alias host (deploy
# publishes to `--branch=pr-<N>`, served at pr-<N>.<project>.pages.dev),
# so the absolute links the build bakes (language switcher, language
# sites' links into the English API reference) point at the preview
# instead of production; empty when no Pages project is configured, which
# makes build.sh fall back to the production site_url.
- env:
DOCS_SITE_URL: >-
${{ vars.CLOUDFLARE_PAGES_PROJECT && format('https://pr-{0}.{1}.pages.dev', needs.authorize.outputs.pr_number, vars.CLOUDFLARE_PAGES_PROJECT) || '' }}
run: |
if [ -f scripts/docs/build.sh ]; then
bash scripts/docs/build.sh
else
Expand Down
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,13 @@ venv.bak/
# documentation
/site
/.worktrees/
# Generated at build time by scripts/docs/ (the API reference tree and the
# concrete Zensical config spliced from mkdocs.yml).
# Generated at build time by scripts/docs/ (the API reference tree, the
# concrete Zensical configs spliced from mkdocs.yml, and the staged
# per-language docs trees).
/docs/api/
/.build/
/mkdocs.gen.yml
/mkdocs.*.gen.yml

# mypy
.mypy_cache/
Expand Down
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ repos:
"/tool/markdown/lint",
]
types: [markdown]
# Machine-translated pages are generated artefacts: corrections flow
# through i18n/<code>/{instructions.md,glossary.json}, never through
# hand or linter edits to the pages themselves.
exclude: ^i18n/[^/]+/pages/

- repo: local
hooks:
Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ pre-commit run --all-files
- Add type hints to all functions
- Include docstrings for public APIs

## Documentation and Translations

Documentation contributions are English only: the pages under `docs/` are the source of truth, and the translated documentation sites are generated from them, guided by the per-language style guides and glossaries under `i18n/<lang>/`. Never edit the generated pages under `i18n/<lang>/pages/`—the next translation run overwrites them. To fix a translation, change that language's `instructions.md` or `glossary.json` (or the English page, if that's where the problem is), and the fix carries into every future run. See [`i18n/README.md`](i18n/README.md) for the details.

## Pull Requests

By the time you open a PR, the "what" and "why" should already be settled in an issue. This keeps reviews focused on implementation.
Expand Down
24 changes: 24 additions & 0 deletions docs/translations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Translations

This documentation is written in English. To make it useful to more people, we also publish it in a few other languages. Those editions are machine-translated, and this page explains what that means for you and how to help improve them.

## What's available

Translated documentation is currently a **preview**: it covers a growing subset of the pages, published in four languages — Simplified Chinese, Japanese, Korean and Brazilian Portuguese. Pick one from the language switcher at the top of any page.

Every translated page opens with a note saying it was machine-translated and linking to its English original. The API reference is not translated: every language site links to the single English one.

## English is the source of truth

If a translated page and its English original disagree, the English page is correct. Two situations are called out on the page itself:

- A page that hasn't been translated yet shows the English text, with a note saying so.
- A page whose English original changed after it was translated carries a warning that it may be behind, until the translation catches up.

## How the translations are made

Translated pages are generated by a tool in this repository from the English pages under `docs/`, guided by two human-written inputs per language: a style guide (register, tone, typography, how to handle jokes and idioms) and a glossary (which terms stay in English, and the required and forbidden renderings for the rest). The generated text is never edited by hand. Every improvement goes into those inputs instead, so it survives the next time the pages are regenerated.

## Reporting a translation problem

Found a wrong term, an awkward sentence, or a translation that says something the English doesn't? [Open a translation issue](https://github.com/modelcontextprotocol/python-sdk/issues/new?template=translation.yaml) with the language, the page and the passage; reports from native speakers are especially valuable, and maintainers track these with the `translation` label. If you know the fix, propose it directly as a pull request against that language's style guide or glossary under [`i18n/`](https://github.com/modelcontextprotocol/python-sdk/tree/main/i18n) — the correction then shows up on every affected page the next time the translations are regenerated. Problems with the English text itself are fixed in the pages under `docs/`, like any other documentation change.
72 changes: 72 additions & 0 deletions i18n/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Documentation translations

The English pages under `docs/` are the source of truth. This directory holds
what steers their machine translation (human-authored) and the generated
result; the public-facing explanation is [`docs/translations.md`](../docs/translations.md).

- `languages.yml` — the language registry (one entry per translated site,
served at `/<code>/`), the pages that stay English, the model IDs, and the
English text of the notices staged onto every translated page.
- `general-prompt.md` — the translation rules shared by every language.
- `<code>/instructions.md` — register, voice, humour and typography for one
language. Human-authored.
- `<code>/glossary.json` — the termbase for one language: terms that stay in
English, required renderings, and banned ones (`"enforce": true` makes a ban
a hard check). Human-authored.
- `<code>/pages/` and `<code>/state.json` — generated: the translated pages and
the record of what each was made from (English content and section hashes, prompt
inputs, model, timestamp), plus the translated sidebar labels and notices. Never
edited by hand.

## The tool

`scripts/docs/translations.py` (run from the repository root):

```bash
uv run --frozen --group docs python scripts/docs/translations.py status # missing/outdated/current per language
uv run --frozen --group docs python scripts/docs/translations.py translate --lang ja # translate what is missing or outdated
uv run --frozen --group docs python scripts/docs/translations.py stage --lang ja # the docs tree the ja site builds from
```

`translate` calls the Claude API (set `ANTHROPIC_API_KEY` or
`ANTHROPIC_AUTH_TOKEN`). It re-translates only the `##` sections whose English
changed and carries the rest of the page over byte-for-byte from the previous
translation, then gates the result: heading anchors and code blocks are
re-imposed from the English, the page's structure (headings, code fences,
links, admonitions, glossary rules) is checked with the findings fed back for
another attempt, and a stronger model reviews the meaning against the English.
`--pages a.md b.md` narrows a run (a page that is already current comes back
unchanged), `--fresh` re-translates from scratch instead of updating (every
page when no `--pages` are given — the way to redo a language after a model
change), `--dry-run` shows what it would do, and `--no-verify` skips the
meaning review. A page that failed its gates keeps its previous translation and
the run exits non-zero; translations whose English page has left the nav are
deleted. Everything else is offline; `scripts/docs/build.sh` runs `stage` for
each language and builds it at `site/<code>/`.

## Correcting a translation

Never edit a file under `<code>/pages/` — the next run overwrites it. Fix the
input instead: a wrong term goes into `glossary.json`, a recurring style or
register problem into `instructions.md`, and ambiguous English into the page
under `docs/`. Editing a glossary or instructions marks that language's pages
outdated, so the next `translate` run regenerates them with the fix in place.
Readers report problems through the "Translation problem" issue form.

## Staleness

A page is *current* when the English content and the prompt inputs it was
translated from are unchanged, *outdated* otherwise, and *missing* when it has
no translation. The build serves an outdated translation with a warning
notice, unless the English page's links or heading anchors moved under it —
then the English page is served until the next `translate` run refreshes it.
Untranslated and excluded pages are served in English with a notice.

## Adding a language

Add an entry to `languages.yml` (`code`, native `name`; `theme_language` and
`hreflang` default to the code and must be values the theme knows), write
`<code>/instructions.md` and `<code>/glossary.json` (start from an existing
language), then run `translate --lang <code>` and commit the generated `pages/`
and `state.json`. Also name the language in `docs/translations.md` and the
"Translation problem" issue form's dropdown.
59 changes: 59 additions & 0 deletions i18n/general-prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Translation rules

You are translating a page of the MCP Python SDK documentation from English into the target language named in the language instructions that follow. The readers are software developers using the SDK.

## Your role

- Write natural, native-quality prose in the target language. The page should read as if a developer who is a native speaker wrote it, not as a translation.
- Keep the meaning exact. Do not add claims, drop caveats, reorder steps, or change the strength of a requirement (must / should / may).
- Follow the language instructions and the glossary strictly. Where the two disagree, the glossary wins.
- Translate the whole page. Never summarise, abridge, or leave a placeholder such as "translation continues below".

## Never translate

Copy the following byte-for-byte from the English source:

- Fenced code blocks: the fence markers, the info string, and every line inside them, including code comments.
- Inline code spans (text between backticks).
- URLs and link destinations, including `#fragment` anchors, and image paths.
- HTML tags and their attribute values.
- Front matter keys (the `key:` part of each front matter line).
- Snippet-include lines containing `--8<--`.
- Code-annotation markers such as `# (1)!`.
- Heading anchor attributes: the `{#some-id}` at the end of a heading (it may also be written with spaces, `{ #some-id }`; copy it exactly as it appears).
- The syntax markers for admonitions, collapsible blocks and content tabs (`!!!`, `???`, `???+`, `///`, `===`) and the block-type keyword that follows them (`note`, `tip`, `warning`, ...).
- Footnote labels (`[^1]`), abbreviation definitions (`*[HTML]: ...`) and emoji shortcodes (`:smile:`).
- Mermaid diagram source inside `mermaid` fences.

Do translate the human-language text around those elements: prose, headings, link text, image alt text, table cells, list items, admonition titles (the quoted text after `!!! type`) and bodies, and content-tab labels (the quoted text after `===`).

## Preserve the structure exactly

The translation must have the same shape as the English source, block for block:

- The same headings, at the same levels, in the same order, each ending in the same `{#anchor}` attribute as the source.
- The same number and type of admonitions, collapsible blocks and content-tab groups, in the same order.
- The same tables, with the same number of rows and columns.
- The same lists (same nesting, same number of items) and the same code fences (same count, same info strings, identical contents).
- The same links and images, in the same order. Never add, remove or merge a link.
- The same footnotes, and the same blank lines separating blocks.

Do not add explanatory notes, translator's remarks or extra examples.

## Links and anchors

- Keep every link destination exactly as written in the source, whether it is an absolute URL, a relative path such as `../servers/tools.md`, or a bare `#anchor`. Only the link text is translated.
- Do not add anchors the source does not have, and never rewrite a fragment: heading anchors are pinned in the English source, so the same `#id` is valid on every language site.
- Preserve the link syntax the source uses (Markdown `[text](target)` or HTML `<a href="...">`).

## Updating an existing translation

When the request includes a previous translation of the page and marks which sections of the English page changed:

- Outside the changed sections, reproduce the previous translation verbatim. Do not rephrase, "improve" or re-punctuate text whose English has not changed.
- Inside the changed sections, translate the new English following all of the rules above, and keep terminology, register and tone consistent with the surrounding unchanged text.
- A section is the page's front matter, the text before the first second-level heading, or one second-level heading (`##`) together with everything under it up to the next.

## Output

Return only the translated Markdown document, from its first line to its last. Do not add a preamble, a summary or any commentary, and do not wrap the document in a code fence.
Loading
Loading