Skip to content

Commit 8ed9da1

Browse files
committed
Serve stored translations as generated; make site links relative
stage no longer re-imposes the current English structure onto a stored translation: a page is served exactly as it was generated (with the outdated notice once its English has moved on) or in English when there is none, so prose can never be paired with another section's code or heading ids. The switcher entries and the language sites' API entry are emitted relative to the site being built, so a mirrored copy of the build stays self-contained; the switcher script resolves the rendered roots before pointing them at the current page. Model replies end with the English's trailing newline, glossary files of the wrong shape are rejected up front, and the contributor notes describe what actually happens to a hand-edited generated page.
1 parent 00e9565 commit 8ed9da1

26 files changed

Lines changed: 230 additions & 210 deletions

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pre-commit run --all-files
128128

129129
## Documentation and Translations
130130

131-
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 tool can't tell a hand edit from its own output, so the edit persists unchecked, is carried forward into future runs, and hides the real fix. 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 re-run `translate --pages` for the affected pages; the fix then carries into every future run. See [`i18n/README.md`](i18n/README.md) for the details.
131+
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 tool can't tell a hand edit from its own output, so the edit persists unchecked, is carried forward into future runs, and hides the real fix. 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 re-run `translate --lang <code> --pages <page> …` for the affected pages; the fix then carries into every future run. See [`i18n/README.md`](i18n/README.md) for the details.
132132

133133
## Pull Requests
134134

docs/js/language-switch.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,13 @@
77
const base = JSON.parse(document.getElementById("__config").textContent).base;
88
// The site root as a directory path; `base` lacks the trailing slash on 404 pages.
99
const site = new URL(base.replace(/\/?$/, "/"), location).pathname;
10-
const entries = ".md-select__link[hreflang]";
11-
12-
function samePage(entry) {
13-
const page = location.pathname.slice(site.length);
14-
return entry.dataset.site + (page.startsWith("api/") ? "" : page);
15-
}
1610

