You can setup i18n using Fumadocs CLI or update the configurations manually.
Read the Next.js Docs to learn more about implementing I18n in Next.js.
Initialize i18n with CLI.
Define the i18n configurations in a file, we will import it with @/ilb/i18n
in this guide.
import type { I18nConfig } from 'fumadocs-core/i18n' ;
export const i18n : I18nConfig = {
defaultLanguage : 'en' ,
languages : [ 'en' , 'cn' ] ,
};
Change your current source configurations.
import { i18n } from '@/lib/i18n' ;
import { loader } from 'fumadocs-core/source' ;
export const source = loader ( {
i18n ,
// other options
} ) ;
Update the usages to your source:
import { source } from '@/lib/source' ;
// get page tree
source . pageTree[params . lang] ;
// get page
source . getPage (params . slug , params . lang) ;
// get pages
source . getPages (params . lang) ;
See Source API for other usages.
Create a middleware that redirects users to appropriate locale.
import { createI18nMiddleware } from 'fumadocs-core/i18n' ;
import { i18n } from '@/lib/i18n' ;
export default createI18nMiddleware (i18n) ;
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher : [ '/((?!api|_next/static|_next/image|favicon.ico).*)' ] ,
};
See Middleware for customisable options.
Create a dynamic route /app/[lang]
, and move all special files from /app
to
the folder.
A I18nProvider
is needed for localization. Wrap the root provider inside your I18n provider.
import { RootProvider } from 'fumadocs-ui/provider' ;
import { I18nProvider } from 'fumadocs-ui/i18n' ;
export default function RootLayout ({
params ,
children ,
} : {
params : { lang : string };
children : React . ReactNode ;
}) {
return (
< html lang = { params . lang } >
< body >
< I18nProvider locale = { params . lang } >
< RootProvider > { children } </ RootProvider >
</ I18nProvider >
</ body >
</ html >
) ;
}
Make sure to update references to source
and configure Static Site Generation correctly.
import { source } from '@/lib/source' ;
import {
DocsPage ,
DocsBody ,
DocsTitle ,
DocsDescription ,
} from 'fumadocs-ui/page' ;
import { notFound } from 'next/navigation' ;
import defaultMdxComponents from 'fumadocs-ui/mdx' ;
import { metadataImage } from '@/lib/metadata' ;
export default async function Page ( props : {
params : Promise < { lang : string ; slug ?: string [] } > ;
}) {
const params = await props . params ;
const page = source . getPage (params . slug , params . lang) ;
if ( ! page) notFound () ;
const MDX = page . data . body ;
return (
< DocsPage toc = { page . data . toc } >
< DocsTitle > { page . data . title } </ DocsTitle >
< DocsDescription > { page . data . description } </ DocsDescription >
< DocsBody >
< MDX components = {{ ... defaultMdxComponents }} />
</ DocsBody >
</ DocsPage >
) ;
}
export async function generateStaticParams () {
return source . generateParams () ;
}
export async function generateMetadata ( props : {
params : Promise < { lang : string ; slug ?: string [] } > ;
}) {
const params = await props . params ;
const page = source . getPage (params . slug , params . lang) ;
if ( ! page) notFound () ;
return metadataImage . withImage (page . slugs , {
title : page . data . title ,
description : page . data . description ,
} ) ;
}
see Page Conventions to learn how to organize your documents.
Configure i18n on your search solution.
You don't need further changes if you're using the createFromSource
shortcut.
For the built-in Orama search, see Search I18n .
We only provide English translation by default, you have to pass your translations to the provider.
import { I18nProvider } from 'fumadocs-ui/i18n' ;
< I18nProvider
locales = { [
{
name : 'English' ,
locale : 'en' ,
},
{
name : 'Chinese' ,
locale : 'cn' ,
},
] }
translations = {
{
cn : {
search : 'Translated Content' ,
},
} [locale]
}
// other props
/> ;
To allow users changing their language, enable i18n
on your layouts.
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared' ;
export const baseOptions : BaseLayoutProps = {
i18n : true ,
};