Internationalization
One English MDX source, PO translations, and four static language routes with localized search and UI.
On this page
This website is available in English, German, French, and Spanish. Choose a language in the header or mobile menu. Ardo keeps the same page, query string, and fragment when you switch languages.
Static Language Routes
Configure locales in ardo.config.ts or the ardo() Vite plugin:
import { defineArdoConfig } from "ardo/config"
export default defineArdoConfig({
title: "My Docs",
i18n: {
defaultLocale: "en",
locales: [
{ id: "en", label: "English" },
{ id: "de", label: "Deutsch" },
{ id: "fr", label: "Français" },
{ id: "es", label: "Español" },
],
},
})
Put matching routes under app/routes/en/, app/routes/de/, app/routes/fr/, and app/routes/es/. Keep route slugs identical across languages. Ardo requires a complete route tree and reports missing pages during the build. It does not silently substitute another language.
The V6 deployment uses /v6/en/, /v6/de/, /v6/fr/, and /v6/es/. Older documentation versions retain their original language and URLs.
UI, Search, and Metadata
Use useArdoLocale() from ardo/runtime for the active locale, including during server rendering. Pass localized labels to <ArdoRoot labels={...}> for navigation, search, callouts, copy controls, and page actions. Ardo formats last-updated dates with the route locale.
Search loads only the active language's index when readers focus the field or enter a query. Generated HTML carries the correct lang, canonical URL, and alternate-language links. Code identifiers and import paths remain unchanged. The API reference is generated from English source comments and says so in each translated interface.
One MDX Source with Palamedes
This example is compiled by Palamedes from one English MDX file. Its paragraphs and rich-text placeholders come from the language catalogs; the React component stays intact:
Welcome to Ardo. This paragraph is translated from one MDX source with Palamedes.
Code, links, and React components keep working in every language.
Palamedes' native compiler extracts semantic messages from each English guide in docs/app/content/guide/. During the build, the site applies the PO translations and generates the four route trees before Ardo collects metadata, search, and Markdown exports.
Only the English MDX source and the PO catalogs are maintained. Generated routes under docs/app/routes/<locale>/guide/ are ignored by Git. Code, imports, live components, and English heading IDs stay structural; translators work on prose, labels, and frontmatter.
Server Render Context
A site can export withRenderContext from app/server.ts to scope work around one complete page render. This module is only included in the server bundle. Metadata resolution and suspended React components run inside the same context:
import type { ArdoServerRenderContext } from "ardo/runtime"
import { createServerI18nScope } from "@palamedes/runtime/server"
const scope = createServerI18nScope()
export async function withRenderContext({ path, render }: ArdoServerRenderContext) {
const i18n = await loadI18n(path.split("/")[1] ?? "en")
return scope.run(i18n, render)
}
Here loadI18n is the site's catalog loader. Use one immutable instance per locale or a fresh instance per request. Do not activate a process-wide mutable locale: parallel renders would otherwise mix languages. In the browser, Palamedes v2 initializes its runtime from generated catalog dependencies. The site’s server hook uses createViteCatalogDelivery() from @palamedes/vite-plugin/delivery to insert the active locale’s import map and handle catalog-loading failures before hydration.
Maintain Translations
From the repository root:
pnpm --filter ardo-docs i18n:extract
pnpm --filter ardo-docs i18n:check
Extraction updates source messages and preserves existing translations. Edit the guide catalogs in docs/app/i18n/guides/; shared UI and the interactive example use docs/app/i18n/. The audit checks missing translations, ICU syntax, and rich-text placeholders. The Vite plugin regenerates routes after source or PO edits. Build the site and run the language-switching browser tests before submitting changes.