Astro
Support i18n routing on your Astro + Fumadocs app.
Setup
Define the i18n configurations in a file, we will import it with @/lib/i18n in this guide.
import { defineI18n } from 'fumadocs-core/i18n';
export const i18n = defineI18n({
defaultLanguage: 'en',
hideLocale: 'default-locale',
languages: ['en', 'cn'],
});See available options for i18n config.
Routing
Move your pages into a [...lang] folder. With hideLocale: 'default-locale', the parameter is empty for the default language (e.g. /docs), and the locale for others (e.g. /cn/docs).
To always prefix the locale, remove hideLocale and use a [lang] folder instead.
Translations
Define your translations in lib/layout.shared.tsx, see Translations for more details (including official language packs).
You can also add locale parameter to baseOptions() for localized layout options:
import { i18n } from '@/lib/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export const translations = i18n
.translations()
.extend(uiTranslations())
.add({
en: {
displayName: 'English',
},
cn: {
displayName: 'Chinese',
},
});
export function baseOptions(): BaseLayoutProps {
export function baseOptions(locale: string): BaseLayoutProps {
return {
nav: {
title: 'Astro',
url: locale === i18n.defaultLanguage ? '/' : `/${locale}`,
},
};
}Provider
Pass translations to <RootProvider />. The MDX content renders in an island of its own, add a provider for it too, without theme and search:
import { navigate } from 'astro:transitions/client';
import type { ReactNode } from 'react';
import { RootProvider } from 'fumadocs-ui/provider/astro';
import { i18nProvider } from 'fumadocs-ui/i18n';
import SearchDialog from '@/components/search';
import { translations } from '@/lib/layout.shared';
export interface ProviderProps {
lang: string;
/** `Astro.url.pathname` */
pathname: string;
/** `Astro.params` */
params: Record<string, string | undefined>;
children?: ReactNode;
}
export function Provider({ pathname, params, children }: ProviderProps) {
export function Provider({ lang, pathname, params, children }: ProviderProps) {
return (
<RootProvider
pathname={pathname}
params={params}
navigate={navigate}
i18n={i18nProvider(translations, lang)}
search={{ SearchDialog }}
>
{children}
</RootProvider>
);
}
export function ContentProvider({ lang, pathname, params, children }: ProviderProps) {
return (
<RootProvider
pathname={pathname}
params={params}
navigate={navigate}
i18n={i18nProvider(translations, lang)}
theme={{ enabled: false }}
search={{ enabled: false }}
>
{children}
</RootProvider>
);
}The wrapper of your MDX components receives the props of <Content />, wrap the content with ContentProvider:
import { ContentProvider, type ProviderProps } from '@/components/provider';
// ...
export default getMDXComponents({ wrapper: DocsBody });
export default getMDXComponents({
wrapper: ({ children, ...props }: ProviderProps) => (
<ContentProvider {...props}>
<DocsBody>{children}</DocsBody>
</ContentProvider>
),
});Pass Locale
Pass the locale to Fumadocs in your pages and layouts.
import { i18n } from '@/lib/i18n';
export const source = loader({
source: toFumadocsSource(await getCollection('docs'), await getCollection('meta')),
baseUrl: '/docs',
i18n,
});Search
The search endpoint indexes every language, the search dialog searches the current one:
import { useI18n } from 'fumadocs-ui/contexts/i18n';
export default function DefaultSearchDialog(props: SharedProps) {
const search = useStaticSearch();
const { locale } = useI18n();
const search = useStaticSearch({ locale });
// ...
}See Internationalization for the tokenizers of other languages, like Chinese and Japanese.
Writing Documents
See i18n routing to learn how to create pages for specific locales.
Navigation
Fumadocs only handles navigation for its own layouts (e.g. sidebar). For other places, prepend the locale to links.
In MDX content, register DynamicLink in your MDX components, it fills [lang] with the locale:
import { DynamicLink } from 'fumadocs-core/dynamic-link';
export function getMDXComponents(components?: MDXComponents) {
return {
...defaultMdxComponents,
DynamicLink,
...components,
} satisfies MDXComponents;
}<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>Components imported in MDX files are rendered by Astro, outside the providers of content.
How is this guide?
Last updated on
