localize

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Localize App or Component

应用或组件本地化

Workflow Checklist

工作流检查清单

- [ ] 1. Extract hardcoded strings
- [ ] 2. Replace with t() calls in source files
- [ ] 3. Add English translations to en/translation.json
- [ ] 4. Sync translations across languages
- [ ] 5. Machine translate [TODO] keys
- [ ] 6. Validate coverage
- [ ] 1. 提取硬编码字符串
- [ ] 2. 在源文件中替换为t()调用
- [ ] 3. 将英文翻译添加到en/translation.json
- [ ] 4. 跨语言同步翻译内容
- [ ] 5. 机器翻译标记为[TODO]的键
- [ ] 6. 校验翻译覆盖率

Step 1: Extract Hardcoded Strings

步骤1:提取硬编码字符串

bash
bun run scripts/extract-strings.ts --pattern [PATTERN]
bash
bun run scripts/extract-strings.ts --pattern [PATTERN]

Step 2: Replace Strings with t() Calls

步骤2:将字符串替换为t()调用

For each component:
  1. Add import:
    import { useTranslation } from "react-i18next";
  2. Add hook:
    const { t } = useTranslation();
  3. Replace strings:
    t("apps.[appName].category.key")
  4. Add
    t
    to dependency arrays for
    useMemo
    /
    useCallback
针对每个组件:
  1. 添加导入:
    import { useTranslation } from "react-i18next";
  2. 引入Hook:
    const { t } = useTranslation();
  3. 替换字符串:
    t("apps.[appName].category.key")
  4. t
    添加到
    useMemo
    /
    useCallback
    的依赖数组中

Key Structure

键结构

apps.[appName].menu.*        # Menu labels
apps.[appName].dialogs.*     # Dialog titles/descriptions
apps.[appName].status.*      # Status messages
apps.[appName].ariaLabels.*  # Accessibility labels
apps.[appName].help.*        # Help items (auto-translated)
apps.[appName].menu.*        # 菜单标签
apps.[appName].dialogs.*     # 弹窗标题/描述
apps.[appName].status.*      # 状态消息
apps.[appName].ariaLabels.*  # 无障碍标签
apps.[appName].help.*        # 帮助项(自动翻译)

Common Patterns

常见模式

tsx
// Basic
t("apps.ipod.menu.file")

// With variables
t("apps.ipod.status.trackCount", { count: 5 })

// Conditional
isPlaying ? t("pause") : t("play")

// With symbol prefix
`${t("apps.ipod.menu.shuffle")}`
tsx
// 基础用法
t("apps.ipod.menu.file")

// 带变量
t("apps.ipod.status.trackCount", { count: 5 })

// 条件判断
isPlaying ? t("pause") : t("play")

// 带符号前缀
`${t("apps.ipod.menu.shuffle")}`

Step 3: Add English Translations

步骤3:添加英文翻译

Add to
src/lib/locales/en/translation.json
:
json
{
  "apps": {
    "ipod": {
      "menu": { "file": "File", "addSong": "Add Song..." },
      "dialogs": { "clearLibraryTitle": "Clear Library" },
      "status": { "shuffleOn": "Shuffle ON" }
    }
  }
}
添加到
src/lib/locales/en/translation.json
json
{
  "apps": {
    "ipod": {
      "menu": { "file": "File", "addSong": "Add Song..." },
      "dialogs": { "clearLibraryTitle": "Clear Library" },
      "status": { "shuffleOn": "Shuffle ON" }
    }
  }
}

Step 4: Sync Across Languages

步骤4:跨语言同步

bash
bun run scripts/sync-translations.ts --mark-untranslated
Adds missing keys to all language files, marked with
[TODO]
.
bash
bun run scripts/sync-translations.ts --mark-untranslated
将缺失的键添加到所有语言文件中,标记为
[TODO]

Step 5: Machine Translate

步骤5:机器翻译

bash
bun run scripts/machine-translate.ts
Requires
GOOGLE_GENERATIVE_AI_API_KEY
env variable.
bash
bun run scripts/machine-translate.ts
需要配置
GOOGLE_GENERATIVE_AI_API_KEY
环境变量。

Step 6: Validate

步骤6:校验

bash
bun run scripts/find-untranslated-strings.ts
bash
bun run scripts/find-untranslated-strings.ts

Component Guidelines

组件指南

ComponentWhat to translate
Menu barsAll labels, items, submenus
DialogsTitles, descriptions, button labels
Status
showStatus()
calls, toasts
Help itemsAuto-translated via
useTranslatedHelpItems
组件需翻译内容
菜单栏所有标签、菜单项、子菜单
弹窗标题、描述、按钮标签
状态
showStatus()
调用、toast通知
帮助项通过
useTranslatedHelpItems
自动翻译

Notes

注意事项

  • Emoji/symbols (♪, ✓) can stay hardcoded
  • Help items use pattern:
    apps.[appName].help.[key].title/description
  • Include
    t
    in dependency arrays when used in
    useMemo
    /
    useCallback
  • 表情/符号(♪, ✓)可以保留硬编码
  • 帮助项使用格式:
    apps.[appName].help.[key].title/description
  • useMemo
    /
    useCallback
    中使用
    t
    时,需将其加入依赖数组