cherry-studio/docs/zh/guides/i18n.md
George·Dong 2a31fa2ad5
refactor: switch yarn to pnpm (#12260)
* refactor: switch workflows from yarn to pnpm

Replace Yarn usage with pnpm in CI workflows to standardize package
management and leverage pnpm's store/cache behavior.

- Use pnpm/action-setup to install pnpm (v) instead of enabling corepack
  and preparing Yarn.
- Retrieve pnpm store path and update cache actions to cache the pnpm
  store and use pnpm-lock.yaml for cache keys and restores.
- Replace yarn commands with pnpm equivalents across workflows:
  install, i18n:sync/translate, format, build:* and tsx invocation.
- Avoid committing lockfile changes by resetting pnpm-lock.yaml instead
  of yarn.lock when checking for changes.
- Update install flags: use pnpm install --frozen-lockfile / --install
  semantics where appropriate.

These changes unify dependency tooling, improve caching correctness,
and ensure CI uses pnpm-specific lockfile and cache paths.

* build: switch pre-commit hook to pnpm lint-staged

Update .husky/pre-commit to run pnpm lint-staged instead of yarn.
This aligns the pre-commit hook with the project's package manager
and ensures lint-staged runs using pnpm's environment and caching.

* chore(ci): remove pinned pnpm version from GH Action steps

Remove the explicit `with: version: 9` lines from multiple GitHub Actions workflows
(auto-i18n.yml, nightly-build.yml, pr-ci.yml, update-app-upgrade-config.yml,
sync-to-gitcode.yml, release.yml). The workflows still call `pnpm/action-setup@v4`
but no longer hardcode a pnpm version.

This simplifies maintenance and allows the action to resolve an appropriate pnpm
version (or use its default) without needing updates whenever the pinned
version becomes outdated. It reduces churn when bumping pnpm across CI configs
and prevents accidental pin drift between workflow files.

* build: Update pnpm to 10.27.0 and add onlyBuiltDependencies config

* Update @cherrystudio/openai to 6.15.0 and consolidate overrides

* Add @langchain/core to overrides

* Add override for openai-compatible 1.0.27

* build: optimize pnpm config and add missing dependencies

- Comment out shamefully-hoist in .npmrc for better pnpm compatibility
- Add React-related packages to optimizeDeps in electron.vite.config.ts
- Add missing peer dependencies and packages that were previously hoisted

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* build: refine pnpm configuration and dependency management

- Simplify .npmrc to only essential electron mirror config
- Move platform-specific dependencies to devDependencies
- Pin sharp version to 0.34.3 for consistency
- Update sharp-libvips versions to 1.2.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* reduce app size

* format

* build: remove unnecessary disableOxcRecommendation option from react plugin configuration

* docs: Replace yarn commands with pnpm in documentation and scripts

* Revert "build: optimize pnpm config and add missing dependencies"

This reverts commit acffad31f8.

* build: import dependencies from yarn.lock

* build: Add some phantom dependencies and reorganize dependencies

* build: Keep consistent by removing types of semver

It's not in the previous package.json

* build: Add some phantom dependencies

Keep same version with yarn.lock

* build: Add form-data dependency version 4.0.4

* Add chalk dependency

* build: downgrade some dependencies

Reference: .yarn-state-copy.yml. These phantom dependencies should use top-level package of that version in node_modules

* build: Add phantom dependencies

* build: pin tiptap dependencies to exact versions

Ensure consistent dependency resolution by removing caret ranges and pinning all @tiptap packages to exact version 3.2.0

* chore: pin embedjs dependencies to exact versions

* build: pin @modelcontextprotocol/sdk to exact version 1.23.0

Remove caret from version specifier to prevent automatic upgrades and ensure consistent dependencies

* chore: update @types/node dependency to 22.17.2

Update package.json and pnpm-lock.yaml to use @types/node version 22.17.2 instead of 22.19.3 to maintain consistency across dependencies

* build: move some dependencies to dev deps and pin dependency versions to exact numbers

Remove caret (^) from version ranges to ensure consistent dependency resolution across environments

* chore: move dependencies from prod to dev and update lockfile

Move @ant-design/icons, chalk, form-data, and open from dependencies to devDependencies
Update pnpm-lock.yaml to reflect dependency changes

* build: update package dependencies

- Add new dependencies: md5, @libsql/win32-x64-msvc, @strongtz/win32-arm64-msvc, bonjour-service, emoji-picker-element-data, gray-matter, js-yaml
- Remove redundant dependencies from devDependencies

* build: add cors, katex and pako dependencies

add new dependencies to support cross-origin requests, mathematical notation rendering and data compression

* move some js deps to dev deps

* test: update snapshot tests for Spinner and InputEmbeddingDimension

* chore: exclude .zed directory from biome formatting

* Update @ai-sdk/openai-compatible patch hash

* chore: update @kangfenmao/keyv-storage to version 0.1.3 in package.json and pnpm-lock.yaml

---------

Co-authored-by: icarus <eurfelux@gmail.com>
Co-authored-by: beyondkmp <beyondkmp@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-01-05 22:16:34 +08:00

4.5 KiB
Raw Blame History

如何优雅地做好 i18n

使用 i18n ally 插件提升开发体验

i18n ally 是一个强大的 VSCode 插件,它能在开发阶段提供实时反馈,帮助开发者更早发现文案缺失和错译问题。

项目中已经配置好了插件设置,直接安装即可。

开发时优势

  • 实时预览:翻译文案会直接显示在编辑器中
  • 错误检测:自动追踪标记出缺失的翻译或未使用的 key
  • 快速跳转:可通过 key 直接跳转到定义处Ctrl/Cmd + click)
  • 自动补全:输入 i18n key 时提供自动补全建议

