ETN Website i18n 国际化实施计划
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 为 ETN 网站添加中英双语支持,URL 前缀方案(/website/ 中文,/en/website/ 英文),首次访问自动检测浏览器语言,静态构建 SEO 友好。
Architecture: Docusaurus 官方 i18n,<Translate> 组件包裹所有 UI 字符串,构建时生成两套完整静态 HTML。自动检测逻辑在客户端模块中运行,语言偏好写入 localStorage,语言切换器触发 URL 跳转。
Tech Stack: Docusaurus 3.9.2, React 18, TypeScript, @docusaurus/Translate
文件变更总览
新建:
src/clientModules/autoLocale.ts— 首次访问语言检测 + localStorage 缓存i18n/en/code.json— 所有<Translate>字符串的英文翻译i18n/en/docusaurus-theme-classic/navbar.json— 导航英文标签i18n/en/docusaurus-theme-classic/footer.json— Footer 英文内容
修改:
docusaurus.config.ts— 新增enlocale,注册 clientModulesrc/theme/NavbarItem/NavbarLoginItem.tsx— 语言切换器触发真实 URL 跳转src/pages/index.tsx—<Translate>包裹所有中文字符串src/pages/pricing/index.tsxsrc/pages/login/index.tsxsrc/pages/changelog/index.tsxsrc/pages/usercenter/index.tsxsrc/pages/clipping/index.tsxsrc/pages/statistics/index.tsxsrc/pages/database/index.tsxsrc/pages/tags/index.tsxsrc/pages/weread/index.tsxsrc/pages/pic-config/index.tsx
Task 1: Docusaurus 配置 — 添加 en locale
Files:
-
Modify:
docusaurus.config.ts -
Step 1: 读取当前配置确认 i18n 块位置
grep -n "i18n" E:/work/ETN/etn-website/docusaurus.config.ts
预期输出:
151: i18n: {
153: locales: ["zh-Hans"],
- Step 2: 更新 i18n 配置块
将 docusaurus.config.ts 中的 i18n 配置替换为:
i18n: {
defaultLocale: "zh-Hans",
locales: ["zh-Hans", "en"],
localeConfigs: {
"zh-Hans": { label: "中文(简体)", direction: "ltr" },
en: { label: "English", direction: "ltr" },
},
},
- Step 3: 在 config 对象中注册 clientModule
在 const config: Config = { 块内(plugins: [] 行之后)新增:
clientModules: [require.resolve('./src/clientModules/autoLocale')],
- Step 4: 验证配置语法正确
cd E:/work/ETN/etn-website && npx tsc --noEmit 2>&1 | grep "docusaurus.config"
预期:无输出(无该文件错误)
Task 2: 创建自动语言检测客户端模块
Files:
-
Create:
src/clientModules/autoLocale.ts -
Step 1: 创建目录
mkdir -p E:/work/ETN/etn-website/src/clientModules
- Step 2: 写入 autoLocale.ts
// src/clientModules/autoLocale.ts
// 在浏览器端执行,检测首次访问语言并跳转
export function onRouteDidUpdate(): void {
// SSR 环境跳过
if (typeof window === 'undefined') return;
const LOCALE_KEY = 'etn-locale';
const currentPath = window.location.pathname;
const isEnPath = currentPath.startsWith('/en/');
const stored = localStorage.getItem(LOCALE_KEY);
if (stored) {
// 已有缓存,按缓存决定是否需要跳转
if (stored === 'en' && !isEnPath) {
window.location.replace('/en' + currentPath);
} else if (stored === 'zh-Hans' && isEnPath) {
window.location.replace(currentPath.replace(/^\/en/, ''));
}
return;
}
// 首次访问,无缓存,检测浏览器语言
const lang = (navigator.language || navigator.languages?.[0] || 'zh').toLowerCase();
if (lang.startsWith('zh')) {
localStorage.setItem(LOCALE_KEY, 'zh-Hans');
} else {
localStorage.setItem(LOCALE_KEY, 'en');
if (!isEnPath) {
window.location.replace('/en' + currentPath);
}
}
}
- Step 3: 验证 TypeScript 无错误
cd E:/work/ETN/etn-website && npx tsc --noEmit 2>&1 | grep "autoLocale"
预期:无输出