国际化
使用 i18next 配置 UI 文案、语言路由与双语 Fumadocs 内容。
模板使用 i18next + react-i18next,而不是 next-intl。文案查询与 URL 路由彼此 独立又相互配合:i18next 加载 UI 字符串,可选的 TanStack Router segment 控制 公开语言 URL。
当前路由模型
| 语言 | URL 形式 | 示例 |
|---|---|---|
英文(en,默认) | 无前缀 | /blog、/docs |
中文(zh) | /zh 前缀 | /zh/blog、/zh/docs |
src/routes/{-$locale}.tsx 在 beforeLoad 校验可选 segment。未知值进入 not
found,/en/* 重定向到无前缀 canonical 路径,有效路由则在渲染前调用
i18n.changeLanguage(locale)。布局中的 effect 会随导航更新 <html lang>。
虽然旧项目说明曾写“没有 URL segment 路由”,当前模板确实使用可选的
{-$locale};只是 canonical URL 隐藏了默认语言。
重要文件
| 文件 | 作用 |
|---|---|
src/i18n/index.ts | i18next 实例、字典、defaultLocale、supportedLocales 与标签 |
src/i18n/routing.tsx | 解析/移除/添加语言前缀、LocaleLink、当前语言与导航 hook |
src/routes/{-$locale}.tsx | Segment 校验、canonical 重定向、语言同步与文档语言 |
src/components/common/LanguageToggle.tsx | 语言选择器 |
messages/en.json、messages/zh.json | UI 翻译 |
src/lib/source.ts | Fumadocs 语言配置与本地化文档 URL |
content/docs | 双语 MDX 页面 |
localizePath() 会保留 query/hash、移除已有语言前缀,并且只为非默认语言添加
前缀。链接优先用 LocaleLink,命令式导航使用 useLocaleRouter()。
import { LocaleLink } from "#/i18n/routing"
<LocaleLink href="/pricing">Pricing</LocaleLink>语言检测与切换
当前 detectInitialLocale() 读取浏览器 pathname 的第一段;SSR 默认英文。路由
布局是权威来源,并在导航时同步 i18next。现有 LanguageToggle 会修改 i18next,
然后进入所选语言的首页。
项目虽安装了 i18next-browser-languagedetector,当前模板并未初始化它,也没有
内置语言 cookie 或 localStorage 偏好。若增加偏好检测,应让显式 URL segment
保持最高优先级并避免重定向循环。若切换语言时需要保留当前路径,也要修改
LanguageToggle,而不是总回首页。
翻译 UI 文案
先在两个字典中添加相同层级的 key,再在组件中使用 useTranslation():
import { useTranslation } from "react-i18next"
export function Greeting() {
const { t } = useTranslation()
return <h1>{t("home.hero.title")}</h1>
}保持字典结构一致。需要类型安全或按领域拆 namespace 时,应扩展 i18next 配置, 不要在 UI 到处写语言条件分支。
新增语言
创建字典
新增 messages/ja.json,key 与现有字典一致,并在 src/i18n/index.ts 导入。
扩展语言配置
把 "ja" 加入 supportedLocales,补充 localeLabels 并注册 resource:
export const supportedLocales = ["en", "zh", "ja"] as const
resources: {
en: { translation: en },
zh: { translation: zh },
ja: { translation: ja },
}若默认语言也要改变,请更新 defaultLocale 并重新测试所有 canonical 重定向。
扩展 SEO 语言映射
更新 src/lib/seo.ts 的 toOpenGraphLocale()。supportedLocales 已驱动 alternate
链接与 sitemap 展开,但 Open Graph locale 仍需对应 provider 格式。
添加本地化内容
Fumadocs 使用成对文件名:默认页面是 slug.mdx,中文是 slug.zh.mdx,所以
日文应新增 slug.ja.mdx。为所有必需文档补齐对应文件并检查导航 metadata。
博客和法律页 loader 目前在各语言 URL 共用内容,上线前应另行设计其本地化策略。
验证
-
/与其他英文页不带/en。 -
/en/blog?x=1重定向到/blog?x=1,/zh/blog保持中文。 - 不支持的首段不会被误当作语言。
- 语言感知链接保留 query 与 hash。
- 客户端导航后
<html lang>正确变化。 - 每个文档页都有对应语言文件,并能在该语言 URL 渲染。
- Canonical、alternate、Open Graph 与 sitemap 正确包含新语言。
