Tolgee & Flutter CI/CD 最佳实践
· 阅读需 7 分钟
Tolgee + Flutter CI/CD 最佳实践
核心原则:代码侧提取字符串 → Tolgee平台翻译 → CI构建前拉取已翻译ARB → 校验翻译完整性 → 打包;区分「开发侧推送key」和「构建侧拉取译文」,不要在CI流水线随意覆盖Tolgee源,密钥全部放在CI Secrets,禁止提交到Git。
Flutter使用原生 .arb 文件作为本地化源,Tolgee原生支持ARB,通过 Tolgee CLI 完成自动化;有两种大模式:
- 静态ARB模式(推荐,最稳定):CI构建前拉取ARB到本地,打包进App;适合绝大多数Flutter项目。
- OTA动态加载模式:打包只带基础key,App运行时从Tolgee CDN拉取译文;适合需要热更新文案,但是要配合Tolgee Flutter SDK(alpha)。
一、推荐流水线架构(GitHub Actions示例,GitLab CI同理)
分支策略
feature/*:开发本地执行tolgee extract,新增key,本地push到Tolgee;CI只做代码检查、提取校验,不自动push到Tolgee(防止脏key覆盖)。develop:合并触发,CI拉取Tolgee已翻译ARB,运行本地化校验、flutter test,构建测试包。main/release tag:正式发布流水线,拉取已审核、已翻译ARB,强制校验翻译覆盖率,构建Release包。
流水线阶段
- Checkout代码
- 安装Tolgee CLI(npx tolgee / npm全局)
- [可选] 提取新key校验:
tolgee extract,检查是否新增key;只校验,不自动push - 拉取翻译文件:
tolgee pull,输出到lib/l10n(Flutter arb目录) - 本地化质量门禁(重点)
- 校验翻译覆盖率(可写脚本,未翻译达到阈值阻断构建)
- ARB语法校验,防止非法json打断flutter gen-l10n
- 检查缺失占位符、变量不匹配
- Flutter 本地化生成:
flutter gen-l10n - flutter analyze / test
- 构建APK/AAB/IPA
⚠️ 重要:CI不要自动执行
tolgee push --force-mode override。Push操作由开发者本地执行,只在合并到develop/main时,CI可以做只读提取、打tag(标记生产key,标记废弃key)。
二、Tolgee CLI 核心命令(ARB for Flutter)
# 1. 提取代码内字符串(从dart源码提取key,生成tolgee项目元数据)
tolgee extract
# 2. 本地推送到Tolgee(开发本地执行,新增key,不会覆盖已翻译文本)
tolgee push --force-mode keep
# 3. CI构建时拉取已翻译ARB文件到flutter l10n目录
tolgee pull --path lib/l10n
# 4. CI标记生产key(main分支,可选高级能力)
tolgee tag --filter-extracted --tag production
tolgee tag --filter-not-extracted --filter-tag production --tag deprecated --untag production
--force-mode keep:只新增key,不覆盖平台已翻译内容,团队推荐。override:强制覆盖,CI严禁使用,只在迁移初始化一次性使用。
三、GitHub Actions 完整工作流示例(tolgee + flutter)
文件:.github/workflows/flutter-i18n-ci.yml
name: Flutter Tolgee I18N CI
on:
push:
branches: [develop, main]
pull_request:
branches: [develop, main]
env:
# 从Tolgee项目设置获取
TOLGEE_API_KEY: ${{ secrets.TOLGEE_API_KEY }}
TOLGEE_PROJECT_ID: ${{ secrets.TOLGEE_PROJECT_ID }}
jobs:
i18n-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js (for Tolgee CLI)
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Tolgee CLI
run: npm install -g @tolgee/cli
- name: Pull ARB translations from Tolgee
run: tolgee pull --path lib/l10n
- name: Validate arb files
run: |
# 简单校验json格式,可扩展脚本统计翻译覆盖率
for f in lib/l10n/*.arb; do jq . "$f" >/dev/null || exit 1; done
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.0'
cache: true
- name: Flutter gen-l10n generate localization dart
run: flutter gen-l10n
- name: Flutter analyze & test
run: |
flutter pub get
flutter analyze
flutter test
- name: Build release app (only on main branch)
if: github.ref == 'refs/heads/main'
run: flutter build appbundle --release
四、安全最佳实践
- Tolgee API Key 必须放入CI Secrets,禁止提交代码仓库
- 区分权限:CI使用只读API Key(pull only);开发本地使用带写入权限的key。
- 不要使用管理员密钥做CI。
- 不要把ARB文件全部提交Git(可选方案)
- 方案A(推荐):Git只提交模板
app_en.arb;其余语言ARB由CI拉取,不提交到Git,避免翻译冲突。 - 方案B:全部ARB提交Git,适合小团队;但必须CI拉取后对比,如有差异阻断PR,防止人工修改ARB和Tolgee平台不一致。
- 方案A(推荐):Git只提交模板
- 自托管Tolgee:在CI环境配置环境变量
TOLGEE_API_URL指向你的服务地址。
五、质量门禁与校验脚本(推荐)
CI拉取ARB之后,增加自动化校验:
- 翻译覆盖率检查:例如生产构建要求 ≥95%翻译完成,不达标直接失败。
- 占位符一致性:检查所有语言
{variable}和源语言完全一致,防止文案缺失变量导致App崩溃。 - Key废弃检测:使用
tolgee tag识别代码已经删除、但还留在Tolgee平台的key,标记deprecated,定期清理。 - 禁止硬编码字符串:
flutter analyze配合自定义lint规则,禁止dart代码直接写UI文本。
附加:翻译覆盖率+占位符校验Shell脚本
文件:scripts/i18n-validate.sh
#!/bin/bash
set -e
SOURCE_ARB="lib/l10n/app_en.arb"
MIN_COVERAGE=95
# 统计源文本key总数
SOURCE_KEYS=$(jq -r 'keys[] | select(startswith("@"))' "$SOURCE_ARB" | wc -l)
echo "Source keys count: $SOURCE_KEYS"
# 遍历所有arb
for ARB_FILE in lib/l10n/app_*.arb; do
if [[ "$ARB_FILE" == "$SOURCE_ARB" ]]; then
continue
fi
# 已翻译key
TRANSLATED=$(jq -r 'to_entries[] | select(.key | startswith("@") | not) | select(.value != "") | .key' "$ARB_FILE" | wc -l)
COVERAGE=$(echo "$TRANSLATED * 100 / $SOURCE_KEYS" | bc)
echo "$ARB_FILE coverage: ${COVERAGE}%"
if (( COVERAGE < MIN_COVERAGE )); then
echo "ERROR: $ARB_FILE coverage below threshold $MIN_COVERAGE%"
exit 1
fi
# 占位符校验,简单检测{xxx}是否匹配源文件
# 此处可扩展正则对比
done
echo "All i18n checks passed"
六、两种模式取舍
模式A:静态ARB + flutter gen-l10n(生产首选)
✅ 优点:零运行时依赖、类型安全、编译期检查、稳定,官方Flutter标准本地化方案。 ❌ 缺点:文案修改必须重新打包发版,不能热更新。
模式B:Tolgee Flutter SDK OTA(适合营销文案热更新)
✅ 优点:无需打包,Tolgee平台改文案App实时生效,支持上下文in-context翻译。 ❌ 缺点:SDK还在alpha;增加网络依赖;无法编译期校验文本;需要缓存策略、离线兜底ARB。
七、常见坑 & 避坑
- ❌ CI流水线
tolgee push --force-mode override:会覆盖翻译人员在Tolgee平台已修改译文,灾难。 - ❌ 开发本地忘记
tolgee extract,新增字符串不会同步到Tolgee,漏翻译。 - ❌ ARB文件手动修改,和Tolgee平台源不一致,双向冲突。
- ❌ CI没有校验翻译覆盖率,直接打包上线大量未翻译占位符。
- ❌ Tolgee CLI版本不固定,CI自动升级CLI,行为变更导致构建失败 → 锁定CLI版本号。
八、GitLab CI / Jenkins 适配要点
逻辑完全一致,只是yaml语法:
- 配置环境变量
TOLGEE_API_KEY/TOLGEE_PROJECT_ID在CI变量(保护掩码) - 安装node → 安装固定版本
@tolgee/cli tolgee pull→ arb校验 →flutter gen-l10n→ flutter构建
九、最小落地检查清单
- Tolgee项目创建,ARB格式开启
- 开发本地配置tolgee,可extract/push
- CI配置只读Tolgee API Key
- CI构建前自动pull arb
- CI校验ARB语法、翻译覆盖率
- CI自动执行
flutter gen-l10n - PR合并前必须过i18n检查
- 禁止CI自动push/override Tolgee翻译
可选扩展:GitLab CI完整yml、Tolgee Flutter SDK OTA集成示例代码。