Before you begin
- A single-locale site you want to split into languages, or a plan for which pages need translation first
- Organize familiarity with sidebar groups and
hrefvalues - Preview running locally when you want to confirm locale URLs, navigation, and the language switcher
Multi-locale behavior is driven by the sidebar property in docs.json, not a separate locales field. For how locale keys shape URLs, link prefixing, and the language switcher, see Locales.
A minimal multi-locale setup needs three pieces:
- Locale folders: page files under
docs/{locale}/with matching paths (for exampledocs/en/index.mdxanddocs/fr/index.mdx) - Locale-keyed sidebar: replace the flat
sidebararray indocs.jsonwith an object keyed by locale code (en,fr, …) - Local verification: open
/en/...and/fr/...in Preview, then rundocs check
The sections below cover planning, content files, sidebar configuration, and a full preview checklist.
Readers need distinct URL segments and matching files per language. Start by locking locale codes, folder layout, and what / should do.
Goal at / | Pattern | Where to configure |
|---|---|---|
| Send readers to a default locale | redirect frontmatter on docs/index.mdx | Redirects |
Keep a language picker at / | sidebar.default tree plus content at docs/index.mdx | Configure locale sidebars and Locales |
Each translated page lives under a locale folder in docs/. Match the path after the locale key across languages:
| File | URL |
|---|---|
docs/en/installation.mdx | /en/installation |
docs/fr/installation.mdx | /fr/installation |
Pick stable locale codes up front
Use two-letter ISO 639-1 keys (for example
en,fr,de). They become URL segments andsidebarobject keys.Mirror page paths across locale folders
You do not need every locale to have every page on day one, but sidebar links should point at pages that exist for that locale, or readers will hit 404s. See Locales for partial rollout details.
Sketch a sidebar tree per locale
Each locale gets its own navigation labels and order. Keep
hrefvalues locale-neutral (/installation, not/fr/installation), docs.page prefixes the active locale when building links. See Locales: Automatic link prefixing.
Create a folder per locale under docs/
Match folder names to your locale keys:
textdocs/ en/ index.mdx installation.mdx fr/ index.mdx installation.mdxKeep matching paths across languages
Copy or write each page as its own
.mdxor.mdfile. English atdocs/en/installation.mdxand French atdocs/fr/installation.mdxboth use sidebarhref/installation, the path after the locale folder must match so the same link works in every locale.Write frontmatter in the target language
Every page needs at least
titleanddescriptionin the locale readers will see. See Write: Frontmatter.Retire single-locale files when you switch layouts
If
docs/installation.mdxused to serve/installation, relocate content intodocs/en/installation.mdx(and other locales) and add redirects for old URLs if they were already published. To send/to a default locale, addredirect: /en(or your chosen locale) ondocs/index.mdx.
Replace the flat sidebar array in docs.json with an object keyed by locale code.
Key sidebar trees by locale code
Open
docs.jsonand changesidebarfrom an array to an object. Each value is the same nested group structure you use for a single-language site:json{ "sidebar": { "en": [ { "group": "Getting Started", "pages": [ { "title": "Get started", "href": "/" }, { "title": "Installation", "href": "/installation" } ] } ], "fr": [ { "group": "Commencer", "pages": [ { "title": "Commencer", "href": "/" }, { "title": "Installation", "href": "/installation" } ] } ] } }docs.page derives available locales from these keys (every key except
default). There is no separatelocalesblock to maintain.Keep href values locale-neutral
Write
/installation, not/fr/installation. While a locale is active, internal navigation and in-page links are prefixed automatically so readers stay in the current language.Serve locale-free root URLs with a default tree
The
defaultkey is optional and is not treated as a locale. Use it for pages without a locale prefix, for example a language picker at/:json{ "sidebar": { "default": [ { "group": "Languages", "pages": [ { "title": "English", "href": "/en" }, { "title": "Français", "href": "/fr" } ] } ], "en": [], "fr": [] } }When the URL has no recognized locale segment, docs.page renders
sidebar.default(or an empty sidebar ifdefaultis omitted). See Locales for when each pattern fits.Align each locale tree with its files
Every
hrefin a locale's sidebar must resolve to a page underdocs/{locale}/. Use Organize for groups, nesting, tabs, and ordering within each tree.
When at least two locale keys are configured and the reader is on a locale-prefixed page, a language switcher appears in the sidebar. It does not show on locale-free root pages, even when sidebar.default is defined. See Locales: Language switcher.
Open locale-prefixed URLs in preview
Start Preview and open paths like
/en/installationand/fr/installation.Confirm navigation stays under the active locale
Sidebar labels match the active locale, internal links keep the locale prefix, and nested groups expand for the active page.
Exercise the language switcher
Switch between locales and confirm each lands on the expected locale root (
/en,/fr, and so on).Check root URL behavior
If you use
redirect: /enor adefaultsidebar, open/and confirm the behavior you planned.Catch broken locale links before merge
bashnpx @docs.page/cli checkThe CLI catches broken internal links, missing files, and invalid redirect targets.
| Symptom | Likely cause | Fix |
|---|---|---|
| Locale page returns 404 | File path does not include the locale segment | Store the page at docs/{locale}/path.mdx so /fr/installation maps to docs/fr/installation.mdx |
| Sidebar link 404 in one locale only | Translated file missing for that locale | Add the matching file under docs/{locale}/ or remove the link from that locale's sidebar tree |
| Wrong sidebar on a locale URL | sidebar is still a flat array, or locale key typo | Use a locale-keyed object with ISO 639-1 keys. Match the first URL segment to a configured key |
| Links drop out of the current locale | href includes a locale prefix | Use locale-neutral paths like /installation. Let the platform add the prefix |
| Language switcher missing | Only one locale key configured, or page is locale-free | Add a second locale key under sidebar, and open a URL under a configured locale |
| Root page shows wrong navigation | No default sidebar for locale-free URLs | Add sidebar.default, or redirect / to a default locale with redirect frontmatter |
redirect: /en fails check | Target page does not exist | Add docs/en/index.mdx (or the path you redirect to) before publishing |
- Locales: How locale keys, link prefixing, and the language switcher work in production.
- Organize: Structure groups, tabs, and page links before you split them by locale.
- Redirects: Send
/or renamed URLs to a default locale or new path. - Preview: Reload locally to confirm locale URLs, sidebars, and the language switcher.
