You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular i18n如何将messages.en.xlf的翻译反向批量同步到源码?

Angular i18n 英文翻译批量同步回源码解决方案

方案核心思路

通过自定义Node脚本解析messages.en.xlf文件,提取所有trans-unit节点的source(源码原始文案)和target(编辑器修改后的正式英文文案)映射关系,全局匹配源码文件完成批量替换。

具体实现步骤

1. 安装依赖

只需要两个轻量工具库:

npm install xml2js glob --save-dev

2. 编写同步脚本

在项目根目录新建sync-i18n-to-source.js文件,代码如下:

const fs = require('fs');
const glob = require('glob');
const xml2js = require('xml2js');

// 配置项,可根据自己项目调整
const CONFIG = {
  xlfPath: './src/locale/messages.en.xlf', // 你的en语言包路径
  sourceGlob: './src/**/*.{html,ts}', // 要替换的源码文件匹配规则
  dryRun: true, // 先开dryRun,只打印要修改的内容,确认没问题再改成false执行替换
};

// 解析xlf文件
async function parseXlf() {
  const xlfContent = fs.readFileSync(CONFIG.xlfPath, 'utf8');
  const parser = new xml2js.Parser();
  const result = await parser.parseStringPromise(xlfContent);
  const transUnits = result.xliff.file[0].body[0]['trans-unit'];
  
  const translateMap = new Map();
  transUnits.forEach(unit => {
    const source = unit.source[0].trim();
    // 处理带占位符的情况,比如xlf里的<x id="INTERPOLATION" />对应源码的{{xxx}}
    const target = unit.target[0].replace(/<x id="INTERPOLATION"(\s+[^>]+)?\/>/g, (match, p1) => {
      // 如果你有其他类型占位符,这里可以扩展对应规则
      const idMatch = p1.match(/equiv-text="([^"]+)"/);
      return idMatch ? idMatch[1] : match;
    }).trim();
    if (source && target && source !== target) {
      translateMap.set(source, target);
    }
  });
  return translateMap;
}

// 替换源码文件
async function replaceSource(translateMap) {
  const files = glob.sync(CONFIG.sourceGlob, { ignore: './src/**/*.spec.ts' });
  let modifiedCount = 0;

  files.forEach(filePath => {
    let content = fs.readFileSync(filePath, 'utf8');
    let hasChange = false;

    translateMap.forEach((target, source) => {
      // 转义正则特殊字符
      const escapedSource = source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      // 匹配规则:可以根据自己源码里i18n的写法调整,比如html里的i18n属性,ts里的$localize标记
      const regex = new RegExp(`((i18n(="[^"]*")?>|\\$localize\\s*(:[^`]+)?\\s*`))${escapedSource}`, 'g');
      if (regex.test(content)) {
        console.log(`[${CONFIG.dryRun ? '预览' : '修改'}] ${filePath}: "${source}" -> "${target}"`);
        content = content.replace(regex, `$1${target}`);
        hasChange = true;
      }
    });

    if (hasChange) {
      modifiedCount++;
      if (!CONFIG.dryRun) {
        fs.writeFileSync(filePath, content, 'utf8');
      }
    }
  });

  console.log(`\n处理完成,共${modifiedCount}个文件需要修改`);
  if (CONFIG.dryRun) {
    console.log('确认修改内容无误后,将CONFIG.dryRun改为false即可执行实际替换');
  }
}

// 执行
parseXlf().then(replaceSource).catch(console.error);

如果你项目的i18n文案是通过自定义ID(比如i18n="@@submitBtn")来标记的,可以把脚本的映射逻辑改成以id为key,匹配对应ID后的文案进行替换,准确性更高。

3. 执行脚本

先开启dryRun模式预览修改内容:

node sync-i18n-to-source.js

确认所有替换符合预期后,把配置里的dryRun改成false,再执行一次脚本即可完成批量替换。

后续优化建议

替换完成后可以把这个脚本加入ng extract-i18n的后置钩子,每次提取新文案后自动同步编辑器已经修改过的翻译,从流程上避免后续再出现dev和en版本的文案差异问题。

内容的提问来源于stack exchange,提问作者Senne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 15:15:05