mirror of
https://github.com/labring/FastGPT.git
synced 2026-05-05 01:02:59 +08:00
2fd4b6030b
* feat(docs): enable i18n language selector * docs(i18n): translate introduction page to English * fix(i18n): fix language switching issue by always showing locale prefix * fix(docs): use relative paths for internal links to preserve language * refactor(i18n): add getLocalizedPath helper to simplify URL generation * refactor(i18n): make getLocalizedPath respect hideLocale config * feat(i18n): fallback to default language when translation missing, keep URL unchanged * feat(i18n): fix language loss in navigation and add language selector - Set hideLocale to 'never' to always show language prefix - Add localized-navigation.ts with useLocalizedRouter hook - Update all navigation points to preserve language: 1. Tab navigation (already using getLocalizedPath) 2. Sidebar navigation (handled by Fumadocs) 3. Home/404 redirects (using getLocalizedPath) 4. MDX Redirect component (using useLocalizedRouter) 5. Old page redirects (updated not-found.tsx) 6. Document links (custom LocalizedLink component) - Configure language selector in layout.config.tsx - Add LOCALIZED_NAVIGATION.md documentation * fix(i18n): fix type errors and useEffect dependencies * refactor(i18n): move redirects to middleware for SSR support - Move old path redirects from client-side (not-found.tsx) to server-side (middleware.ts) - Use 301 permanent redirects for better SEO - Preserve language prefix in redirects - Fix SSR issue caused by client-side redirects * refactor(i18n): clean up not-found.tsx, remove duplicate redirect maps - Remove duplicate exactMap and prefixMap (now in middleware) - Keep dynamic meta.json lookup for unknown pages - Simplify to only handle fallback cases - Two-layer approach: middleware (SSR) + not-found (dynamic) * refactor(i18n): simplify not-found to always redirect to introduction - Remove dynamic meta.json lookup - Always redirect to introduction page on 404 - Ensures no 404 pages are shown - Keep language prefix in redirect * fix(i18n): fix middleware type error with ts-expect-error - Add @ts-expect-error for Fumadocs middleware signature mismatch - Fix syntax error in config matcher (remove literal \n) --------- Co-authored-by: archer <archer@archerdeMac-mini.local>
108 lines
3.0 KiB
Markdown
108 lines
3.0 KiB
Markdown
# 国际化路由适配说明
|
||
|
||
## 问题
|
||
路由跳转时语言前缀丢失,导致用户在切换页面后回到默认语言。
|
||
|
||
## 解决方案
|
||
|
||
### 1. 核心配置
|
||
- **`lib/i18n.ts`**: 设置 `hideLocale: 'never'`,确保所有语言(包括默认语言)都显示语言前缀
|
||
- **`lib/localized-navigation.ts`**: 提供客户端路由工具,自动处理语言前缀
|
||
|
||
### 2. 修复的路由跳转位置
|
||
|
||
#### ✅ 一级导航(Tab Navigation)
|
||
- **文件**: `app/[lang]/docs/layout.tsx`
|
||
- **方法**: 使用 `getLocalizedPath()` 为每个 tab 的 URL 添加语言前缀
|
||
- **状态**: 已完成
|
||
|
||
#### ✅ 二级导航(Sidebar)
|
||
- **文件**: `lib/source.ts`
|
||
- **方法**: Fumadocs 的 loader 自动根据 i18n 配置生成带语言前缀的链接
|
||
- **状态**: 已完成(无需修改)
|
||
|
||
#### ✅ 空页面重定向
|
||
- **文件**:
|
||
- `app/[lang]/(home)/page.tsx` - 首页重定向
|
||
- `app/[lang]/(home)/[...not-found]/page.tsx` - 404 重定向
|
||
- **方法**: 使用 `getLocalizedPath()` 添加语言前缀
|
||
- **状态**: 已完成
|
||
|
||
#### ✅ MDX 组件重定向
|
||
- **文件**: `components/docs/Redirect.tsx`
|
||
- **方法**: 使用 `useLocalizedRouter()` hook
|
||
- **状态**: 已完成
|
||
|
||
#### ✅ 旧页面重定向
|
||
- **文件**: `components/docs/not-found.tsx`
|
||
- **方法**:
|
||
- 使用 `useCurrentLang()` 获取当前语言
|
||
- 从 pathname 中移除语言前缀进行匹配
|
||
- 使用 `useLocalizedPath()` 为重定向目标添加语言前缀
|
||
- **状态**: 已完成
|
||
|
||
#### ✅ 文档内链接
|
||
- **文件**:
|
||
- `components/docs/LocalizedLink.tsx` - 自定义 Link 组件
|
||
- `mdx-components.tsx` - 配置 MDX 使用 LocalizedLink
|
||
- **方法**: 拦截 MDX 中的 `<a>` 标签,自动为内部链接添加语言前缀
|
||
- **状态**: 已完成
|
||
|
||
### 3. 语言选择器
|
||
- **文件**: `app/layout.config.tsx`
|
||
- **配置**:
|
||
```typescript
|
||
i18n: {
|
||
locale,
|
||
languages: [
|
||
{ name: '简体中文', locale: 'zh-CN' },
|
||
{ name: 'English', locale: 'en' }
|
||
],
|
||
hideLocale: 'never'
|
||
}
|
||
```
|
||
- **状态**: 已完成
|
||
|
||
## 使用方法
|
||
|
||
### 客户端组件
|
||
```tsx
|
||
'use client';
|
||
import { useLocalizedRouter } from '@/lib/localized-navigation';
|
||
|
||
function MyComponent() {
|
||
const router = useLocalizedRouter();
|
||
router.push('/docs/introduction'); // 自动添加语言前缀
|
||
}
|
||
```
|
||
|
||
### 服务端组件
|
||
```tsx
|
||
import { getLocalizedPath } from '@/lib/i18n';
|
||
import { redirect } from 'next/navigation';
|
||
|
||
export default async function Page({ params }: { params: Promise<{ lang: string }> }) {
|
||
const { lang } = await params;
|
||
redirect(getLocalizedPath('/docs/intro', lang));
|
||
}
|
||
```
|
||
|
||
### MDX 文档
|
||
```mdx
|
||
<!-- 内部链接会自动添加语言前缀 -->
|
||
[查看介绍](/docs/introduction)
|
||
|
||
<!-- 或使用 Redirect 组件 -->
|
||
<Redirect to="/docs/faq" />
|
||
```
|
||
|
||
## 测试清单
|
||
- [ ] 一级导航切换保持语言
|
||
- [ ] 侧边栏导航保持语言
|
||
- [ ] 首页重定向保持语言
|
||
- [ ] 404 页面重定向保持语言
|
||
- [ ] 旧链接重定向保持语言
|
||
- [ ] 文档内链接保持语言
|
||
- [ ] 语言选择器正常工作
|
||
- [ ] 搜索结果链接保持语言
|