关注

前端国际化自动化方案:从手工劳动到工程化实践

前端国际化自动化方案:从手工劳动到工程化实践

当 Web 产品要进入国际市场时,国际化(i18n)就成了基础需求。传统开发方式下,支持多语言是个麻烦事——开发者得手动把中文换成 key,再在 JSON 文件里一个个填翻译。今天聊聊怎么用工程化手段自动搞定这些事。

一、手动处理 i18n 的三个坑

没自动化工具时,手动维护多语言配置总出这些问题:

  1. 漏译错译:代码里新增的文案经常忘了同步到 en.json 这些文件,上线后界面直接显示 key 名。
  2. 开发效率低:每改一句话都要切到 JSON 文件对齐,思路老被打断。
  3. 文件臃肿:功能下线后,对应的翻译 key 还留在文件里,白白占空间。

二、编译时自动提取方案

核心思路是把提取和校验放进构建流程:

graph TD
    A[代码里写中文] --> B[静态扫描提取文案]
    B --> C[生成 key 对照表]
    C --> D{对比现有配置文件}
    D -->|缺翻译| E[生成待翻译补丁]
    D -->|有多余 key| F[清理无用配置]
    E --> G[调用翻译 API]
    G --> H[合并到主分支]

具体实现分两步:

  • 提取器:用 AST 或正则抓代码里的 t("文案") 内容
  • 校验器:在 CI 里比对提取的 key 和配置文件,漏了就直接报错

三、原生 Node.js 检测工具

这里有个纯原生实现的扫描脚本(只用 fspath),能检查代码里用的 key 是否都在 JSON 里定义了:

const fs = require('fs');
const path = require('path');

class I18nGatekeeper {
    constructor(localesDir, sourceDir) {
        this.localesDir = localesDir;
        this.sourceDir = sourceDir;
        this.translationKeys = new Set();
    }

    scanSourceFiles(dir) {
        const list = fs.readdirSync(dir);
        const i18nRegex = /\$?t\(\s*['"]([^'"]+)['"]\s*\)/g;

        list.forEach(item => {
            const fullPath = path.join(dir, item);
            const stat = fs.statSync(fullPath);

            if (stat.isDirectory() && !['node_modules', 'dist'].includes(item) && !item.startsWith('.')) {
                this.scanSourceFiles(fullPath);
            } else if (stat.isFile() && /\.(js|ts|vue|jsx|tsx)$/.test(item)) {
                try {
                    const content = fs.readFileSync(fullPath, 'utf8');
                    let match;
                    i18nRegex.lastIndex = 0;
                    while ((match = i18nRegex.exec(content)) !== null) {
                        this.translationKeys.add(match[1]);
                    }
                } catch (e) {
                    console.error(`读取文件 ${fullPath} 失败: ${e.message}`);
                }
            }
        });
    }

    verifyLocales() {
        const localeFiles = fs.readdirSync(this.localesDir).filter(f => f.endsWith('.json'));
        let hasErrors = false;

        localeFiles.forEach(file => {
            const filePath = path.join(this.localesDir, file);
            try {
                const localeData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
                const missingKeys = [];

                this.translationKeys.forEach(key => {
                    if (!(key in localeData)) {
                        missingKeys.push(key);
                    }
                });

                if (missingKeys.length > 0) {
                    hasErrors = true;
                    console.log(`\n🚨 ${file} 缺失翻译:`);
                    missingKeys.forEach(k => console.log(`  - ${k}`));
                }
            } catch (err) {
                console.error(`解析 ${file} 失败: ${err.message}`);
            }
        });

        return !hasErrors;
    }
}

// 测试代码(实际使用时替换真实路径)
if (require.main === module) {
    const gatekeeper = new I18nGatekeeper('./locales', './src');
    gatekeeper.scanSourceFiles('./src');
    
    if (!gatekeeper.verifyLocales()) {
        console.log('\n❌ 发现翻译缺失,CI 应拦截');
        process.exit(1);
    }
}

四、落地建议

实际用这套方案时要注意:

  1. 所有新文案必须用 t() 包裹,老代码逐步重构
  2. 把扫描脚本集成到 CI,漏翻译直接打回 PR
  3. 可以对接 Crowdin 这类平台自动同步翻译

五、小结

做过国际化的都知道,手动维护 JSON 文件有多痛苦。这套方案把提取、校验、翻译都自动化后,确实能省不少事。不过要注意扫描规则得覆盖项目所有场景,否则会有漏网之鱼。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_34803115/article/details/162445137

文章来源crawl

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--