- Introduced `extractLocaleAndBase` function to streamline locale and base name extraction from filenames. - Added new blog documentation files covering comparisons, internationalization, manual installation, and markdown usage in both English and Chinese. - Removed outdated author and blog content files to enhance content organization and clarity. - Updated `content-collections.ts` to utilize the new locale extraction function for improved file handling.
222 lines
5.6 KiB
Plaintext
222 lines
5.6 KiB
Plaintext
---
|
||
title: 国际化
|
||
description: 在您的文档中支持多种语言
|
||
---
|
||
|
||
<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>
|
||
``` |