效果展示

demo-1

demo-2

demo-3

i18n 约定

绝对避免使用 flat 格式

绝对避免使用 flat 格式,如"add.button.tip": "添加"。应采用清晰的嵌套结构:

// 错误示例 - flat结构
{
  "add.button.tip": "添加",
  "delete.button.tip": "删除"
}

// 正确示例 - 嵌套结构
{
  "add": {
    "button": {
      "tip": "添加"
    }
  },
  "delete": {
    "button": {
      "tip": "删除"
    }
  }
}

为什么要使用嵌套结构

  1. 自然分组:通过对象结构天然能将相关上下文的文案分到一个组别中
  2. 插件要求i18n ally 插件需要嵌套或 flat 格式其一的文件才能正常分析

避免在t()中使用模板字符串

强烈建议避免使用模板字符串进行动态插值。虽然模板字符串在 JavaScript 开发中非常方便,但在国际化场景下会带来一系列问题。

  1. 插件无法跟踪 i18n ally 等工具无法解析模板字符串中的动态内容,导致:

    • 无法正确显示实时预览
    • 无法检测翻译缺失
    • 无法提供跳转到定义的功能
    // 不推荐 - 插件无法解析
    const message = t(`fruits.${fruit}`);
    
  2. 编辑器无法实时渲染 在 IDE 中,模板字符串会显示为原始代码而非最终翻译结果,降低了开发体验。

  3. 更难以维护 由于插件无法跟踪这样的文案,编辑器中也无法渲染,开发者必须人工确认语言文件中是否存在相应的文案。

推荐做法

为了避免键的缺失,所有需要动态翻译的文本都应当先维护一个FooKeyMap,再通过函数获取翻译文本。

例如:

// src/renderer/src/i18n/label.ts
const themeModeKeyMap = {
  dark: "settings.theme.dark",
  light: "settings.theme.light",
  system: "settings.theme.system",
} as const;

export const getThemeModeLabel = (key: string): string => {
  return themeModeKeyMap[key] ? t(themeModeKeyMap[key]) : key;
};

通过避免模板字符串,可以获得更好的开发体验、更可靠的翻译检查以及更易维护的代码库。

自动化脚本

项目中有一系列脚本来自动化 i18n 相关任务:

i18n:check - 检查 i18n 结构

此脚本会检查:

  • 所有语言文件是否为嵌套结构
  • 是否存在缺失的 key
  • 是否存在多余的 key
  • 是否已经有序
pnpm i18n:check

i18n:sync - 同步 json 结构与排序

此脚本以zh-cn.json文件为基准,将结构同步到其他语言文件,包括:

  1. 添加缺失的键。缺少的翻译内容会以[to be translated]标记
  2. 删除多余的键
  3. 自动排序
pnpm i18n:sync

i18n:translate - 自动翻译待翻译文本

次脚本自动将标记为待翻译的文本通过机器翻译填充。

通常,在zh-cn.json中添加所需文案后,执行i18n:sync即可自动完成翻译。

使用该脚本前,需要配置环境变量,例如:

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

你也可以通过直接编辑.env文件来添加环境变量。

pnpm i18n:translate

工作流

  1. 开发阶段,先在zh-cn.json中添加所需文案
  2. 确认在中文环境下显示无误后,使用pnpm i18n:sync将文案同步到其他语言文件
  3. 使用pnpm i18n:translate进行自动翻译
  4. 喝杯咖啡,等翻译完成吧!

最佳实践

  1. 以中文为源语言:所有开发首先使用中文,再翻译为其他语言
  2. 提交前运行检查脚本:使用pnpm i18n:check检查 i18n 是否有问题
  3. 小步提交翻译:避免积累大量未翻译文本
  4. 保持 key 语义明确key 应能清晰表达其用途,如user.profile.avatar.upload.error