i18n

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

i18n Skill

i18n 技能指南

Standards and workflow for internationalization. All user-visible text must use i18n.
Announce at start: "I'm using i18n skill to ensure proper internationalization."
国际化的标准与工作流。所有用户可见的文本都必须使用i18n。
开始时声明: "我正在使用i18n技能来确保正确的国际化。"

File Structure

文件结构

src/renderer/i18n/
├── index.ts              # i18next configuration
└── locales/
    ├── en-US.json        # English (primary)
    ├── zh-CN.json        # Simplified Chinese
    ├── zh-TW.json        # Traditional Chinese
    ├── ja-JP.json        # Japanese
    └── ko-KR.json        # Korean
src/renderer/i18n/
├── index.ts              # i18next 配置
└── locales/
    ├── en-US.json        # 英文(主语言)
    ├── zh-CN.json        # 简体中文
    ├── zh-TW.json        # 繁体中文
    ├── ja-JP.json        # 日语
    └── ko-KR.json        # 韩语

Key Naming Convention

键命名规范

IMPORTANT: New i18n keys MUST use flat dot-notation format.
Format:
<module>.<feature>.<detail>
重要提示:新的i18n键必须使用扁平化的点符号格式。
格式:
<模块>.<功能>.<细节>

Rules

规则

LevelDescriptionExamples
ModulePage or major feature
cron
,
chat
,
settings
,
auth
FeatureSpecific functionality
form
,
list
,
modal
,
sidebar
DetailSpecific text purpose
title
,
placeholder
,
label
,
empty
层级描述示例
模块页面或主要功能
cron
,
chat
,
settings
,
auth
功能具体功能
form
,
list
,
modal
,
sidebar
细节具体文本用途
title
,
placeholder
,
label
,
empty

Examples

示例

✓ cron.form.title
✓ cron.form.namePlaceholder
✓ cron.list.emptyState
✓ settings.llm.apiKeyRequired

✗ cronFormTitle           (missing dots)
✗ CRON.FORM.TITLE         (wrong case)
✓ cron.form.title
✓ cron.form.namePlaceholder
✓ cron.list.emptyState
✓ settings.llm.apiKeyRequired

✗ cronFormTitle           (缺少点符号)
✗ CRON.FORM.TITLE         (大小写错误)

Flat vs Nested Structure

扁平化 vs 嵌套结构

json
// ✅ GOOD - flat structure (use for NEW keys)
{
  "cron.form.title": "Create Scheduled Task",
  "cron.form.nameLabel": "Task Name",
  "cron.list.empty": "No scheduled tasks"
}

// ❌ AVOID - nested structure (legacy only, do not add new)
{
  "cron": {
    "form": {
      "title": "..."
    }
  }
}
Rationale:
  • Flat keys are searchable in codebase (see
    t('cron.form.title')
    , search directly)
  • Easier to verify sync across locale files
  • Avoids deep nesting confusion
json
// ✅ 推荐 - 扁平化结构(用于新增键)
{
  "cron.form.title": "Create Scheduled Task",
  "cron.form.nameLabel": "Task Name",
  "cron.list.empty": "No scheduled tasks"
}

// ❌ 避免 - 嵌套结构(仅用于遗留代码,请勿新增)
{
  "cron": {
    "form": {
      "title": "..."
    }
  }
}
理由:
  • 扁平化键可在代码库中直接搜索(例如
    t('cron.form.title')
    ,可直接搜索)
  • 更易验证各语言文件间的同步性
  • 避免深层嵌套带来的混淆

Common Suffixes

常见后缀

SuffixUsage
title
Section/page titles
placeholder
Input placeholders
label
Form labels
button
/
action
Button text
success
/
error
Status messages
confirm
Confirmation dialogs
empty
Empty state messages
loading
Loading states
tooltip
Tooltip text
后缀用途
title
章节/页面标题
placeholder
输入框占位符
label
表单标签
button
/
action
按钮文本
success
/
error
状态消息
confirm
确认对话框
empty
空状态消息
loading
加载状态
tooltip
提示框文本

Shared Keys

共享键

Use
common.*
for reusable text:
json
{
  "common.save": "Save",
  "common.cancel": "Cancel",
  "common.confirm": "Confirm",
  "common.delete": "Delete",
  "common.loading": "Loading..."
}
使用
common.*
定义可复用文本:
json
{
  "common.save": "Save",
  "common.cancel": "Cancel",
  "common.confirm": "Confirm",
  "common.delete": "Delete",
  "common.loading": "Loading..."
}

Adding New Text Workflow

添加新文本的工作流

Step 1: Check Existing Keys

步骤1:检查现有键

Before adding new key, search for similar existing keys:
bash
grep -r "keyword" src/renderer/i18n/locales/
添加新键前,先搜索是否存在类似的现有键:
bash
grep -r "keyword" src/renderer/i18n/locales/

Step 2: Add to ALL Locale Files

步骤2:添加至所有语言文件

CRITICAL: Must add to all 5 files simultaneously.
bash
undefined
关键要求:必须同时添加至全部5个文件。
bash
undefined

Files to update:

需要更新的文件:

src/renderer/i18n/locales/en-US.json # English text src/renderer/i18n/locales/zh-CN.json # Simplified Chinese src/renderer/i18n/locales/zh-TW.json # Traditional Chinese src/renderer/i18n/locales/ja-JP.json # Japanese src/renderer/i18n/locales/ko-KR.json # Korean
undefined
src/renderer/i18n/locales/en-US.json # 英文文本 src/renderer/i18n/locales/zh-CN.json # 简体中文 src/renderer/i18n/locales/zh-TW.json # 繁体中文 src/renderer/i18n/locales/ja-JP.json # 日语 src/renderer/i18n/locales/ko-KR.json # 韩语
undefined

