Files
computer-playbook/roles/web-app-docs/files/javascript/languages.js
T
kevinveenbirkenbachandClaude Opus 5 6a23926648 feat(docs): build and serve a translated site per language
Every version whose tree holds a locale/<code>/LC_MESSAGES/docs.po with at
least one translation now gets one site per such language next to the
English one, built with `-D language=<code> -D html_copy_source=0` after
the English site is published. Sphinx reads one docs.po per language
(locale_dirs, gettext_compact = "docs"); YAML pages stay untranslated
through an extension that runs before the Locale transform.

The deployed working tree is built as the unlisted version `deployed` from a
snapshot baked into the image, because the git mirror only holds what is
pushed to main. The server answers /<version>/<code>/ and
/api/languages/<version>, a language without a site is a 404 rather than the
English page, and a switcher on every page lists the built languages and
keeps the page path. min_storage grows to 13GB for the translated sites.

The 47 docs.po catalogs hold the 24869 documentation messages; German is
partially machine-translated so far. The raw-docker and primary-domain lints
skip .po files, which carry the Markdown's own commands and hosts as
translation sources.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 18:56:06 +02:00

33 lines
1.0 KiB
JavaScript

(function () {
function pageUrl(version, code, page) {
const prefix = code === "en" ? `/${version}` : `/${version}/${code}`;
return page ? `${prefix}/${page}.html` : `${prefix}/`;
}
async function fill(select) {
const { version, language, page } = select.dataset;
const response = await fetch(`/api/languages/${encodeURIComponent(version)}`);
if (!response.ok) {
return;
}
const { languages } = await response.json();
select.replaceChildren(
...languages.map((entry) => {
const option = document.createElement("option");
option.value = pageUrl(version, entry.code, page);
option.textContent = entry.native;
option.lang = entry.code;
option.selected = entry.code === language;
return option;
}),
);
select.addEventListener("change", () => {
window.location.href = select.value;
});
}
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".docs-language-switcher").forEach(fill);
});
})();