docs: generate full locale nav during publish sync

This commit is contained in:
Peter Steinberger
2026-04-05 14:29:14 +01:00
parent 9a0d88a868
commit 98bac6a0e4
2 changed files with 108 additions and 11 deletions

View File

@@ -15,14 +15,57 @@ const GENERATED_LOCALES = [
dir: "zh-CN",
navFile: "zh-Hans-navigation.json",
tmFile: "zh-CN.tm.jsonl",
navMode: "overlay",
},
{
language: "ja",
dir: "ja-JP",
navFile: "ja-navigation.json",
tmFile: "ja-JP.tm.jsonl",
navMode: "clone-en",
},
{
language: "es",
dir: "es",
navFile: "es-navigation.json",
tmFile: "es.tm.jsonl",
navMode: "clone-en",
},
{
language: "pt-BR",
dir: "pt-BR",
navFile: "pt-BR-navigation.json",
tmFile: "pt-BR.tm.jsonl",
navMode: "clone-en",
},
{
language: "ko",
dir: "ko",
navFile: "ko-navigation.json",
tmFile: "ko.tm.jsonl",
navMode: "clone-en",
},
{
language: "de",
dir: "de",
navFile: "de-navigation.json",
tmFile: "de.tm.jsonl",
navMode: "clone-en",
},
{
language: "fr",
dir: "fr",
navFile: "fr-navigation.json",
tmFile: "fr.tm.jsonl",
navMode: "clone-en",
},
{
language: "ar",
dir: "ar",
navFile: "ar-navigation.json",
tmFile: "ar.tm.jsonl",
navMode: "clone-en",
},
{ language: "ja", dir: "ja-JP", navFile: "ja-navigation.json", tmFile: "ja-JP.tm.jsonl" },
{ language: "es", dir: "es", navFile: "es-navigation.json", tmFile: "es.tm.jsonl" },
{ language: "pt-BR", dir: "pt-BR", navFile: "pt-BR-navigation.json", tmFile: "pt-BR.tm.jsonl" },
{ language: "ko", dir: "ko", navFile: "ko-navigation.json", tmFile: "ko.tm.jsonl" },
{ language: "de", dir: "de", navFile: "de-navigation.json", tmFile: "de.tm.jsonl" },
{ language: "fr", dir: "fr", navFile: "fr-navigation.json", tmFile: "fr.tm.jsonl" },
{ language: "ar", dir: "ar", navFile: "ar-navigation.json", tmFile: "ar.tm.jsonl" },
];
function parseArgs(argv) {
@@ -80,6 +123,60 @@ function writeJson(filePath, value) {
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
}
function prefixLocalePage(entry, localeDir) {
if (typeof entry === "string") {
return `${localeDir}/${entry}`;
}
if (Array.isArray(entry)) {
return entry.map((item) => prefixLocalePage(item, localeDir));
}
if (!entry || typeof entry !== "object") {
return entry;
}
const clone = { ...entry };
if (typeof clone.page === "string") {
clone.page = `${localeDir}/${clone.page}`;
}
if (Array.isArray(clone.pages)) {
clone.pages = clone.pages.map((item) => prefixLocalePage(item, localeDir));
}
return clone;
}
function cloneEnglishLanguageNav(englishNav, locale) {
if (!englishNav) {
throw new Error("docs/docs.json is missing navigation.languages.en");
}
return {
...englishNav,
language: locale.language,
tabs: Array.isArray(englishNav.tabs)
? englishNav.tabs.map((tab) => ({
...tab,
pages: Array.isArray(tab.pages)
? tab.pages.map((entry) => prefixLocalePage(entry, locale.dir))
: tab.pages,
groups: Array.isArray(tab.groups)
? tab.groups.map((group) => ({
...group,
pages: Array.isArray(group.pages)
? group.pages.map((entry) => prefixLocalePage(entry, locale.dir))
: group.pages,
}))
: tab.groups,
}))
: englishNav.tabs,
};
}
function composeLocaleNav(locale, englishNav) {
if (locale.navMode === "clone-en") {
return cloneEnglishLanguageNav(englishNav, locale);
}
return readJson(path.join(SOURCE_DOCS_DIR, ".i18n", locale.navFile));
}
function composeDocsConfig() {
const sourceConfig = readJson(SOURCE_CONFIG_PATH);
const languages = sourceConfig?.navigation?.languages;
@@ -88,12 +185,11 @@ function composeDocsConfig() {
throw new Error("docs/docs.json is missing navigation.languages");
}
const englishNav = languages.find((entry) => entry?.language === "en");
const generatedLanguageSet = new Set(GENERATED_LOCALES.map((entry) => entry.language));
const withoutGenerated = languages.filter((entry) => !generatedLanguageSet.has(entry?.language));
const enIndex = withoutGenerated.findIndex((entry) => entry?.language === "en");
const generated = GENERATED_LOCALES.map((entry) =>
readJson(path.join(SOURCE_DOCS_DIR, ".i18n", entry.navFile)),
);
const generated = GENERATED_LOCALES.map((entry) => composeLocaleNav(entry, englishNav));
if (enIndex === -1) {
withoutGenerated.push(...generated);
} else {