Step 3: Use in Component

步骤3:在组件中使用

tsx
import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { t } = useTranslation();

  return <button>{t('module.feature.action')}</button>;
}
tsx
import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { t } = useTranslation();

  return <button>{t('module.feature.action')}</button>;
}

Step 4: Verify Sync

步骤4:验证同步性

After adding, verify all files have the new keys.
添加完成后,验证所有文件都包含新键。

Sync Checking

同步检查

Before Commit

提交前检查

Always verify key sync across all locale files:
bash
undefined
请始终验证所有语言文件间的键是否同步:
bash
undefined

Quick check - compare line counts (rough indicator)

快速检查 - 比较行数(大致指标)

wc -l src/renderer/i18n/locales/*.json
wc -l src/renderer/i18n/locales/*.json

Check for flat keys diff between en-US and zh-CN

检查en-US与zh-CN之间的扁平化键差异

diff <(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/en-US.json | sort -u)
<(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/zh-CN.json | sort -u)
undefined
diff <(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/en-US.json | sort -u)
<(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/zh-CN.json | sort -u)
undefined

Fix Sync Issues

修复同步问题

If keys are out of sync:
  1. Identify missing keys from diff output
  2. Add missing keys to appropriate files
  3. Re-run diff to verify
如果键不同步:
  1. 从差异输出中找出缺失的键
  2. 将缺失的键添加至对应文件
  3. 重新运行diff验证

Hardcoded String Detection

硬编码字符串检测

Prohibited Patterns

禁止模式

Never use hardcoded Chinese/English text in JSX:
tsx
// ❌ BAD
<span>重命名</span>
<span>Delete</span>
<button title="更多操作">...</button>
{name || '新对话'}

// ✅ GOOD
<span>{t('common.rename')}</span>
<span>{t('common.delete')}</span>
<button title={t('common.moreActions')}>...</button>
{name || t('chat.newConversation')}
请勿在JSX中使用硬编码的中文/英文文本:
tsx
// ❌ 错误示例
<span>重命名</span>
<span>Delete</span>
<button title="更多操作">...</button>
{name || '新对话'}

// ✅ 正确示例
<span>{t('common.rename')}</span>
<span>{t('common.delete')}</span>
<button title={t('common.moreActions')}>...</button>
{name || t('chat.newConversation')}

Exceptions

例外情况

Comments and internal logs are allowed:
tsx
// This is a comment, Chinese is OK
console.log('Debug info'); // OK for logs
注释和内部日志允许使用硬编码文本:
tsx
// 这是一条注释,可使用中文
console.log('Debug info'); // 日志中使用英文没问题

zh-TW Maintenance

繁体中文(zh-TW)维护

Auto-conversion Safe

可安全自动转换的术语

Most terms can be auto-converted from zh-CN:
  • 设置 → 設置
  • 删除 → 刪除
  • 确认 → 確認
大部分术语可从简体中文自动转换:
  • 设置 → 設置
  • 删除 → 刪除
  • 确认 → 確認

Manual Adjustment Required

需要手动调整的术语

Some terms need manual review:
zh-CNzh-TWNotes
视频影片Different term
软件軟體Different term
信息訊息Different term
默认預設Different term
部分术语需要手动检查调整:
简体中文繁体中文说明
视频影片术语不同
软件軟體术语不同
信息訊息术语不同
默认預設术语不同

Interpolation

插值语法

Variables

变量

json
{
  "greeting": "Hello, {{name}}!",
  "itemCount": "{{count}} items"
}
tsx
t('greeting', { name: 'User' });
t('itemCount', { count: 5 });
json
{
  "greeting": "Hello, {{name}}!",
  "itemCount": "{{count}} items"
}
tsx
t('greeting', { name: 'User' });
t('itemCount', { count: 5 });

HTML in Translations

翻译中的HTML

Use Trans component for complex markup:
tsx
import { Trans } from 'react-i18next';

<Trans i18nKey='cron.countdown'>
  Task <strong>{{ taskName }}</strong> in <span>{{ countdown }}</span>
</Trans>;
对于复杂标记,使用Trans组件:
tsx
import { Trans } from 'react-i18next';

<Trans i18nKey='cron.countdown'>
  Task <strong>{{ taskName }}</strong> in <span>{{ countdown }}</span>
</Trans>;

Quick Checklist

快速检查清单

Before submitting code with new text:
  • All user-visible text uses
    t()
    function
  • New keys use flat
    module.feature.detail
    format
  • New keys added to ALL 5 locale files
  • No hardcoded Chinese/English in JSX
  • zh-TW reviewed for term differences
  • ja-JP and ko-KR translations added (or marked TODO)
提交包含新文本的代码前,请确认:
  • 所有用户可见文本均使用
    t()
    函数
  • 新键使用扁平化的
    module.feature.detail
    格式
  • 新键已添加至全部5个语言文件
  • JSX中无硬编码的中文/英文文本
  • 繁体中文(zh-TW)术语已检查差异
  • 日语(ja-JP)和韩语(ko-KR)翻译已添加(或标记为TODO)

Common Mistakes

常见错误

MistakeCorrect
Adding key to only one fileAdd to all 5 files
Using nested structure for newUse flat
module.feature.detail
Using
t("New Chat")
Define key:
t("chat.new")
Inline Chinese in JSXUse
t()
with defined key
Forgetting interpolationUse
{{variable}}
syntax
错误修正方案
仅在一个文件中添加键添加至全部5个文件
新增键使用嵌套结构使用扁平化的
module.feature.detail
格式
使用
t("New Chat")
定义键后使用:
t("chat.new")
JSX中直接写中文使用
t()
函数调用已定义的键
忘记使用插值语法使用
{{variable}}
语法