Files
FastGPT/document/LOCALIZED_NAVIGATION.md
Archer 2fd4b6030b feat(i18n): Fix language loss in navigation and add language selector (#6467)
* 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>
2026-02-26 16:29:03 +08:00

3.0 KiB
Raw Blame History

国际化路由适配说明

问题

路由跳转时语言前缀丢失,导致用户在切换页面后回到默认语言。

解决方案

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
  • 配置:
    i18n: {
      locale,
      languages: [
        { name: '简体中文', locale: 'zh-CN' },
        { name: 'English', locale: 'en' }
      ],
      hideLocale: 'never'
    }
    
  • 状态: 已完成

使用方法

客户端组件

'use client';
import { useLocalizedRouter } from '@/lib/localized-navigation';

function MyComponent() {
  const router = useLocalizedRouter();
  router.push('/docs/introduction'); // 自动添加语言前缀
}

服务端组件

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 文档

<!-- 内部链接会自动添加语言前缀 -->
[查看介绍](/docs/introduction)

<!-- 或使用 Redirect 组件 -->
<Redirect to="/docs/faq" />

测试清单

  • 一级导航切换保持语言
  • 侧边栏导航保持语言
  • 首页重定向保持语言
  • 404 页面重定向保持语言
  • 旧链接重定向保持语言
  • 文档内链接保持语言
  • 语言选择器正常工作
  • 搜索结果链接保持语言