cherry-studio/docs/technical/how-to-i18n-en.md
Phantom 6cc29c5005
chore(i18n): forced nested structure to support i18n ally (#8457)
* chore(i18n): 更新i18n文件为嵌套结构以适应插件

* feat(i18n): 添加自动翻译脚本处理待翻译文本

添加自动翻译脚本auto-translate-i18n.ts,用于处理以[to be translated]开头的待翻译文本
在package.json中添加对应的运行命令auto:i18n

* chore(i18n): 更新嵌套结构

* chore(i18n): 更新多语言翻译文件并改进翻译逻辑

更新了多个语言的翻译文件,替换了"[to be translated]"标记为实际翻译内容
改进auto-translate-i18n.ts中的翻译逻辑,添加错误处理和日志输出
部分数组格式的翻译描述自动改为对象格式

* fix(i18n): 修复嵌套结构检查并改进错误处理

添加对嵌套结构中使用点符号的检查,确保使用严格嵌套结构
改进错误处理,在检查失败时输出更清晰的错误信息

* fix(测试): 更新下载失败测试中的翻译键名

* test(下载): 移除重复的下载失败翻译并更新测试

* feat(eslint): 添加规则,警告不建议在t()函数中使用模板字符串

* style: 使用单引号替换模板字符串中的反引号

* docs(.vscode): 添加i18n-ally扩展推荐到vscode配置

* fix: 在自动翻译脚本中停止进度条显示

确保在脚本执行完成后正确停止进度条,避免控制台输出混乱

* fix(i18n): 修复模型列表添加确认对话框的翻译键名

更新多语言文件中模型管理部分的翻译结构,将"add_listed"从字符串改为包含"confirm"和"key"的对象
同时修正EditModelsPopup组件中对应的翻译键引用

* chore: 注释掉i18n-ally命名空间配置

* docs: 添加国际化(i18n)最佳实践文档

添加中英文双语的技术文档,详细介绍项目中的i18n实现方案、工具链和最佳实践
包含i18n ally插件使用指南、自动化脚本说明以及代码规范要求

* docs(国际化): 更新i18n文档中的键名格式示例

将文档中错误的flat格式示例从下划线命名改为点分隔命名,以保持一致性

* refactor(i18n): 统一翻译键名从.key后缀改为.label后缀

* chore(i18n): sort

* refactor(locales): 使用 Object.fromEntries 重构 locales 对象

* feat(i18n): 添加机器翻译的语言支持

新增希腊语、西班牙语、法语和葡萄牙语的机器翻译支持,并调整语言资源加载顺序
2025-07-25 17:36:04 +08:00

5.0 KiB

How to Do i18n Gracefully

Warning

This document is machine translated from Chinese. While we strive for accuracy, there may be some imperfections in the translation.

Enhance Development Experience with the i18n Ally Plugin

i18n Ally is a powerful VSCode extension that provides real-time feedback during development, helping developers detect missing or incorrect translations earlier.

The plugin has already been configured in the project — simply install it to get started.

Advantages During Development

  • Real-time Preview: Translated texts are displayed directly in the editor.
  • Error Detection: Automatically tracks and highlights missing translations or unused keys.
  • Quick Navigation: Jump to key definitions with Ctrl/Cmd + click.
  • Auto-completion: Provides suggestions when typing i18n keys.

Demo

demo-1

demo-2

demo-3

i18n Conventions

Avoid Flat Structure at All Costs

Never use flat structures like "add.button.tip": "Add". Instead, adopt a clear nested structure:

// Wrong - Flat structure
{
  "add.button.tip": "Add",
  "delete.button.tip": "Delete"
}

// Correct - Nested structure
{
  "add": {
    "button": {
      "tip": "Add"
    }
  },
  "delete": {
    "button": {
      "tip": "Delete"
    }
  }
}

Why Use Nested Structure?

  1. Natural Grouping: Related texts are logically grouped by their context through object nesting.
  2. Plugin Requirement: Tools like i18n Ally require either flat or nested format to properly analyze translation files.

Avoid Template Strings in t()

We strongly advise against using template strings for dynamic interpolation. While convenient in general JavaScript development, they cause several issues in i18n scenarios.

1. Plugin Cannot Track Dynamic Keys

Tools like i18n Ally cannot parse dynamic content within template strings, resulting in:

  • No real-time preview
  • No detection of missing translations
  • No navigation to key definitions
// Not recommended - Plugin cannot resolve
const message = t(`fruits.${fruit}`);

2. No Real-time Rendering in Editor

Template strings appear as raw code instead of the final translated text in IDEs, degrading the development experience.

3. Harder to Maintain

Since the plugin cannot track such usages, developers must manually verify the existence of corresponding keys in language files.

const fruitLabels = {
  apple: t('fruits.apple'),
  banana: t('fruits.banana')
} as const

const fruit = getFruit()

const label = fruitLabels[fruit]

By avoiding template strings, you gain better developer experience, more reliable translation checks, and a more maintainable codebase.

Automation Scripts

The project includes several scripts to automate i18n-related tasks:

check:i18n - Validate i18n Structure

This script checks:

  • Whether all language files use nested structure
  • For missing or unused keys
  • Whether keys are properly sorted
yarn check:i18n

sync:i18n - Synchronize JSON Structure and Sort Order

This script uses zh-cn.json as the source of truth to sync structure across all language files, including:

  1. Adding missing keys, with placeholder [to be translated]
  2. Removing obsolete keys
  3. Sorting keys automatically
yarn sync:i18n

auto:i18n - Automatically Translate Pending Texts

This script fills in texts marked as [to be translated] using machine translation.

Typically, after adding new texts in zh-cn.json, run sync:i18n, then auto:i18n to complete translations.

Before using this script, set the required environment variables:

API_KEY="sk-xxx"
BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1/"
MODEL="qwen-plus-latest"

Alternatively, add these variables directly to your .env file.

yarn auto:i18n

update:i18n - Object-level Translation Update

Updates translations in language files under src/renderer/src/i18n/translate at the object level, preserving existing translations and only updating new content.

Not recommended — prefer auto:i18n for translation tasks.

yarn update:i18n

Workflow

  1. During development, first add the required text in zh-cn.json
  2. Confirm it displays correctly in the Chinese environment
  3. Run yarn sync:i18n to propagate the keys to other language files
  4. Run yarn auto:i18n to perform machine translation
  5. Grab a coffee and let the magic happen!

Best Practices

  1. Use Chinese as Source Language: All development starts in Chinese, then translates to other languages.
  2. Run Check Script Before Commit: Use yarn check:i18n to catch i18n issues early.
  3. Translate in Small Increments: Avoid accumulating a large backlog of untranslated content.
  4. Keep Keys Semantically Clear: Keys should clearly express their purpose, e.g., user.profile.avatar.upload.error