Read the Next.js Docs to learn more about implementing I18n in Next.js.
Define the i18n configurations in a file, we will import it with @/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 '@/i18n' ;
import { loader } from 'fumadocs-core/source' ;
export const source = loader ( {
i18n ,
// other options
} ) ;
Update the usages to your source:
import { source } from '@/app/source' ;
// get page tree
source . pageTree[params . lang] ;
// get page
source . getPage (params . slug , params . lang) ;
// get pages
source . getPages (params . lang) ;
Create a middleware that redirects users to appropriate locale.
import { createI18nMiddleware } from 'fumadocs-core/i18n' ;
import { i18n } from '@/i18n' ;
export default createI18nMiddleware (i18n) ;
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher : [ '/((?!api|_next/static|_next/image|favicon.ico).*)' ] ,
};
Create a dynamic route /app/[lang]
, and move all special files from /app
to
the folder.
export default function Layout ({
params ,
children ,
} : {
params : { lang : string };
children : React . ReactNode ;
}) {
return (
< html lang = { params . lang } >
< body > { children } </ body >
</ html >
) ;
}
Make sure to update references to source
and configure Static Site Generation correctly.
import { source } from '@/app/source' ;
import type { Metadata } from 'next' ;
import {
DocsPage ,
DocsBody ,
DocsTitle ,
DocsDescription ,
} from 'fumadocs-ui/page' ;
import { notFound } from 'next/navigation' ;
import defaultMdxComponents from 'fumadocs-ui/mdx' ;
export default async function Page ({
params ,
} : {
params : { lang : string ; slug ?: string [] };
}) {
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 function generateMetadata ({
params ,
} : {
params : { lang : string ; slug ?: string [] };
}) {
const page = source . getPage (params . slug , params . lang) ;
if ( ! page) notFound () ;
return {
title : page . data . title ,
description : page . data . description ,
} satisfies Metadata ;
}
see Page Conventions to learn how to organize your documents.
Configure i18n on your search solution. For Flexsearch, see Setup I18n .
You can also customise the i18n middleware from i18n.ts
.
To hide the locale prefix, for example, use /
instead of /en
, use the hideLocale
option.
Mode Description always
Always hide the prefix, detect locale from cookies default-locale
Only hide the default locale never
Never hide the prefix (default)
It uses NextResponse.rewrite
under the hood.
import type { I18nConfig } from 'fumadocs-core/i18n' ;
export const i18n : I18nConfig = {
defaultLanguage : 'en' ,
languages : [ 'en' , 'cn' ] ,
hideLocale : 'default-locale' ,
};
It's not recommended to use always
.
On this mode, locale is stored as a cookie, read and set on the middleware.
This may cause undesired cache problems on your hosting platform, and need to pay extra attention on SEO to ensure search engines can index your pages correctly.