Fumadocs

Internationalization

Support multiple languages in your docs.

Setup

Define your languages:

src/lib/i18n.ts
import { defineI18n } from 'fumadocs-core/i18n';

export const i18n = defineI18n({
  defaultLanguage: 'en',
  hideLocale: 'default-locale',
  languages: ['en', 'cn'],
});

See i18n Config for the options, like hideLocale.

Pass it to your source and add Fumadocs UI translations to your config:

import { getCollection } from 'astro:content';
import { loader } from 'fumadocs-core/source';
import { toFumadocsSource } from '@fumadocs/astro/source';
import { i18n } from './i18n';

export const source = loader({
  source: toFumadocsSource(await getCollection('docs'), await getCollection('meta')),
  baseUrl: '/docs',
  i18n,
});

@fumadocs/language has translations for many languages.

Writing Pages

Add the language to a translation's file name, see i18n Routing:

index.mdx
index.cn.mdx
meta.json
meta.cn.json

Docs pages are created for every language, like /docs and /cn/docs above. The search dialog searches the current language.

For links that include the language, add DynamicLink to your MDX components:

src/components/mdx.tsx
import defaultMdxComponents from 'fumadocs-ui/mdx';
import { DynamicLink } from 'fumadocs-core/dynamic-link';
import type { MDXComponents } from 'mdx/types';

export function getMDXComponents(components?: MDXComponents) {
  return {
    ...defaultMdxComponents,
    // links with the locale, like `/[lang]/docs`
    DynamicLink,
    ...components,
  } satisfies MDXComponents;
}

export default getMDXComponents();
<DynamicLink href="/[lang]/docs/setup">Setup</DynamicLink>

Layout Options

baseOptions() receives the language. The navbar title links to the language's home page by default:

src/lib/layout.shared.tsx
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';

export function baseOptions(locale?: string): BaseLayoutProps {
  return {
    nav: { title: locale === 'cn' ? '文檔' : 'Docs' },
  };
}

Custom Pages

Create a page for each language with getStaticPaths(), and pass the language to HomeLayout:

src/pages/[...lang]/index.astro
---
import type { GetStaticPaths, InferGetStaticPropsType } from 'astro';
import HomeLayout from '@fumadocs/astro/components/HomeLayout.astro';
import { i18n } from '@/lib/i18n';

export const getStaticPaths = (() => {
  return i18n.languages.map((lang) => ({
    // the default language has no prefix
    params: { lang: lang === i18n.defaultLanguage ? undefined : lang },
    props: { lang },
  }));
}) satisfies GetStaticPaths;

type Props = InferGetStaticPropsType<typeof getStaticPaths>;

const { lang } = Astro.props;
---

<HomeLayout lang={lang}>
  <div class="p-4 flex flex-col items-center justify-center text-center flex-1">
    <h1 class="text-xl font-bold mb-2">Fumadocs on Astro.</h1>
    <p class="text-fd-muted-foreground mb-4">The truly flexible docs framework on React.js.</p>
    <a
      class="text-sm bg-fd-primary text-fd-primary-foreground rounded-full font-medium px-4 py-2.5"
      href={lang === i18n.defaultLanguage ? '/docs' : `/${lang}/docs`}
    >
      Open Docs
    </a>
  </div>
</HomeLayout>

How is this guide?

Last updated on