You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Add documentation languages: a languages.json in the project root declares the site's languages ([{ "code": "en", "label": "English", "default": true }, { "code": "de", "label": "Deutsch" }]), and each non-default language lives in a docs folder named after its code, which is also its URL prefix, so docs/de/guides/intro.mdx publishes at /de/guides/intro while the default language stays at the docs root with unchanged URLs. The generated site gets a language switcher in the sidebar (linking to the same page in the chosen language when it exists, else to that language's home), a sidebar and section bar scoped to the current language, search and AI chat scoped through new optional locale/version parameters on /api/search and /api/rag, language/version parameters on the MCP search_docs and list_docs tools with a docs://list resource that labels every variant, per-language llms.txt and llms-full.txt under each prefix with the root files linking to them, alternates.languages (hreflang with x-default) and an Open Graph locale on every translated page, sitemap alternates, a lang attribute on the article's <main>, and an <html lang> that is the default language server-side and is corrected from the URL by the pre-paint script. A language folder without an index.mdx gets a generated home redirect; a section index inside a language folder no longer overwrites the default one; untranslated pages are 404s under the language prefix. Watch mode reloads languages.json (keeping the previous configuration when the file is invalid) and re-renders a page's translations when its set of alternates changes. The site's own labels are English by default and can be overridden per language through a strings object on the entry; an unknown key is reported when the site is generated
Add documentation versions: a versions.json in the project root declares the versions ([{ "label": "v2.0", "default": true }, { "slug": "v1", "label": "v1.0" }]); the default version is the docs root and every other version is a folder named after its slug, so docs/v1/guides/intro.mdx publishes at /v1/guides/intro, and versions combine with languages as docs/de/v1/. The sidebar gets a version switcher, and the sidebar navigation, search, chat, MCP tools, and llms.txt files are scoped per version exactly as they are per language. The API reference generated from an OpenAPI spec stays in the default language and version
Both files are opt-in: a site without them generates byte-identical output, apart from the two empty [] copies the generated app now carries like sections.json. A language code or version slug must be a lowercase URL segment and must not collide with a section slug, the first folder of a section directory, each other, or the reserved segments api, gate, mcp, and ingest; a docs/<default code>/ folder or a version folder placed before a language folder stops the build with a message naming the file, as does an invalid languages.json or versions.json rather than publishing the folders as unscoped pages. navigation.json object keys are now URL prefixes ("", "api", "de", "de/api", "v1"), which keeps every existing section-keyed file working
Put the language and version switchers in the sidebar footer, on the same row as the focus-mode and theme toggles, on desktop and in the mobile menu, and drop the header's switchers slot: each is the Doccupine platform's dropdown, ported into the generated site as components/layout/Dropdown.tsx (a bordered trigger that mirrors the search trigger, a menu that scales in and out, click-outside dismissal), opening above the trigger with role="menu" radio items, a check mark on the current entry, arrow keys, Escape, and focus landing on the current entry. On that row the trigger is a 30px pill matching the two toggles, carrying the Lucide glyph, the current label, and a chevron that turns while the menu is open; where the narrow sidebar cannot hold all four controls at full width, a pair of switchers grows from its labels' widths to fill the rail's free width and drops to the short labels (a language's code, a version's own label) instead of truncating both
Translate the rest of the generated site's chrome through the same strings object: the AI chat's greeting, composer placeholder, composer label, typing indicator, and error prefix (chatGreeting, chatPlaceholder, chatInputLabel, chatAnswering, chatError), the chat launcher's label and accessible name (askAi, askAiAssistant), the sidebar's group toggles (expandGroup and collapseGroup, both taking a {title} placeholder), and a code block's copy button and variant tab list (copyCode, codeVariants). Cherry's chat kit ships English defaults for the greeting, placeholder, and typing indicator, so each is now passed explicitly rather than inherited; the generated Languages page lists every key
Render the two root layouts before touching the output directory: a generation error raised while the site layout was rendered used to surface as an unhandled rejection because the scaffolder created that promise before writing the earlier files
Remove the unused language-menu state the generated header component still carried