Fumadocs

Next.js

在您的 Next.js + Fumadocs 应用中支持 i18n 路由

Next.js 新手?

设置

在文件中定义 i18n 配置,我们将在本指南中使用 @/lib/i18n 导入它。

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

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

有关 i18n 配置的可用选项,请参阅。

中间件

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

middleware.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).*)'],
};

使用自己的中间件?

默认中间件是可选的,您也可以使用自己的中间件或 i18n 库提供的中间件。

确保其行为与您在 i18n 配置中设置的 hidePrefix 选项一致。

路由

创建一个 /app/[lang] 文件夹,并将您的页面/布局移动到其中,但路由处理器除外。

api/search/route.ts
layout.tsx
(home)/page.tsx
...

常见错误

您是否意外发现样式丢失了?确保导入 global.css 的路径仍然正确!

<RootProvider /> 提供 UI 翻译和其他配置,当未指定 translations 时,将使用英语翻译。

app/[lang]/layout.tsx
import { RootProvider } from 'fumadocs-ui/provider';
import { defineI18nUI } from 'fumadocs-ui/i18n';
import { i18n } from '@/lib/i18n';

const { provider } = defineI18nUI(i18n, {
  translations: {
    en: {
      displayName: '英语',
    },
    cn: {
      displayName: '中文',
      search: '搜尋文檔',
    },
  },
});

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

  return (
    <html lang={lang}>
      <body>
        <RootProvider
          i18n={provider(lang)}
        >
          {children}
        </RootProvider>
      </body>
    </html>
  );
}

传递语言环境

locale 参数添加到 baseOptions() 中,并将其添加到 i18n 中:

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

export function baseOptions(locale: string): BaseLayoutProps {
  return {
    i18n,
    // 基于 `locale` 的不同属性
  };
}

在您的页面和布局中将语言环境传递给 Fumadocs。

import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  i18n,
  // 其他选项
});

lang 动态段使用其他名称?

如果您使用其他名称,如 app/[locale],您还需要在文档页面中更新 generateStaticParams()

export function generateStaticParams() {
  return source.generateParams();
  return source.generateParams('slug', 'locale'); // 新参数名称
}

搜索

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

  • 内置搜索 (Orama): 参阅国际化
  • 云解决方案 (例如 Algolia): 它们通常对多语言有官方支持。

编写文档

参阅i18n 路由 以了解如何为特定语言环境创建页面。

导航

Fumadocs 只处理其自身布局的导航(例如侧边栏)。

对于其他位置,您可以使用 useParams 钩子从 URL 获取语言环境,并将其附加到 href

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

const { lang } = useParams();

return <Link href={`/${lang}/another-page`}>这是一个链接</Link>;

此外,fumadocs-core/dynamic-link 组件支持动态 href,您可以使用它来附加语言环境前缀。 它对于 Markdown/MDX 内容非常有用。

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

<DynamicLink href="/[lang]/another-page">这是一个链接</DynamicLink>

How is this guide?

Last updated on