Lingo.dev CLI 可通过已配置的 localization engine 翻译 Xcode 的 String Catalogs(.xcstrings)。String Catalogs 是 Apple 在 Xcode 15 中推出的现代本地化格式,可将所有语言统一存储在一个 JSON 文件中。CLI 会直接原地更新这个文件——无需再按语言环境维护单独目录。
本指南将带你完整走通 iOS 应用本地化流程:配置 CLI、本地执行翻译,以及结合 GitHub Actions 实现自动化,让每次 push 都能同步交付最新翻译。
演示仓库
你可以克隆或 fork lingodotdev/ios-app-localization-example 跟着一起操作。该仓库提供了一个可直接运行的 Xcode 项目,其中包含 String Catalogs、Lingo.dev CLI 配置和 GitHub Actions 工作流。
String Catalogs 如何工作#
在 Xcode 15 之前,iOS 本地化需要在不同的 [locale].lproj/ 目录下分别管理 .strings 和 .stringsdict 文件。String Catalogs 用单个 Localizable.xcstrings 文件取代了这种方式,并由 Xcode 自动维护。
当你在 SwiftUI 或 UIKit 中将字符串标记为可本地化时,Xcode 会在构建过程中自动识别,并将其加入 String Catalog。每个条目都会记录源字符串、各个已配置语言环境下的翻译,以及一个可选注释字段,用来为译者提供上下文。
| 对比项 | 旧版 .strings | String Catalogs .xcstrings |
|---|---|---|
| 文件数量 | 每个语言环境、每个表各一份 | 单个文件,包含所有语言环境 |
| 格式 | 键值文本 | 结构化 JSON |
| 复数支持 | 单独的 .stringsdict 文件 | 内建复数规则 |
| Xcode 集成 | 手动导出/导入 | 自动识别 |
| 译者注释 | 不支持 | 每个条目都有注释字段 |
CLI 的 xcode-xcstrings bucket 类型会解析这套 JSON 结构,通过 localization engine 翻译每个条目,并将结果写回同一个文件——同时保留注释、复数规则和元数据。
前提条件#
创建 localization engine
每次运行 CLI,内容都会经过一个 localization engine——也就是决定采用哪个 LLM 模型、glossary、brand voice 和 instructions 的配置。你可以在 Lingo.dev dashboard 中创建一个,并生成 API key。
确认 Node.js 版本
CLI 需要 Node.js 18 或更高版本:
node -v在 Xcode 中启用本地化
在 Xcode 项目中,进入 Project Settings > Info > Localizations,添加目标语言。你每添加一个语言环境,Xcode 就会为其创建对应的 String Catalog 条目。更多细节可参考 Apple 的 localization documentation。
配置 CLI#
在项目根目录创建一个 i18n.json 文件。xcode-xcstrings bucket 会告诉 CLI 按 String Catalog 格式解析,并原地更新该文件:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"xcode-xcstrings": {
"include": ["MyApp/Localizable.xcstrings"]
}
}
}由于 String Catalogs 会将所有语言环境统一存储在一个文件中,因此 include 模式里不需要 [locale] 占位符。CLI 会读取源语言条目,完成翻译后,再将所有目标语言写回同一个 .xcstrings 文件。
多个 String Catalogs
如果项目中使用了多个 String Catalog 文件(例如每个 framework target 一份),请在 include 数组中将它们全部列出:
{
"buckets": {
"xcode-xcstrings": {
"include": [
"MyApp/Localizable.xcstrings",
"MyAppWidgets/Localizable.xcstrings"
]
}
}
}本地执行翻译#
设置好 API key 后,运行 CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI 会读取你的 String Catalog,借助 lockfile 识别尚未翻译的条目,通过 localization engine 翻译增量内容,并将结果写回 .xcstrings 文件。随后在 Xcode 中打开该文件,即可看到每个已配置语言环境的翻译已自动填入。
如果你想在开发阶段只处理特定语言环境:
npx lingo.dev@latest run --target-locale es译者注释#
String Catalogs 支持为每个条目添加注释字段,CLI 会在发起翻译请求时一并带上。这些注释能为 localization engine 提供上下文——帮助消除术语歧义、明确语气,或说明字符串在 UI 中出现的位置。
在 Xcode 中,选中 String Catalog 编辑器里的某个字符串,然后在检查器面板中添加注释。该注释会存储在 .xcstrings JSON 中:
{
"sourceLanguage": "en",
"strings": {
"Set": {
"comment": "Refers to a collection of items, not the verb",
"localizations": { }
}
}
}CLI 会将这条注释与字符串一起发送,从而引导模型做出更准确的理解。比如 “Set” 如果缺少上下文,在很多语言里可能会被翻成动词;而注释可以消除这种歧义。更多用法可参阅 Translator Notes。
复数#
String Catalogs 基于 CLDR plural rules 原生支持复数形式。当你在 Xcode 中定义复数变体时,String Catalog 会为目标语言所需的各个复数类别存储规则(zero、one、two、few、many、other)。
CLI 会在翻译过程中保留这一结构,并为每个目标语言环境生成正确的复数类别。英语只用两类(one 和 other),但阿拉伯语需要六类,波兰语需要四类,日语则只需要一类。localization engine 会自动处理这些差异。
借助 GitHub Actions 实现自动化#
在 .github/workflows/translate.yml 添加一个工作流文件,让每次 push 时都能自动执行翻译:
翻译结果直接提交到 main——几乎零摩擦,特别适合小团队:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}在 GitHub 仓库的 Settings > Secrets and variables > Actions 中,将你的 API key 保存为 LINGODOTDEV_API_KEY。
部署前先校验#
可使用 --frozen 标志作为部署门禁,确保未翻译字符串不会进入生产环境。如果仍有条目待翻译,CLI 会以非零状态码退出:
npx lingo.dev@latest run --frozen可以在构建前把它作为单独的 CI 步骤加入:
- name: Verify translations
run: npx lingo.dev@latest run --frozen