Lingo.dev CLI 会通过已配置好的 localization engine 翻译 Android 的 字符串资源(strings.xml)。CLI 的 android bucket 类型原生支持 <resources>、<string>、<string-array> 和 <plurals> 元素,既能保留 XML 结构,也能为每个目标语言环境生成正确的复数类别。
这份指南会带你完整走通 Android 应用本地化流程:配置 CLI、本地翻译,以及结合 GitHub Actions 实现自动化,让每次 push 都能随代码一同交付最新翻译。
示例仓库
你可以克隆或 fork lingodotdev/android-app-localization-example 跟着实操。这个仓库包含一个可运行的 Android 项目,以及字符串资源、Lingo.dev CLI 配置和 GitHub Actions 工作流。
Android 本地化如何工作#
Android 采用 资源目录约定,为每个语言环境使用独立的 values-[locale]/ 目录。系统会在运行时根据设备语言设置加载对应的 strings.xml。
app/src/main/res/
values/ # Default (source) strings
strings.xml
values-es/ # Spanish
strings.xml
values-fr/ # French
strings.xml
values-ja/ # Japanese
strings.xml一个典型的 strings.xml 通常包含三类元素:
<resources>
<!-- Simple strings -->
<string name="app_name">My App</string>
<string name="welcome_message">Welcome back!</string>
<!-- String arrays -->
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
</string-array>
<!-- Plurals -->
<plurals name="items_count">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
</resources>CLI 会解析这三类元素,通过 localization engine 翻译其中内容,并将各语言环境对应的文件写入正确的 values-[locale]/ 目录。
准备工作#
创建 localization engine
每次运行 CLI,内容都会经过一个 localization engine——也就是决定使用哪个 LLM 模型、术语表、品牌语气和 指令 的配置。你可以在 Lingo.dev dashboard 中创建,并生成一个 API 密钥。
确认 Node.js 版本
CLI 需要 Node.js 18 或更高版本:
node -v准备 Android 项目
你的项目需要在 app/src/main/res/values/ 中有一个默认的 strings.xml。新建项目时,Android Studio 会自动生成这个文件。关于资源目录的设置方式,可参考 Android 的 本地化指南。
配置 CLI#
在项目根目录创建一个 i18n.json 文件。android bucket 会告诉 CLI 解析 Android XML 资源,并按语言环境分别生成文件:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"]
}
}
}[locale] 占位符会在运行时解析为每个已配置的语言环境代码。CLI 会把源语言环境代入这个模式——因此使用 source: "en" 时,它会查找 values-en/strings.xml。目标语言环境则会生成 values-es/strings.xml、values-fr/strings.xml 等文件。
打通默认语言目录#
Android 会把默认字符串放在 values/ 中(不带语言环境后缀),但 CLI 会按字面解析 [locale],因此会去查找 values-en/strings.xml。你可以创建一个符号链接,打通这两套约定:
cd app/src/main/res
ln -s values values-en这样一来,源字符串就会同时出现在 values/strings.xml(Android 期望的位置)和 values-en/strings.xml(CLI 查找的位置)。请把这个符号链接提交到仓库中——git 在 macOS 和 Linux 上原生支持跟踪符号链接。
Windows
在 Windows 上,Git 可能会根据你的配置把符号链接检出为普通文本文件。如果你使用的是 Windows,请先运行 git config core.symlinks true 再进行克隆,或者直接把 values/ 目录复制到 values-en/。
多个资源文件
如果你的项目把字符串拆分在多个文件里(例如 strings.xml 和 arrays.xml),请把它们全部列出来。由于符号链接覆盖的是整个目录,因此 values/ 中的所有文件都可以通过 values-en/ 访问:
{
"buckets": {
"android": {
"include": [
"app/src/main/res/values-[locale]/strings.xml",
"app/src/main/res/values-[locale]/arrays.xml"
]
}
}
}本地翻译#
设置好 API 密钥后,运行 CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI 会读取源 strings.xml,通过 lockfile 识别尚未翻译的条目,经由你的 localization engine 翻译增量内容,再把结果写入目标 values-[locale]/ 目录。打开任意目标文件,即可查看翻译后的字符串。
开发过程中,如果只想针对某个特定语言环境:
npx lingo.dev@latest run --target-locale es复数处理#
Android 使用 <plurals> 元素,并配合 CLDR quantity strings(zero、one、two、few、many、other)来处理复数形式。不同语言所需的复数类别不同——英语需要两类(one 和 other),俄语需要四类,阿拉伯语需要六类。
CLI 会在翻译时保留 <plurals> 结构,并为每个目标语言环境生成正确的 quantity 条目。比如一个只包含两个类别的源条目:
<plurals name="messages_count">
<item quantity="one">%d new message</item>
<item quantity="other">%d new messages</item>
</plurals>就能为每种目标语言生成正确的类别。localization engine 知道每个语言环境适用哪些 CLDR plural rules,并且只会生成该语言真正需要的类别。
键锁定#
有些字符串值在所有语言中都应保持完全一致——例如品牌名称、API 端点或格式模式。这时可以使用 key locking,直接复制这些值而不进行翻译:
{
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"],
"lockedKeys": ["app_name", "api_base_url"]
}
}
}被锁定的键会从源文件直接复制到所有目标文件,不会进入翻译流程。
用 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 仓库中,将 API 密钥以 LINGODOTDEV_API_KEY 的名称保存到 Settings > Secrets and variables > Actions。
部署前先校验#
使用 --frozen 标志作为部署门禁,确保未翻译的字符串不会进入生产环境。只要还有条目待翻译,CLI 就会以非零状态码退出:
npx lingo.dev@latest run --frozen可以在构建前把它作为单独的 CI 步骤加入:
- name: Verify translations
run: npx lingo.dev@latest run --frozen