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
相关产品推荐
相关产品推荐

