# Fumadocs (Framework Mode, Next.js): 國際化
URL: /zh-TW/docs/next/internationalization
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/internationalization.zh-TW.mdx

讓您的 Next.js 文件支援多種語言。

<Callout title="Fumadocs CLI">
執行 `npx @fumadocs/cli init --i18n` 即可建立支援 i18n 的新文件網站，您也可以依照下方說明手動設定。
</Callout>

## 概覽 [#overview]

請在 Next.js 與 Fumadocs 兩端設定 i18n 路由。

Fumadocs 會負責文件內容與側邊欄的 i18n。應用程式的其他部分，請透過您自己的 i18n 設定來進行國際化。

您也可以搭配 Fumadocs 使用 [next-intl](https://github.com/amannn/next-intl) 等函式庫。如需了解基本概念，請參閱 [Next.js 的 i18n](https://nextjs.org/docs/app/building-your-application/routing/internationalization)。

## 設定 [#setup]

請在一個檔案中定義 i18n 設定。本指南會以 `@/lib/i18n` 匯入該設定。

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

export const i18n = defineI18n({
  defaultLanguage: 'en',
  languages: ['en', 'cn'],
});
```

> i18n 設定的可用選項請參閱[這裡](/docs/headless/internationalization/config)。

### 中介軟體 [#middleware]

建立一個中介軟體，將使用者重新導向至對應的語系。

```ts title="proxy.ts"
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).*)'],
};
```

<Callout title="想使用自己的中介軟體？">
預設的中介軟體並非必要。您也可以使用自己的中介軟體，或 i18n 函式庫提供的中介軟體。

請確認其行為與您在 i18n 設定中指定的 [`hideLocale`](/docs/headless/internationalization/config#hide-locale-prefix) 選項一致。
</Callout>

### 路由 [#routing]

建立 `/app/[lang]` 資料夾，並將路由處理常式以外的頁面與版面配置全部移入其中。

<Files>
<Folder name="app" defaultOpen>
<File name="api/search/route.ts" />

<Folder name="[lang]" defaultOpen>
<File name="layout.tsx" />

<File name="(home)/page.tsx" />

<File name="..." />
</Folder>
</Folder>
</Files>

<Callout title="常見錯誤" type="error">
發現樣式不見了嗎？請確認 `global.css` 的匯入路徑仍然
正確！
</Callout>

### 翻譯 [#translations]

請在 `lib/layout.shared.tsx` 中定義您的翻譯。詳細資訊 (包括官方語言包) 請參閱[翻譯](/docs/ui/translations)。

您也可以為 `baseOptions()` 加上 `locale` 參數，以提供依語系調整的版面配置選項：

```tsx title="lib/layout.shared.tsx"
// [!code ++:2]
import { i18n } from '@/lib/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';

// [!code ++:11]
export const translations = i18n
  .translations()
  .extend(uiTranslations())
  .add({
    en: {
      displayName: 'English',
    },
    cn: {
      displayName: 'Chinese',
    },
  });

export function baseOptions(): BaseLayoutProps { // [!code --]
export function baseOptions(locale: string): BaseLayoutProps { // [!code ++]
  return {
    // 根據 `locale` 提供不同的 props
  };
}
```

將翻譯傳入 `<RootProvider />`：

```tsx title="app/[lang]/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider/next';
// [!code ++:2]
import { i18nProvider } from 'fumadocs-ui/i18n';
import { translations } from '@/lib/layout.shared';

export default function Layout({ children }: LayoutProps<'/'>) { // [!code --]
// [!code ++:2]
export default async function Layout({ params, children }: LayoutProps<'/[lang]'>) {
  const { lang } = await params;

  return (
    // [!code highlight]
    <html lang={lang} suppressHydrationWarning>
      <body className="flex flex-col min-h-screen">
        <RootProvider
          // [!code ++]
          i18n={i18nProvider(translations, lang)}
        >
          {children}
        </RootProvider>
      </body>
    </html>
  );
}
```

### 傳入語系 [#pass-locale]

請在頁面與版面配置中將語系傳給 Fumadocs。

```ts tab="lib/source.ts"
import { i18n } from '@/lib/i18n'; // [!code ++]
import { loader } from 'fumadocs-core/source';

export const source = loader({
  i18n, // [!code ++]
  // 其他選項
});
```

```tsx tab="首頁版面配置" title="app/[lang]/(home)/layout.tsx"
export default function Layout({ children }: LayoutProps<'/'>) { // [!code --]
// [!code ++:2]
export default async function Layout({ params, children }: LayoutProps<'/[lang]'>) {
  const { lang } = await params;

  return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>; // [!code highlight]
}
```

```tsx tab="文件版面配置" title="app/[lang]/docs/layout.tsx"
export default function Layout({ children }: LayoutProps<'/docs'>) { // [!code --]
// [!code ++:2]
export default async function Layout({ params, children }: LayoutProps<'/[lang]/docs'>) {
  const { lang } = await params;

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

```tsx tab="文件頁面" title="app/[lang]/docs/[[...slug]]/page.tsx"
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) { // [!code --]
export default async function Page(props: PageProps<'/[lang]/docs/[[...slug]]'>) { // [!code ++]
  const params = await props.params;
  const page = source.getPage(params.slug); // [!code --]
  const page = source.getPage(params.slug, params.lang); // [!code ++]
  if (!page) notFound();

  // ...
}
```

<Callout>
若您使用其他名稱 (例如 `app/[locale]`) ，也需要一併更新文件頁面中的 `generateStaticParams()`：

```tsx
export function generateStaticParams() {
  return source.generateParams(); // [!code --]
  return source.generateParams('slug', 'locale'); // [!code ++]
}
```
</Callout>

### 搜尋 [#search]

請在您使用的搜尋方案中設定 i18n。

* **內建搜尋：** 請參閱[國際化](/docs/headless/search/orama#internationalization)。
* **雲端方案 (例如 Algolia) ：** 這類方案通常有官方的多語系支援。

## 撰寫文件 [#writing-documents]

請參閱 [i18n 路由](/docs/next/page-conventions#i18n-routing)，了解如何為特定語系建立頁面。

### 導覽 [#navigation]

Fumadocs 只會處理其自身版面配置 (例如側邊欄) 中的導覽。

至於其他地方，請使用 `useParams` hook 從 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) 元件支援動態 href，因此您可以在 Markdown/MDX 內容中用它加上語系前綴。

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

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