Android 多语言自动翻译流程(一)

172 阅读3分钟

引言:解决多语言开发的痛点

在全球化应用开发中,多语言支持是必不可少的环节。但传统的多语言管理流程存在诸多痛点:

  • 响应延迟:翻译团队无法实时响应开发变更
  • 格式错误:手动编辑XML导致占位符丢失或格式错误
  • 协作低效:需要多角色协同完成翻译、审核、合并流程

本文将深入解析一个全自动化的Android多语言解决方案,揭示如何通过技术手段实现开发提交→自动翻译→资源更新→审核通知的完整闭环。

GitLab CI的精准监听:strings.xml

1.1 智能触发机制

核心配置

# .gitlab-ci.yml  
translation-check:  
  only:  
    changes:  
      - src/main/res/values/strings.xml  
  script:  
    - python translate.py  

工作原理

  1. 精准监听:GitLab Runner持续监控代码仓库变化
  2. 变更过滤:仅当values/strings.xml文件被修改时触发任务
  3. 环境隔离:在独立CI Runner中启动Python脚本

为何选择strings.xml?
这是Android应用的核心字符串资源文件,包含所有需要翻译的文本内容,是多语言系统的唯一来源

1.2 环境初始化流程

关键代码

def __init__(self):  
    # 获取CI环境变量  
    self.project_id = os.getenv('CI_PROJECT_ID')  
    self.commit_sha = os.getenv('CI_COMMIT_SHA')  
    self.source_path = 'src/main/res/values/strings.xml'  
      
    # 初始化GitLab API客户端  
    self.gl = gitlab.Gitlab(self.gitlab_url, private_token=self.private_token)  
    self.project = self.gl.projects.get(self.project_id)  

初始化步骤

  1. 环境变量获取

    • CI_PROJECT_ID:当前GitLab项目ID
    • CI_COMMIT_SHA:触发本次CI的提交哈希
    • SOURCE_STRING_PATH:字符串资源文件路径
  2. API客户端配置

    • 使用GITLAB_API_TOKEN进行认证
    • 创建GitLab项目对象用于后续操作
  3. 翻译引擎准备

    • 从环境变量获取引擎路径(DeepLX或Google)
    • 加载语言映射配置

1.3 变更检测算法

核心方法

def get_changed_strings(old_commit, new_commit, file_path):  
    # 获取Git差异  
    diff_output = subprocess.check_output(  
        ['git', 'diff', old_commit, new_commit, '--', file_path],  
        universal_newlines=True  
    )  
      
    # 修改识别正则  
    modified_pattern = re.compile(  
        r'-(.*<string [^>]*>(.*?)</string>)\n'  
        r'+(.*<string [^>]*>(.*?)</string>)'  
    )  
      
    # 新增识别正则  
    new_pattern = re.compile(  
        r'^+\s*<string name="([^"]+)"[^>]*>(.*?)</string>$'  
    )  

变更检测流程

deepseek_mermaid_20250628_378091.png

智能过滤规则

  1. 忽略纯属性变更

    <!-- 变更前 -->  
    <string name="welcome" translatable="true">Hello</string>  
      
    <!-- 变更后 -->  
    <string name="welcome" translatable="false">Hello</string>  
    

    仅属性变化,文本未变 → 忽略

  2. 识别内容变更

    <!-- 变更前 -->  
    <string name="welcome">Hi</string>  
      
    <!-- 变更后 -->  
    <string name="welcome">Hello</string>  
    

    文本内容变化 → 记录

  3. 捕获新增字符串

    <!-- 新增项 -->  
    + <string name="new_string">New Value</string>  
    

1.4 提交范围判定

版本对比策略

# 获取上一个有效提交  
try:  
    previous_commit = subprocess.check_output(  
        ['git', 'rev-parse', 'HEAD^'],  
        universal_newlines=True  
    ).strip()  
except:  
    # 使用空树对象作为初始状态  
    previous_commit = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"  

特殊场景处理

  1. 首次提交:与空树对象比较,识别所有字符串为新增
  2. 分支合并:对比合并前后的差异
  3. 批量修改:正确处理同时修改多个字符串的情况

1.5 输出结果示例

终端日志

[INFO] Detected changes in strings.xml  
[INFO] Found 2 modified strings and 1 new string  
[INFO] Changes:  
  - welcome: 'Hi''Hello'  
  - button_ok: 'OK''Confirm'  
  + error_network: 'Network error'  

变更字典结构

{  
    "welcome": "Hello",  
    "button_ok": "Confirm",  
    "error_network": "Network error"  
}  

1.6 技术优势

  1. 精准识别:双重正则匹配确保不漏掉任何有效变更
  2. 高效过滤:忽略无关修改,减少无效翻译任务
  3. 上下文感知:区分修改和新增,优化处理逻辑
  4. 版本安全:空树对象处理确保首次提交也能正常工作