网站国际化(i18n)指南
目标:本文档是添加新语言的完整操作手册。下次添加韩语(
ko)、法语(fr)等语言时,请严格按照本文档的步骤操作。当前已支持:英语(
en)、中文(zh)、日语(ja)、西班牙语(es)、葡萄牙语(pt)
目录
1. 系统架构
.vitepress/
├── theme/
│ ├── utils/
│ │ └── i18n.ts ← 核心国际化模块(翻译数据 + useI18n hook)
│ ├── components/
│ │ ├── **/*.vue ← 各组件中通过 t() / L() / .en.zh.ja 使用翻译
│ │ └── ...
│ └── custom.css ← 全局 .lang-xx 等语言选择器 CSS
├── config.mts ← VitePress 配置(locales、导航、侧边栏、语言检测脚本)
└── ...
zh/ ← 中文页面文件(markdown)
ja/ ← 日语页面文件(markdown)核心模块:i18n.ts
文件位置:.vitepress/theme/utils/i18n.ts
导出:
messages对象:包含en、zh、ja三个语言的翻译数据useI18n()hook:返回t、lang、locale、isChinese、isJapanese、localePath
const { t, lang, locale, isChinese, isJapanese, localePath } = useI18n()
t('auth.login') // 根据当前语言返回翻译文本
localePath('/home') // 生成正确的语言路径(如 /ja/home)
isChinese.value // 是否中文
isJapanese.value // 是否日语2. 添加新语言:分步操作指南
假设要添加韩语(ko)。以下步骤需按顺序执行,每步完成后请对照自查清单打勾 ✅。
第 1 步:翻译数据(i18n.ts)
文件:.vitepress/theme/utils/i18n.ts
- [ ] 在
messages对象中添加ko区块 - [ ] 复制
en的所有 key 结构,替换为韩语翻译 - [ ] 确保 key 路径与
en完全一致(层级和数量)
const messages = {
en: { /* ... */ },
zh: { /* ... */ },
ja: { /* ... */ },
ko: { // ← 新增
auth: {
login: '로그인',
logout: '로그아웃',
signInWithGoogle: 'Google로 로그인',
},
common: {
cancel: '취소',
save: '저장',
},
// ... 所有 key
},
}第 2 步:更新 useI18n() hook
文件:.vitepress/theme/utils/i18n.ts
- [ ]
localecomputed 中添加语种检测 - [ ] 添加
isKoreancomputed(或其他新语言标识) - [ ] 更新
localePath()路径前缀逻辑
const locale = computed(() => {
const l = (lang.value || 'en').toLowerCase()
if (l.startsWith('zh')) return 'zh'
if (l.startsWith('ja')) return 'ja'
if (l.startsWith('ko')) return 'ko' // ← 新增
return 'en'
})
const isChinese = computed(() => locale.value === 'zh')
const isJapanese = computed(() => locale.value === 'ja')
const isKorean = computed(() => locale.value === 'ko') // ← 新增
// localePath 需处理新语言前缀
const localePath = (path) => {
const prefix = l === 'zh' ? '/zh' : l === 'ja' ? '/ja' : l === 'ko' ? '/ko' : ''
return prefix + path
}第 3 步:全局 CSS 支持
文件:.vitepress/theme/custom.css
- [ ] 添加新语言的全局 CSS 规则
/* 韩语模式全局规则 */
.ko { display: none; }
.lang-ko .ko { display: revert; }
.lang-ko .en { display: none; }
.lang-ko .zh { display: none !important; }
.lang-ko .ja { display: none !important; }⚠️ 重要:
.lang-ko .en必须设为display: none(而非revert),否则多语言会同时显示。
第 4 步:配置文件(config.mts)
文件:.vitepress/config.mts
- [ ]
locales中添加新语言条目 - [ ] 为该语言配置导航栏(
themeConfig.nav) - [ ] 为该语言配置侧边栏(
themeConfig.sidebar) - [ ] 更新内联语言检测脚本
locales: {
root: { label: 'English', lang: 'en', link: '/' },
zh: { label: '简体中文', lang: 'zh', link: '/zh/' },
ja: { label: '日本語', lang: 'ja', link: '/ja/' },
ko: { label: '한국어', lang: 'ko', link: '/ko/' }, // ← 新增
}语言检测脚本更新:
var browserLang = (navigator.language || 'en').toLowerCase();
targetLang = browserLang.indexOf('zh') !== -1 ? 'zh'
: browserLang.indexOf('ja') !== -1 ? 'ja'
: browserLang.indexOf('ko') !== -1 ? 'ko' // ← 新增
: 'en';⚠️ 导航栏中的外部链接(如 FastMoss 主站)也需按语言调整。
第 5 步:创建页面文件
- [ ] 创建
ko/目录,目录结构与ja/保持一致 - [ ] 复制
ja/的所有.md文件到ko/ - [ ] 翻译每个
.md文件的内容 - [ ] 检查 frontmatter(如
title、description)是否需要翻译
多数页面仅引用 Vue 组件(文本由
t()或 span 处理),但 API 文档页面含有具体内容,需要逐页翻译。
第 6 步:更新 Vue 组件(核心工作量)
这是最繁琐的一步。需要遍历所有组件,根据其国际化模式做对应修改。
6a. 处理模式 B 组件(<span class="en/zh/ja">)
搜索所有使用了 .en / .zh / .ja span 的组件,见「文件清单」章节:
<!-- ✅ 为每个 .ja span 后面添加 .ko span -->
<h1>
<span class="en">Get Help</span>
<span class="zh">获取帮助</span>
<span class="ja">ヘルプを見る</span>
<span class="ko">도움말 보기</span> <!-- ← 新增 -->
</h1>在组件 scoped CSS 中添加 .ko / .lang-ko 规则。参考下方「CSS 语言切换机制」章节。
6b. 处理模式 C 组件(v-if="isChinese")
搜索所有使用 isChinese / isJapanese 的组件:
<!-- ✅ 添加新语言分支 -->
<h1 v-if="isChinese">中文</h1>
<h1 v-else-if="isJapanese">日本語</h1>
<h1 v-else-if="isKorean">한국어</h1> <!-- ← 新增 -->
<h1 v-else>English</h1>⚠️ 注意
v-if="!isChinese"和v-if="isChinese || isJapanese"这类条件逻辑——新语言可能属于哪个组别需要单独判断。
6c. 处理组件根元素 class 绑定
确保每个组件的根元素有完整绑定:
<div :class="{ 'lang-zh': isChinese, 'lang-ja': isJapanese, 'lang-ko': isKorean }">6d. 处理数据驱动组件(L() 函数)
搜索使用 L() 函数的组件(见文件清单),更新函数和数据:
// L() 函数增加第 4 参数
const L = (en, zh, ja, ko) => isChinese.value ? zh
: (isJapanese.value ? (ja || en)
: (isKorean.value ? (ko || en) : en))
// 数据增加 Ko 后缀字段
const items = [
{
title: 'Find a product opportunity',
titleZh: '选品:找值得做的机会',
titleJa: '商品機会を見つける',
titleKo: '제품 기회 찾기', // ← 新增
}
]6e. 处理 copyText / copyPrompt 等反馈函数
// 复制反馈增加韩语
const en = el.querySelector('.en'), zh = el.querySelector('.zh'),
ja = el.querySelector('.ja'), ko = el.querySelector('.ko')
if (en && zh && ja && ko) {
const origEn = en.textContent, origZh = zh.textContent,
origJa = ja.textContent, origKo = ko.textContent
en.textContent = 'Copied'; zh.textContent = '已复制';
ja.textContent = 'コピーしました'; ko.textContent = '복사됨'
setTimeout(() => {
en.textContent = origEn; zh.textContent = origZh
ja.textContent = origJa; ko.textContent = origKo
}, 1400)
}6f. 处理 ROLE_LABEL 等映射数组
const ROLE_LABEL = {
context: ['Context', '背景', 'コンテキスト', '컨텍스트'], // ← 新增
}
// 取值逻辑更新
const idx = isChinese.value ? 1 : (isJapanese.value ? 2 : (isKorean.value ? 3 : 0))
const label = ROLE_LABEL[r][idx]6g. 处理 promptOutput computed 等条件分支
if (zh) {
// 中文 prompt
} else if (ja) {
// 日语 prompt
} else if (ko) {
// 韩语 prompt(新增分支)
} else {
// 英语 prompt
}第 7 步:验证构建
npm run docs:build- [ ] 无编译错误
- [ ] 首页
/正常显示 - [ ]
/ko/页面正常显示 - [ ] 语言切换器显示新语言
- [ ] 导航栏链接正确
- [ ] 侧边栏正确显示
- [ ] 搜索功能正常
- [ ] 登录/注册页面正常
- [ ] 切换语言后所有文本正确显示
3. 国际化模式参考
项目中存在三种国际化渲染模式,新语言需要全部覆盖。
模式 A:t() 函数(推荐)
适用于纯文本、按钮、标签等。
<button>{{ t('auth.login') }}</button>
<p>{{ t('common.loading') }}</p>新语言适配:只需在 messages 中添加对应语言的翻译 key。
模式 B:.en / .zh / .ja span + CSS 切换
适用于带有复杂 HTML 结构或需要语法高亮的文本块。
<h1>
<span class="en">TikTok Shop data,<br><em>every way you work</em></span>
<span class="zh">TikTok Shop数据,<br>融入你的每种工作方式</span>
<span class="ja">TikTok Shopデータ、<br><em>あらゆる作業方法に対応</em></span>
</h1>新语言适配:为每一对 .en/.zh/.ja 添加对应的新语言 span,并添加 CSS 规则。
⚠️ 注意语序差异:不同语言的语序可能不同,高亮部分(
<em>或渐变文字)需要根据目标语法重新组织,不能逐字翻译。
模式 C:v-if / v-else-if / v-else 条件渲染
适用于整个段落或复杂 DOM 结构根据不同语言完全不同的场景。
<h1 v-if="isChinese">中文标题</h1>
<h1 v-else-if="isJapanese">日本語のタイトル</h1>
<h1 v-else>English Title</h1>新语言适配:在 v-if 链的适当位置插入新语言分支。
4. CSS 语言切换机制
全局 CSS(custom.css)
/* 韩语模式全局规则 — 添加新语言时复制此模板 */
.ko { display: none; }
.lang-ko .ko { display: revert; }
.lang-ko .en { display: none; }
.lang-ko .zh { display: none !important; }
.lang-ko .ja { display: none !important; }组件级 CSS
每个使用模式 B(span)的组件都需要在自己的 <style scoped> 中添加规则:
/* 默认隐藏所有非英语语言 */
.my-class .zh { display: none; }
.my-class .ja { display: none; }
.my-class .ko { display: none; }
/* 各语言模式 */
.my-class.lang-zh .zh { display: revert; }
.my-class.lang-zh .en { display: none; }
.my-class.lang-zh .ja { display: none !important; }
.my-class.lang-zh .ko { display: none !important; }
.my-class.lang-ja .ja { display: revert; }
.my-class.lang-ja .en { display: none; }
.my-class.lang-ja .zh { display: none !important; }
.my-class.lang-ja .ko { display: none !important; }
.my-class.lang-ko .ko { display: revert; } /* ← 新增 */
.my-class.lang-ko .en { display: none; }
.my-class.lang-ko .zh { display: none !important; }
.my-class.lang-ko .ja { display: none !important; }组件绑定
每个组件的根元素必须有 class 绑定:
<div class="my-component" :class="{ 'lang-zh': isChinese, 'lang-ja': isJapanese, 'lang-ko': isKorean }">5. L() 辅助函数
定义(4 参数版本,用于韩语)
const L = (en, zh, ja, ko) => isChinese.value ? zh
: (isJapanese.value ? (ja || en)
: (isKorean.value ? (ko || en) : en))使用方式
<!-- 传入对应语言的文本 -->
<h2>{{ L(current.title, current.titleZh, current.titleJa, current.titleKo) }}</h2>
<p>{{ L(current.sub, current.subZh, current.subJa, current.subKo) }}</p>数据格式
const items = [
{
title: 'Find a product opportunity',
titleZh: '选品:找值得做的机会',
titleJa: '商品機会を見つける',
titleKo: '제품 기회 찾기', // ← 新增
sub: 'Judge demand, stage, competition, and entry timing.',
subZh: '判断需求、所处阶段、竞争与进入时机。',
subJa: '需要、段階、競争、参入タイミングを判断します。',
subKo: '수요, 단계, 경쟁, 진입 시기를 판단합니다.',
// ...
}
]常见陷阱
| 问题 | 表现 | 解决方案 |
|---|---|---|
L() 只有 2 参数 | 日语/韩语用户看到英语 | 升级为多参数版本 |
| 数组字段不一致 | 索引错位或 undefined | 确保 getJa[] / getKo[] 与 get[] 长度和顺序一致 |
静态 <span> 与 L() 混淆 | 内容结构错误 | <span> 用于静态标签,L() 用于动态数据文本 |
6. 配置文件(config.mts)
locales 配置
locales: {
root: { label: 'English', lang: 'en', link: '/' },
zh: { label: '简体中文', lang: 'zh', link: '/zh/' },
ja: { label: '日本語', lang: 'ja', link: '/ja/' },
ko: { label: '한국어', lang: 'ko', link: '/ko/' }, // 新增
}URL 路径规则
| 语言 | 路径前缀 | 示例 |
|---|---|---|
| 英文 | /(无前缀) | /home.html |
| 中文 | /zh/ | /zh/home.html |
| 日语 | /ja/ | /ja/home.html |
| 韩语 | /ko/ | /ko/home.html |
侧边栏配置
sidebar: {
'/api/docs/': [ /* 英文侧边栏 */ ],
'/zh/api/docs/': [ /* 中文侧边栏 */ ],
'/ja/api/docs/': [ /* 日语侧边栏 */ ],
'/ko/api/docs/': [ /* 韩语侧边栏 */ ], // 新增
}7. 页面文件结构
每种语言有一套独立的 markdown 页面文件。新语言需要创建与 ja/ 完全相同的目录结构。
ko/ ← 韩语页面(与 ja/ 结构一致)
├── index.md
├── home.md
├── login.md
├── register.md
├── pricing.md
├── checkout.md
├── api/
│ ├── overview.md
│ ├── pricing.md
│ └── docs/guide/quickStart.md
├── docs/
│ └── mcp/setup.md
├── mcp/
│ ├── overview.md
│ ├── pricing.md
│ └── setup.md
└── profile/
├── index.md
└── ...大多数页面仅引用 Vue 组件(文本由
t()或 span 处理),但 API 文档页面含有具体内容,需要逐页翻译。
8. 文件清单
必须修改的核心文件
| 文件 | 操作 |
|---|---|
.vitepress/theme/utils/i18n.ts | 添加翻译数据、更新 useI18n()、更新 localePath() |
.vitepress/config.mts | 添加 locale 配置、导航、侧边栏、语言检测脚本 |
.vitepress/theme/custom.css | 添加 .lang-ko 全局 CSS 规则 |
需要添加语言 class 和 CSS 的组件(模式 B span)
以下组件使用了 <span class="en/zh/ja">,需要为每个 .ja 添加 .ko:
| # | 组件 | 文件路径 |
|---|---|---|
| 1 | Auth | components/Auth.vue |
| 2 | SearchInSidebar | components/SearchInSidebar.vue |
| 3 | DocSearch | components/docs/DocSearch.vue |
| 4 | HomePage | components/HomePage.vue |
| 5 | McpOverviewV2 | components/mcp/McpOverviewV2.vue |
| 6 | AppFooter | components/AppFooter.vue |
| 7 | ApiOverview | components/api/ApiOverview.vue |
| 8 | McpPricingV2 | components/mcp/McpPricingV2.vue |
| 9 | PricingByEndpoints | components/api/PricingByEndpoints.vue |
| 10 | DocsHome | components/docs/DocsHome.vue |
| 11 | DocsSidebar | components/docs/DocsSidebar.vue |
| 12 | CommunitySupport | components/docs/CommunitySupport.vue |
| 13 | McpGuideSetup | components/docs/mcp/McpGuideSetup.vue |
| 14 | McpGuideUnderstand | components/docs/mcp/McpGuideUnderstand.vue |
| 15 | McpGuideHelp | components/docs/mcp/McpGuideHelp.vue |
| 16 | ProfileSidebar | components/profile/ProfileSidebar.vue |
| 17 | Dashboard | components/profile/Dashboard.vue |
| 18 | OrderHistory | components/profile/OrderHistory.vue |
| 19 | api/OrderHistory | components/profile/api/OrderHistory.vue |
| 20 | api/Usage | components/profile/api/Usage.vue |
| 21 | InvoiceApply | components/profile/InvoiceApply.vue |
| 22 | api/InvoiceApply | components/profile/api/InvoiceApply.vue |
| 23 | ReceiptList | components/profile/ReceiptList.vue |
| 24 | api/ReceiptList | components/profile/api/ReceiptList.vue |
| 25 | McpBilling | components/profile/mcp/McpBilling.vue |
| 26 | McpApiKeys | components/profile/mcp/McpApiKeys.vue |
| 27 | McpUsage | components/profile/mcp/McpUsage.vue |
| 28 | McpInvoiceApply | components/profile/mcp/McpInvoiceApply.vue |
| 29 | McpReceiptList | components/profile/mcp/McpReceiptList.vue |
| 30 | FloatingDocAction | components/api/FloatingDocAction.vue |
| 31 | DocButtons | components/api/DocButtons.vue |
| 32 | CheckoutByTime | components/api/CheckoutByTime.vue |
| 33 | Profile | components/Profile.vue |
| 34 | OauthGoogleCallback | components/OauthGoogleCallback.vue |
提示:可通过
grep -r 'span class=\"ja\"' components/快速定位所有需要添加.kospan 的文件。
需要处理 L() 函数和数据的数据驱动组件
| 组件 | 文件 | 需要更新 |
|---|---|---|
| McpGuideSetup | components/docs/mcp/McpGuideSetup.vue | L() → 4 参数 + 数据 Ko 字段 |
| McpGuidePlaybooks | components/docs/mcp/McpGuidePlaybooks.vue | L() → 4 参数 + titleKo/subKo/getKo[]/promptKo/followupsKo[] |
| McpGuidePrompt | components/docs/mcp/McpGuidePrompt.vue | L() → 4 参数 + 映射韩语 + promptOutput 韩语分支 + ROLE_LABEL 第 4 项 |
| McpGuideHelp | components/docs/mcp/McpGuideHelp.vue | L() → 4 参数 + helpItems 每条加 Ko 字段 |
9. 附录:日语支持时间线
| 日期 | 操作 |
|---|---|
| 2026-07-13 | 添加 ja 翻译区块、更新 useI18n()、更新 config.mts |
| 2026-07-13 | 创建 ja/ 目录及页面文件 |
| 2026-07-13 | 修复硬编码文本、更新语言检测逻辑 |
| 2026-07-13 | 为 HomePage、McpOverviewV2 等核心组件添加日语内容 |
| 2026-07-13 | 为文档组件添加日语支持 |
| 2026-07-13 | 修复 CSS/日语显示问题 |
| 2026-07-13 | 整理本文档 |
10. 多语言扩展:西班牙语(es)与葡萄牙语(pt)
本节记录 2026-08-28 为项目新增
es/pt时实际执行的操作,作为后续新增语言(ko、fr等)的直接模板。
10.1 新增语言涉及的核心文件
| 文件 | 操作 |
|---|---|
.vitepress/theme/utils/i18n.ts | useI18n() 增加语言识别、localePath 前缀、isXxx computed;t() 对未翻译语言回退英文 |
.vitepress/config.mts | SITE_META、LOCALES、localeOfPage/stripLocaleOfPage、语言检测脚本 supportedLocalePrefixes、locales 条目(含导航) |
.vitepress/theme/custom.css | 全局 .lang-es / .lang-pt 规则 |
es/、pt/ 目录 | 页面文件(英文骨架,后续逐页翻译) |
docs/i18n-guide.md | 本文档(更新支持列表、追加扩展说明) |
10.2 语言识别与路径(i18n.ts)
const localeOf = (l: string) => {
const s = (l || 'en').toLowerCase()
if (s.startsWith('zh')) return 'zh'
if (s.startsWith('ja')) return 'ja'
if (s.startsWith('es')) return 'es'
if (s.startsWith('pt')) return 'pt'
return 'en'
}t()在messages[locale]不存在时回退messages.en,避免新语言页面出现 path 占位符。localePath()新增前缀分支:es → /es、pt → /pt。
⚠️ 重要:未翻译语言(es/pt)的
t()目前返回英文。若需完整翻译,请在messages中添加es/pt区块(复制en的 key 结构)。
10.3 config.mts 需要同步的点
SITE_META[es]/SITE_META[pt](SEO title/desc)LOCALES = ['en', 'zh', 'ja', 'es', 'pt']localeOfPage()/stripLocaleOfPage()增加前缀- 内联语言检测脚本:
var supportedLocalePrefixes = ['zh', 'ja', 'es', 'pt']; locales增加es/pt条目(label、lang、link、themeConfig.nav)PAGE_SEO可按需补充es/pt的页级 SEO(可后补)
10.4 页面骨架
以 ja/ 的文件清单为模板,将英文根目录同名 .md 复制到新语言目录:
# 伪代码:对 ja/ 下每个相对路径 rel,
# 若根目录存在 rel 则复制到 es/rel(英文内容),否则复制 ja/rel 占位
for rel in $(find ja -name '*.md' | sed 's#^ja/##'); do
src=""; [ -f "$rel" ] && src="$rel" || src="ja/$rel"
for lang in es pt; do mkdir -p "$(dirname "$lang/$rel")"; cp "$src" "$lang/$rel"; done
done⚠️ 首页 index.md 必须重定向到对应语言首页(参考
es/index.md使用window.location.replace('/es/home')),不能沿用英文 meta refresh(否则跳回/home)。
10.5 全局 CSS
.es { display: none !important; }
.pt { display: none !important; }
.lang-es .es { display: revert !important; }
.lang-es .en { display: none !important; }
.lang-pt .pt { display: revert !important; }
.lang-pt .en { display: none !important; }⚠️ 记得在
.lang-zh/.lang-ja规则中补上.es/.pt的隐藏,避免跨语言串显。
11. 新增语言检查清单(Quick Start)
以下为每次新增语言的最终核对清单:
基础设施
- [ ]
i18n.ts:localeOf识别新语言 - [ ]
i18n.ts:localePath前缀 - [ ]
i18n.ts:新增isXxxcomputed(如需) - [ ]
i18n.ts:t()英文回退(未翻译时不显示占位符) - [ ]
custom.css:全局.lang-xx规则 + 其他语言隐藏新语言
配置
- [ ]
config.mts:SITE_META[xx] - [ ]
config.mts:LOCALES - [ ]
config.mts:localeOfPage/stripLocaleOfPage - [ ]
config.mts:supportedLocalePrefixes(语言检测脚本) - [ ]
config.mts:locales条目(label/lang/link/nav)
页面
- [ ] 新语言目录(
xx/)已创建,90+ 页面就绪 - [ ]
xx/index.md重定向到/xx/home - [ ] 页面内容已翻译(首版可英文骨架)
验证
- [ ]
npm run docs:build无编译错误 - [ ]
/es/、/pt/首页可访问 - [ ] 顶部语言切换器显示 Español / Português
- [ ] 导航链接、侧边栏、登录页正常
- [ ] 切换语言后回退显示英文(未翻译部分)
后续增量(可选,完善翻译)
- [ ]
messages中添加es/pt完整翻译区块 - [ ] 组件模式 B(
.en/.zh/.jaspan)为每个 span 增加.es/.pt - [ ] 组件模式 C(
v-if isChinese/isJapanese)增加isSpanish/isPortuguese分支 - [ ]
L()辅助函数增加 es/pt 参数与数据字段 - [ ]
PAGE_SEO补全新语言页级 SEO