跳到主要内容

Tolgee & Flutter CI/CD 最佳实践

· 阅读需 7 分钟

Tolgee + Flutter CI/CD 最佳实践

核心原则:代码侧提取字符串 → Tolgee平台翻译 → CI构建前拉取已翻译ARB → 校验翻译完整性 → 打包;区分「开发侧推送key」和「构建侧拉取译文」,不要在CI流水线随意覆盖Tolgee源,密钥全部放在CI Secrets,禁止提交到Git。

Flutter使用原生 .arb 文件作为本地化源,Tolgee原生支持ARB,通过 Tolgee CLI 完成自动化;有两种大模式:

  1. 静态ARB模式(推荐,最稳定):CI构建前拉取ARB到本地,打包进App;适合绝大多数Flutter项目。
  2. 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包。

流水线阶段​

  1. Checkout代码
  2. 安装Tolgee CLI(npx tolgee / npm全局)
  3. [可选] 提取新key校验:tolgee extract,检查是否新增key;只校验,不自动push
  4. 拉取翻译文件:tolgee pull,输出到 lib/l10n(Flutter arb目录)
  5. 本地化质量门禁(重点)
    • 校验翻译覆盖率(可写脚本,未翻译达到阈值阻断构建)
    • ARB语法校验,防止非法json打断flutter gen-l10n
    • 检查缺失占位符、变量不匹配
  6. Flutter 本地化生成:flutter gen-l10n
  7. flutter analyze / test
  8. 构建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

四、安全最佳实践​

  1. Tolgee API Key 必须放入CI Secrets,禁止提交代码仓库
    • 区分权限:CI使用只读API Key(pull only);开发本地使用带写入权限的key。
    • 不要使用管理员密钥做CI。
  2. 不要把ARB文件全部提交Git(可选方案)
    • 方案A(推荐):Git只提交模板 app_en.arb;其余语言ARB由CI拉取,不提交到Git,避免翻译冲突。
    • 方案B:全部ARB提交Git,适合小团队;但必须CI拉取后对比,如有差异阻断PR,防止人工修改ARB和Tolgee平台不一致。
  3. 自托管Tolgee:在CI环境配置环境变量 TOLGEE_API_URL 指向你的服务地址。

五、质量门禁与校验脚本(推荐)​

CI拉取ARB之后,增加自动化校验:

  1. 翻译覆盖率检查:例如生产构建要求 ≥95%翻译完成,不达标直接失败。
  2. 占位符一致性:检查所有语言 {variable} 和源语言完全一致,防止文案缺失变量导致App崩溃。
  3. Key废弃检测:使用 tolgee tag 识别代码已经删除、但还留在Tolgee平台的key,标记deprecated,定期清理。
  4. 禁止硬编码字符串: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。

七、常见坑 & 避坑​

  1. ❌ CI流水线 tolgee push --force-mode override:会覆盖翻译人员在Tolgee平台已修改译文,灾难。
  2. ❌ 开发本地忘记 tolgee extract,新增字符串不会同步到Tolgee,漏翻译。
  3. ❌ ARB文件手动修改,和Tolgee平台源不一致,双向冲突。
  4. ❌ CI没有校验翻译覆盖率,直接打包上线大量未翻译占位符。
  5. ❌ Tolgee CLI版本不固定,CI自动升级CLI,行为变更导致构建失败 → 锁定CLI版本号。

八、GitLab CI / Jenkins 适配要点​

逻辑完全一致,只是yaml语法:

  1. 配置环境变量 TOLGEE_API_KEY / TOLGEE_PROJECT_ID 在CI变量(保护掩码)
  2. 安装node → 安装固定版本 @tolgee/cli
  3. 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集成示例代码。