1711
document$.subscribe(() => {
18-
for (const entry of document.querySelectorAll(entries)) {
19-
entry.dataset.site ??= entry.getAttribute("href"); // the language root the theme rendered
20-
entry.href = samePage(entry);
12+
let page = location.pathname.slice(site.length);
13+
if (page.startsWith("api/")) page = "";
14+
for (const entry of document.querySelectorAll(".md-select__link[hreflang]")) {
15+
// The language root the theme rendered, relative to the page first shown.
16+
entry.dataset.site ??= new URL(entry.getAttribute("href"), location).pathname;
17+
entry.href = entry.dataset.site + page;
2118
}
2219
});
23-
24-
// Headings carry the same ids on every site, so the reader's place carries over
25-
// too: query and fragment as they are when the switch happens, not at page load.
26-
function aim(event) {
27-
const entry = event.target instanceof Element ? event.target.closest(entries) : null;
28-
if (entry?.dataset.site && (event.type !== "keydown" || event.key === "Enter"))
29-
entry.href = samePage(entry) + location.search + location.hash;
30-
}
31-
for (const type of ["click", "auxclick", "keydown"]) document.addEventListener(type, aim, true);

docs/translations.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ The API reference is not translated: the translated site links to the single Eng
1313
If a translated page and its English original disagree, the English page is correct. Every page of a translated site opens with one of three notes saying where it stands:
1414

1515
- **Machine translation** — the page was translated automatically and links to its English original.
16-
- **Translation behind the English page** — the English original changed after the page was translated, so parts of it may be out of date until the translation catches up.
17-
- **Shown in English**there is no current translation of the page, so you are reading the English text.
16+
- **Translation behind the English page** — the English original changed after the page was translated. You are still reading that translation, so parts of it may be out of date until it catches up; the note links to the current English page.
17+
- **Shown in English**the page has not been translated yet, so you are reading the English text.
1818

1919
## How the translations are made
2020

i18n/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ uv run --frozen --group translate python scripts/docs/translations.py translate
1515
uv run --frozen python scripts/docs/translations.py stage [--lang CODE]
1616
```
1717

18-
`status` is offline: per language it lists missing, outdated (with the sections that changed), current and removable pages (translations whose English page is gone — `git rm` them). `translate` calls the Claude API (`ANTHROPIC_API_KEY` in the environment; the registry's model, or `DOCS_TRANSLATE_MODEL` to trial another) for the missing and outdated pages, retranslating only the English sections that changed and keeping the rest byte for byte; `--pages` instead re-translates exactly the named pages from scratch, which is also how a glossary or instructions change reaches existing pages (each generated page records the English section hashes it reflects, so editing those inputs invalidates nothing). `stage` assembles the tree each language site is built from (every language's, or one with `--lang`); `scripts/docs/build.sh` runs it before building them. Commit the generated pages in an ordinary pull request.
18+
`status` is offline: per language it lists missing, outdated (with the sections that changed), current and removable pages (translations whose English page is gone — `git rm` them). `translate` calls the Claude API (`ANTHROPIC_API_KEY` in the environment; the registry's model, or `DOCS_TRANSLATE_MODEL` to trial another) for the missing and outdated pages, retranslating only the English sections that changed and keeping the rest byte for byte; `--pages` instead re-translates exactly the named pages from scratch, which is also how a glossary or instructions change reaches existing pages (each generated page records the English section hashes it reflects, so editing those inputs invalidates nothing). `stage` assembles the tree each language site is built from (every language's, or one with `--lang`): each generated page exactly as it was generated, under an "outdated" notice linking the current English page when the English has changed since, and the English page where nothing was generated yet; `scripts/docs/build.sh` runs it before building them. Commit the generated pages in an ordinary pull request.
1919

2020
To add a language, add an entry to `languages.yml`, write `<code>/instructions.md` (the sections the `pt` file has) and `<code>/glossary.json`, then run `translate --lang <code>`.

i18n/de/instructions.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,7 @@ readers — in particular the du address, the gender-neutral phrasing convention
167167
and the keep-versus-translate line for individual nouns. To propose a change,
168168
edit this file or `glossary.json` in a pull request, ideally with a short
169169
good/bad example; never edit the generated `pages/` or `notices.md` next to
170-
this file, which the next translation run overwrites.
170+
this file. The tool cannot tell a hand edit from its own output, so one would
171+
persist unchecked and be carried forward into later runs; a correction made
172+
here reaches the pages when they are regenerated with
173+
`translate --lang de --pages …`.

i18n/de/pages/translations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [f671b445b16e4f99, 3983a560eb2cece7, 004b3ee918529d8c, c6e2debf1da06eb7, 81d412ed5f399f94]
3+
sections: [f671b445b16e4f99, 3983a560eb2cece7, b5c8bd4f2b3903e5, c6e2debf1da06eb7, 81d412ed5f399f94]
44
tool: 1
55
---
66
# Übersetzungen {#translations}
@@ -18,8 +18,8 @@ Die API-Referenz wird nicht übersetzt: Die übersetzte Website verlinkt auf die
1818
Wenn eine übersetzte Seite und ihr englisches Original voneinander abweichen, gilt die englische Seite. Jede Seite einer übersetzten Website beginnt mit einem von drei Hinweisen, der ihren Stand angibt:
1919

2020
- **Maschinelle Übersetzung** – die Seite wurde automatisch übersetzt und verlinkt auf ihr englisches Original.
21-
- **Übersetzung hinter der englischen Seite zurück** – das englische Original hat sich geändert, nachdem die Seite übersetzt wurde; Teile davon können also veraltet sein, bis die Übersetzung nachzieht.
22-
- **Auf Englisch angezeigt**es gibt keine aktuelle Übersetzung der Seite, deshalb liest du den englischen Text.
21+
- **Übersetzung hinter der englischen Seite zurück** – das englische Original hat sich geändert, nachdem die Seite übersetzt wurde. Du liest weiterhin diese Übersetzung, Teile davon können also veraltet sein, bis sie nachzieht; der Hinweis verlinkt auf die aktuelle englische Seite.
22+
- **Auf Englisch angezeigt**die Seite wurde noch nicht übersetzt, deshalb liest du den englischen Text.
2323

2424
## Wie die Übersetzungen entstehen {#how-the-translations-are-made}
2525

i18n/es/pages/translations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [f671b445b16e4f99, 3983a560eb2cece7, 004b3ee918529d8c, c6e2debf1da06eb7, 81d412ed5f399f94]
3+
sections: [f671b445b16e4f99, 3983a560eb2cece7, b5c8bd4f2b3903e5, c6e2debf1da06eb7, 81d412ed5f399f94]
44
tool: 1
55
---
66
# Traducciones {#translations}
@@ -18,8 +18,8 @@ La referencia de la API no está traducida: el sitio traducido enlaza a la únic
1818
Si una página traducida y su original en inglés no coinciden, la página en inglés es la correcta. Cada página de un sitio traducido se abre con una de estas tres notas, que indica en qué estado se encuentra:
1919

2020
- **Traducción automática**: la página se tradujo automáticamente y enlaza a su original en inglés.
21-
- **Traducción desactualizada respecto a la página en inglés**: el original en inglés cambió después de traducir la página, así que algunas partes pueden estar desactualizadas hasta que la traducción se ponga al día.
22-
- **Mostrada en inglés**: no hay una traducción vigente de la página, así que estás leyendo el texto en inglés.
21+
- **Traducción desactualizada respecto a la página en inglés**: el original en inglés cambió después de traducir la página. Sigues leyendo esa traducción, así que algunas partes pueden estar desactualizadas hasta que se ponga al día; la nota enlaza a la página actual en inglés.
22+
- **Mostrada en inglés**: la página todavía no se ha traducido, así que estás leyendo el texto en inglés.
2323

2424
## Cómo se hacen las traducciones {#how-the-translations-are-made}
2525

i18n/fr/instructions.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,7 @@ The register, voice and terminology decisions above, and every entry in
166166
readers — in particular the translate-versus-keep line for individual nouns
167167
and the typographic apostrophe. To propose a change, edit this file or
168168
`glossary.json` in a pull request, ideally with a short good/bad example;
169-
never edit the generated `pages/` or `notices.md` next to this file, which the
170-
next translation run overwrites.
169+
never edit the generated `pages/` or `notices.md` next to this file. The tool
170+
cannot tell a hand edit from its own output, so one would persist unchecked
171+
and be carried forward into later runs; a correction made here reaches the
172+
pages when they are regenerated with `translate --lang fr --pages …`.

i18n/fr/pages/translations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [f671b445b16e4f99, 3983a560eb2cece7, 004b3ee918529d8c, c6e2debf1da06eb7, 81d412ed5f399f94]
3+
sections: [f671b445b16e4f99, 3983a560eb2cece7, b5c8bd4f2b3903e5, c6e2debf1da06eb7, 81d412ed5f399f94]
44
tool: 1
55
---
66
# Traductions {#translations}
@@ -18,8 +18,8 @@ La référence de l’API n’est pas traduite : le site traduit renvoie vers l
1818
Si une page traduite et son original anglais divergent, c’est la page anglaise qui a raison. Chaque page d’un site traduit s’ouvre sur l’une de ces trois mentions, qui indique où elle en est :
1919

2020
- **Traduction automatique** — la page a été traduite automatiquement et renvoie vers son original anglais.
21-
- **Traduction en retard sur la page anglaise** — l’original anglais a changé après la traduction de la page ; certaines parties peuvent donc être obsolètes jusqu’à ce que la traduction rattrape son retard.
22-
- **Affichée en anglais**il n’existe pas de traduction à jour de la page ; vous lisez donc le texte anglais.
21+
- **Traduction en retard sur la page anglaise** — l’original anglais a changé après la traduction de la page. Vous lisez toujours cette traduction ; certaines parties peuvent donc être obsolètes jusqu’à ce qu’elle rattrape son retard ; la mention renvoie vers la page anglaise actuelle.
22+
- **Affichée en anglais**la page n’a pas encore été traduite ; vous lisez donc le texte anglais.
2323

2424
## Comment les traductions sont produites {#how-the-translations-are-made}
2525

i18n/hi/pages/translations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [f671b445b16e4f99, 3983a560eb2cece7, 004b3ee918529d8c, c6e2debf1da06eb7, 81d412ed5f399f94]
3+
sections: [f671b445b16e4f99, 3983a560eb2cece7, b5c8bd4f2b3903e5, c6e2debf1da06eb7, 81d412ed5f399f94]
44
tool: 1
55
---
66
# अनुवाद {#translations}
@@ -18,8 +18,8 @@ API reference का अनुवाद नहीं किया गया ह
1818
अगर किसी अनुवादित page और उसके अंग्रेज़ी मूल में फ़र्क हो, तो अंग्रेज़ी page सही है। अनुवादित site का हर page इन तीन notes में से किसी एक से शुरू होता है, जो बताता है कि वह page किस स्थिति में है:
1919

2020
- **Machine translation** — page का अनुवाद अपने आप किया गया है और उसमें उसके अंग्रेज़ी मूल का link है।
21-
- **Translation behind the English page** — page का अनुवाद होने के बाद अंग्रेज़ी मूल बदल गया है, इसलिए जब तक अनुवाद फिर से नहीं होता, इसके कुछ हिस्से पुराने हो सकते हैं।
22-
- **Shown in English** — इस page का कोई मौजूदा अनुवाद नहीं है, इसलिए आप अंग्रेज़ी text पढ़ रहे हैं।
21+
- **Translation behind the English page** — page का अनुवाद होने के बाद अंग्रेज़ी मूल बदल गया है। आप अब भी वही अनुवाद पढ़ रहे हैं, इसलिए जब तक वह अंग्रेज़ी के बराबर नहीं आ जाता, इसके कुछ हिस्से पुराने हो सकते हैं; note में मौजूदा अंग्रेज़ी page का link है
22+
- **Shown in English** — इस page का अनुवाद अभी तक नहीं हुआ है, इसलिए आप अंग्रेज़ी text पढ़ रहे हैं।
2323

2424
## अनुवाद कैसे बनते हैं {#how-the-translations-are-made}
2525

0 commit comments

Comments
 (0)