Internationalization
Support multiple languages in your Next.js docs.
Fumadocs CLI
npx @fumadocs/cli init --i18n sets up a new docs with i18n, or configure it manually below.
Overview
Configure i18n routing on both Next.js and Fumadocs.
Fumadocs handles i18n for the docs content and sidebar. Internationalize the rest of your app with your own i18n setup.
You can also use libraries like next-intl with Fumadocs. To learn the basics, see i18n in Next.js.
Setup
Define the i18n config in a file. This guide imports it as @/lib/i18n.
import { defineI18n } from 'fumadocs-core/i18n';
export const i18n = defineI18n({
defaultLanguage: 'en',
languages: ['en', 'cn'],
});
See available options for i18n config.
Middleware
Create a middleware that redirects users to the appropriate locale.
import { createI18nMiddleware } from 'fumadocs-core/i18n/middleware';
import { i18n } from '@/lib/i18n';
export default createI18nMiddleware(i18n);
export const config = {
// Matcher ignoring `/_next/` and `/api/`
// You may need to adjust it to ignore static assets in `/public` folder
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
Using your own middleware?
The default middleware is optional. You can also use your own middleware, or the one of an i18n library.
Make sure its behaviour aligns with the hideLocale option you set in your i18n config.
Routing
Create a /app/[lang] folder, and move your pages and layouts into it, except route handlers.
Common Mistake
Did you accidentally find your styles lost? Make sure the import path to global.css is still
correct!
Translations
Define your translations in lib/layout.shared.tsx. See Translations for more details, including the official language packs.
You can also add a 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 {
// different props based on `locale`
};
}Pass translations to <RootProvider />:
import { RootProvider } from 'fumadocs-ui/provider/next';
import { i18nProvider } from 'fumadocs-ui/i18n';
import { translations } from '@/lib/layout.shared';
export default function Layout({ children }: LayoutProps<'/'>) {
export default async function Layout({ params, children }: LayoutProps<'/[lang]'>) {
const { lang } = await params;
return (
<html lang={lang} suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<RootProvider
i18n={i18nProvider(translations, lang)}
>
{children}
</RootProvider>
</body>
</html>
);
}Pass Locale
Pass the locale to Fumadocs in your pages and layouts.
import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';
export const source = loader({
i18n,
// other options
});Using another name for lang dynamic segment?
If you're using another name like app/[locale], you also need to update generateStaticParams() in docs page:
export function generateStaticParams() {
return source.generateParams();
return source.generateParams('slug', 'locale');
}Search
Configure i18n on your search solution.
- Built-in Search: See Internationalization.
- Cloud Solutions (e.g. Algolia): They usually have official support for multilingual.
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, use the useParams hook to get the locale from the URL, and prepend it to href.
import Link from 'next/link';
import { useParams } from 'next/navigation';
const { lang } = useParams();
return <Link href={`/${lang}/another-page`}>This is a link</Link>;The fumadocs-core/dynamic-link component supports dynamic hrefs, so you can use it to prepend the locale prefix in Markdown/MDX content.
import { DynamicLink } from 'fumadocs-core/dynamic-link';
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>How is this guide?
Last updated on
