From e3f935fd6d9b9fe28eafba1b9d563f914b27c772 Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Sat, 21 Mar 2026 16:42:57 -0600 Subject: [PATCH] =?UTF-8?q?fix(docs):=20community=20feedback=20=E2=80=94?= =?UTF-8?q?=20typo,=20locale=20404s,=20llms-full=20(#2091)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(docs): correct Hasselhoff spelling, add locale-aware 404 redirect Fix "Hasslehoff" → "Hasselhoff" typo in customize-bmad.md across all three locales (en, zh-cn, fr). Add client-side locale detection to 404.astro so GitHub Pages serves the correct localized 404 page instead of always showing English. Co-Authored-By: Claude Opus 4.6 (1M context) * fix(build): exclude translated locales from llms-full.txt llms-full.txt was including zh-cn and fr docs, tripling the content with duplicate information in different languages. Restrict to English only — translations add no value for LLM context consumption. Reduces output from ~393K to ~114K chars (~29k tokens). Co-Authored-By: Claude Opus 4.6 (1M context) * refactor(i18n): extract locale config to shared module Move locale definitions from astro.config.mjs into a shared website/src/lib/locales.mjs consumed by astro config, build-docs, and 404.astro. Adding a new locale is now a single-file change. --------- Co-authored-by: Claude Opus 4.6 (1M context) --- docs/fr/how-to/customize-bmad.md | 2 +- docs/how-to/customize-bmad.md | 2 +- docs/zh-cn/how-to/customize-bmad.md | 2 +- tools/build-docs.mjs | 4 ++++ website/astro.config.mjs | 18 +++------------- website/src/lib/locales.mjs | 32 +++++++++++++++++++++++++++++ website/src/pages/404.astro | 16 +++++++++++++++ 7 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 website/src/lib/locales.mjs diff --git a/docs/fr/how-to/customize-bmad.md b/docs/fr/how-to/customize-bmad.md index f6a481235..c8975cc55 100644 --- a/docs/fr/how-to/customize-bmad.md +++ b/docs/fr/how-to/customize-bmad.md @@ -84,7 +84,7 @@ Ajouter un contexte persistant que l'agent gardera toujours en mémoire : ```yaml memories: - 'Travaille au Krusty Krab' - - 'Célébrité préférée : David Hasslehoff' + - 'Célébrité préférée : David Hasselhoff' - 'Appris dans l’Epic 1 que ce n’est pas cool de faire semblant que les tests ont passé' ``` diff --git a/docs/how-to/customize-bmad.md b/docs/how-to/customize-bmad.md index cfb75333c..15832df89 100644 --- a/docs/how-to/customize-bmad.md +++ b/docs/how-to/customize-bmad.md @@ -85,7 +85,7 @@ Add persistent context the agent will always remember: ```yaml memories: - 'Works at Krusty Krab' - - 'Favorite Celebrity: David Hasslehoff' + - 'Favorite Celebrity: David Hasselhoff' - 'Learned in Epic 1 that it is not cool to just pretend that tests have passed' ``` diff --git a/docs/zh-cn/how-to/customize-bmad.md b/docs/zh-cn/how-to/customize-bmad.md index 5f762ba20..5ed2d44c3 100644 --- a/docs/zh-cn/how-to/customize-bmad.md +++ b/docs/zh-cn/how-to/customize-bmad.md @@ -85,7 +85,7 @@ persona: ```yaml memories: - 'Works at Krusty Krab' - - 'Favorite Celebrity: David Hasslehoff' + - 'Favorite Celebrity: David Hasselhoff' - 'Learned in Epic 1 that it is not cool to just pretend that tests have passed' ``` diff --git a/tools/build-docs.mjs b/tools/build-docs.mjs index 7d916b515..cada7c0e1 100644 --- a/tools/build-docs.mjs +++ b/tools/build-docs.mjs @@ -14,6 +14,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { getSiteUrl } from '../website/src/lib/site-url.mjs'; +import { translatedLocales } from '../website/src/lib/locales.mjs'; // ============================================================================= // Configuration @@ -288,6 +289,9 @@ function shouldExcludeFromLlm(filePath) { const pathParts = filePath.split(path.sep); if (pathParts.some((part) => part.startsWith('_'))) return true; + // Exclude non-root locale directories (translations duplicate English content) + if (translatedLocales.some((locale) => filePath.startsWith(`${locale}/`) || filePath.startsWith(`${locale}${path.sep}`))) return true; + // Check configured patterns return LLM_EXCLUDE_PATTERNS.some((pattern) => filePath.includes(pattern)); } diff --git a/website/astro.config.mjs b/website/astro.config.mjs index b0f44d492..9d7efd99e 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -5,6 +5,7 @@ import sitemap from '@astrojs/sitemap'; import rehypeMarkdownLinks from './src/rehype-markdown-links.js'; import rehypeBasePaths from './src/rehype-base-paths.js'; import { getSiteUrl } from './src/lib/site-url.mjs'; +import { locales } from './src/lib/locales.mjs'; const siteUrl = getSiteUrl(); const urlParts = new URL(siteUrl); @@ -45,22 +46,9 @@ export default defineConfig({ title: 'BMAD Method', tagline: 'AI-driven agile development with specialized agents and workflows that scale from bug fixes to enterprise platforms.', - // i18n: English as root (no URL prefix), Chinese at /zh-cn/, French at /fr/ + // i18n: locale config from shared module (website/src/lib/locales.mjs) defaultLocale: 'root', - locales: { - root: { - label: 'English', - lang: 'en', - }, - 'zh-cn': { - label: '简体中文', - lang: 'zh-CN', - }, - fr: { - label: 'Français', - lang: 'fr-FR', - }, - }, + locales, logo: { light: './public/img/bmad-light.png', diff --git a/website/src/lib/locales.mjs b/website/src/lib/locales.mjs new file mode 100644 index 000000000..ef7e273e9 --- /dev/null +++ b/website/src/lib/locales.mjs @@ -0,0 +1,32 @@ +/** + * Shared i18n locale configuration. + * + * Single source of truth for locale definitions used by: + * - website/astro.config.mjs (Starlight i18n) + * - tools/build-docs.mjs (llms-full.txt locale exclusion) + * - website/src/pages/404.astro (client-side locale redirect) + * + * The root locale (English) uses Starlight's 'root' key convention + * (no URL prefix). All other locales get a URL prefix matching their key. + */ + +export const locales = { + root: { + label: 'English', + lang: 'en', + }, + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN', + }, + fr: { + label: 'Français', + lang: 'fr-FR', + }, +}; + +/** + * Non-root locale keys (the URL prefixes for translated content). + * @type {string[]} + */ +export const translatedLocales = Object.keys(locales).filter((k) => k !== 'root'); diff --git a/website/src/pages/404.astro b/website/src/pages/404.astro index 46065d04c..6ae826ab7 100644 --- a/website/src/pages/404.astro +++ b/website/src/pages/404.astro @@ -1,6 +1,7 @@ --- import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; import { getEntry } from 'astro:content'; +import { translatedLocales } from '../lib/locales.mjs'; const entry = await getEntry('docs', '404'); const { Content } = await entry.render(); @@ -9,3 +10,18 @@ const { Content } = await entry.render(); + + +