---
title: 国际化
description: 在您的文档中支持多种语言
image: /images/blog/post-3.png
date: "2025-03-15"
published: true
categories: [company, product]
author: mksaas
---

<Callout title='开始之前'>

    Fumadocs 不是一个功能齐全的 i18n 库，它只管理自己的组件和工具。

    您可以使用其他库，如 [next-intl](https://github.com/amannn/next-intl)，用于应用程序的其余部分。
    阅读 [Next.js 文档](https://nextjs.org/docs/app/building-your-application/routing/internationalization)，了解更多关于在 Next.js 中实现 I18n 的信息。

</Callout>

## 手动设置

在一个文件中定义 i18n 配置，我们将在本指南中使用 `@/ilb/i18n` 导入它。

{/* <include cwd meta='title="lib/i18n.ts"'>
  ../../examples/i18n/lib/i18n.ts
</include> */}

将其传递给源加载器。

```ts title="lib/source.ts"
import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  i18n, // [!code highlight]
  // other options
});
```

并更新 Fumadocs UI 布局选项。

```tsx title="app/layout.config.tsx"
import { i18n } from '@/lib/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';

export function baseOptions(locale: string): BaseLayoutProps {
  return {
    i18n,
    // different props based on `locale`
  };
}
```

### 中间件

创建一个将用户重定向到适当语言环境的中间件。

```json doc-gen:file
{
  "file": "../../examples/i18n/middleware.ts",
  "codeblock": {
    "lang": "ts",
    "meta": "title=\"middleware.ts\""
  }
}
```

查看[中间件](/docs/headless/internationalization#middleware)了解可自定义选项。

> 请注意，这是可选的，您也可以使用自己的中间件或 i18n 库提供的中间件。

### 路由

创建一个 `/app/[lang]` 文件夹，并将所有文件（例如 `page.tsx`、`layout.tsx`）从 `/app` 移动到该文件夹。

将根提供程序包装在 `I18nProvider` 中，并向其提供可用语言和翻译。
请注意，默认情况下只提供英文翻译。

```tsx title="app/[lang]/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider';
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';

const cn: Partial<Translations> = {
  search: 'Translated Content',
  // other translations
};

// available languages that will be displayed on UI
// make sure `locale` is consistent with your i18n config
const locales = [
  {
    name: 'English',
    locale: 'en',
  },
  {
    name: 'Chinese',
    locale: 'cn',
  },
];

export default async function RootLayout({
  params,
  children,
}: {
  params: Promise<{ lang: string }>;
  children: React.ReactNode;
}) {
  const lang = (await params).lang;

  return (
    <html lang={lang}>
      <body>
        <I18nProvider
          locale={lang}
          locales={locales}
          translations={{ cn }[lang]}
        >
          <RootProvider>{children}</RootProvider>
        </I18nProvider>
      </body>
    </html>
  );
}
```

### 传递区域设置

在您的页面和布局中将区域设置传递给 Fumadocs。

{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
import type { ReactNode } from 'react';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';

export default async function Layout({
  params,
  children,
}: {
  params: Promise<{ lang: string }>;
  children: ReactNode;
}) {
  const { lang } = await params;

  return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
}
```

```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
import type { ReactNode } from 'react';
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/app/layout.config';

export default async function Layout({
  params,
  children,
}: {
  params: Promise<{ lang: string }>;
  children: ReactNode;
}) {
  const { lang } = await params;

  return (
    <DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
      {children}
    </DocsLayout>
  );
}
```

```ts title="page.tsx" tab="Docs Page"
import { source } from '@/lib/source';

export default async function Page({
  params,
}: {
  params: Promise<{ lang: string; slug?: string[] }>;
}) {
  const { slug, lang } = await params;
  // get page
  source.getPage(slug); // [!code --]
  source.getPage(slug, lang); // [!code ++]

  // get pages
  source.getPages(); // [!code --]
  source.getPages(lang); // [!code ++]
}
``` */}

### 搜索

在您的搜索解决方案上配置 i18n。

- **内置搜索 (Orama)：**
  对于[支持的语言](https://docs.orama.com/open-source/supported-languages#officially-supported-languages)，无需进一步更改。

  否则，需要额外配置（例如中文和日语）。请参阅[特殊语言](/docs/headless/search/orama#special-languages)。

- **云解决方案（例如 Algolia）：**
  它们通常官方支持多语言。

## 编写文档

{/* <include>../../shared/page-conventions.i18n.mdx</include> */}

## 导航

Fumadocs 只处理其自己的布局（例如侧边栏）的导航。
对于其他地方，您可以使用 `useParams` 钩子从 url 获取区域设置，并将其添加到 `href`。

```tsx
import Link from 'next/link';
import { useParams } from 'next/navigation';

const { lang } = useParams();

return <Link href={`/${lang}/another-page`}>This is a link</Link>;
```

另外，[`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) 组件支持动态 hrefs，您可以使用它来添加区域设置前缀。
这对于 Markdown/MDX 内容很有用。

```mdx title="content.mdx"
import { DynamicLink } from 'fumadocs-core/dynamic-link';

<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
```