Gulp 把 json 文件批量翻译 i18n 多国语言

🌙
手机阅读
本文目录结构

百度的翻译还是不给力, 改为 Google 进行文档翻译了;推荐使用 Google, 翻译的更好;

项目使用 VUE-I18N 做多国语言处理;

运行环境是 Electron+vue 做的客户端项目;

需求:用一份 json 文件作为模板,构建出 22 国语言;每个国家的语言,单独储存在一个 json 文件内;用的是百度翻译的 API

开始的基础文件

任务执行后的文件;

用的百度翻译 API(迫于翻译太烂,还是改为谷歌了 - -、)

npm 的依赖如下

"devDependencies": {
    "gulp": "^3.9.1",
    "gulp-rename": "^1.2.2",
    "gulp-util": "^3.0.8",
    "md5": "^2.2.1",
    "request": "^2.85.0",
    "through2": "^2.0.3"
}

文件夹

/i18n/config
/i18n/languges_conf
/i18n/tap-i18n.json

gulp 的配置文件

gulpfile.js文件如下

/**
 *  Translate Chinese json files into other language json files
 *  language : https://cloud.google.com/translate/docs/languages
 */
const gulp = require('gulp'),
    i18n = require('./i18n/config'),
    // languges = require('./i18n/languges'),
    languges = require('./i18n/languges_conf'),
    rename = require('gulp-rename');
// The task of translating files
gulp.task('default', function () {
    for (const languge in languges) {
        // console.log(languge,languges[languge])
        gulp.src('./i18n/tap-i18n.json')
            .pipe(
                // The specific logic of translation
                i18n('', languge)
            )
            .pipe(rename({
                dirname: "i18n",
                basename: languge,
                extname: ".json"
            }))
            //  Post-translation file output file path
            .pipe(gulp.dest('./src/renderer/'));
    }
});

gulp.task('watch', function () {
    gulp.watch('i18n/tap-i18n.json', ['default']);
})

配置中引用了别的配置 /i18n/config.js,内容如下;

const { youdao, baidu, google } = require('translation.js');

let through = require('through2'),
    gutil = require('gulp-util');
PluginError = gutil.PluginError;

// Constants, error prompts for use
const PLUGIN_NAME = 'gulp-i18n';

/**
 * Convert json language
 * @param from Translate source data
 * @param to  Translation language
 * @returns {*}
 */
function i18n(from, to) {
    // Create a stream channel to allow each file to pass
    let stream = through.obj(function (file, enc, cb) {
        // console.log(JSON.stringify(file))
        if (file.isStream()) {
            this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
            return cb();
        }
        if (file.isBuffer()) {
            let json = JSON.parse(file.contents.toString());
            let tJson = '';
            //  Get the data to be translated in the json file
            for (let v in json) {
                if (json[v] instanceof Object) {
                    tJson = getText(json[v], tJson);
                }
                else {
                    tJson += json[v] + "\n";
                }
            }
            if (tJson.length > 2000)
                this.emit('error', new PluginError(PLUGIN_NAME, 'Source file is greater than 2000 words'));
            //Google Translate
            google.translate({
                text: tJson,
                from: from,
                to: to
            }).then(result => {
                // console.log("to:"+to,result.result,result) // The data structure of result is shown below

                /*
                * esult.result = [ 'Nastavení',
                    'CZR',
                    'Domů',
                    'Přenos',
                    'Kontakty',
                    'Nastavení',
                    'Celkem',
                    'Nastavení' ]
                * */
                // let result=result;
                // console.log("内容是",file.contents.toString())
                let content = file.contents.toString().replace(/(:\s*")(\S+)(")/gi, function (match, p1, p2, p3, offset, string) {
                    /*              console.log(
                    // result.raw.sentences,
                                      "【match=>"+match+"】",
                                      "【p1=>"+p1+"】",
                                      "【p2=>"+p2+"】",
                                      "【p3=>"+p3+"】",
                                      "【offset=>"+offset+"】",
                                      "【string=>"+string+"】",
                                      )*/

                    /*
                    result.raw.sentences :[
                        { trans: 'Setting\n', orig: 'Setting\n', backend: 3 },
                        { trans: 'CZR\n', orig: 'CZR\n', backend: 3 },
                        { trans: 'Home\n', orig: '首页\n', backend: 3 },
                        { trans: 'Transfer\n', orig: '转账\n', backend: 3 },
                        { trans: 'Contacts\n', orig: '联系人\n', backend: 3 },
                        { trans: 'Settings\n', orig: '设置\n', backend: 3 },
                        { trans: 'total\n', orig: '合计\n', backend: 2 },
                        { trans: 'Settings', orig: '设置', backend: 3 } ] '
                          【match=>:"设置"】'
                          '【p1=>:"】'
                          '【p2=>设置】'
                          '【p3=>"】'
                          '【offset=>270】'
                          '【string=>{\n    "lang": {\n        "browse": "Setting"\n    },\n    "unit":{\n        "czr":"CZR"\n    },\n    "model_header":{\n        "home":"首页",\n        "transfer":"转账",\n        "contacts":"联系人",\n        "setting":"设置",\n        "total":"合计"\n    },\n    "page_setting":{\n        "tit":"设置"\n    }\n}】'
                     */
                    for (let i = 0; i < result.raw.sentences.length; i++) {
                        // console.log(result.raw.sentences[i].orig == p2, , match, p2)
                        let sourcesStr = result.raw.sentences[i].orig.replace("\n", '');
                        let targetStr = result.raw.sentences[i].trans.replace("\n", '');
                        if (sourcesStr == p2) {
                            return ':"' + targetStr + '"'
                        }

                    }
                    return match
                })

                file.contents = new Buffer(content);
                // Make sure the file goes to the next gulp plugin
                this.push(file);
                // Tell the stream engine that we have finished processing this file
                cb();

            })
        }
    });
    // return stream file
    return stream;
}

/**
 * Get data to translate
 * @param src
 * @param dst
 * @returns {*}
 */
function getText(src, dst) {
    for (let k in src) {
        if (src[k] instanceof Object) {
            dst = getText(src[k], dst);
        }
        else {
            dst += src[k] + "\n";
        }
    }
    return dst;
}
module.exports = i18n;

languges_conf.js 文件如下

languges_conf.js

const languges = {

    'af': "Burry (Afrikaans)",//布尔语(南非荷兰语)       Burry (Afrikaans)
    'sq': "shqiptar",//阿尔巴尼亚语                     shqiptar
    'am': "አማርኛ",//阿姆哈拉语				           አማርኛ
    'ar': "عربي",//阿拉伯语				                عربي
    'hy': "Հայերեն",//亚美尼亚语				        Հայերեն
    'az': "Azərbaycan",//阿塞拜疆语				        Azərbaycan
    'eu': "Euskal",//巴斯克语				            Euskal
    'be': "беларускі",//白俄罗斯语				        беларускі
    'bn': "বাংলা ভাষার",//孟加拉语				            বাংলা ভাষার
    'bs': "Bosanski",//波斯尼亚语				        Bosanski

    'bg': "български",//保加利亚语				        български
    'ca': "Català",//加泰罗尼亚语			            Català
    'ceb': "Sugbo",//宿务语				                Sugbo
    'zh-CN': "中文(简体)",//中文(简体)
    'zh-TW': "中文(繁體)",//中文(繁體)
    'co': "Corsa",//科西嘉语				    Corsa
    'hr': "Croata",//克罗地亚语				    Croata
    'cs': "Česky",//捷克语				        Česky
    'da': "dansk",//丹麦语				        dansk
    'nl': "Nederlands",//荷兰语				    Nederlands

    'en': "English",//英语					    English
    'eo': "Esperanto",//世界语				    Esperanto
    'et': "Eesti keel",//爱沙尼亚语				 Eesti keel
    'fi': "suomalainen",//芬兰语				suomalainen
    'fr': "Français",//法国语				    Français
    'fy': "Frysk",//弗里西语				    Frysk
    'gl': "Galego",//加利西亚语				    Galego
    'ka': "ქართული",//格鲁吉亚语				ქართული
    'de': "Deutsche Sprache",//德语			    Deutsche Sprache
    'el': "Ελληνικά",//希腊语				    Ελληνικά

    'gu': "ગુજરાતી",//古吉拉特语				    ગુજરાતી
    'ht': "Kreyòl Ayisyen",//海地克里奥尔语			Kreyòl Ayisyen
    'ha': "Hausa",//豪萨语				        Hausa
    'haw': "Hawaiian",//夏威夷语				Hawaiian
    'iw': "עברית",//希伯来语				    עברית
    'hi': "बात मत करो",//印地语				    बात मत करो
    'hmn': "Miao",//苗语					    Miao
    'hu': "magyar",//匈牙利语				    magyar
    'is': "Íslensku",//冰岛语				    Íslensku
    'ig': "Asụsụ Ibo",//伊博语				    Asụsụ Ibo

    'id': "Bahasa indonesia",//印尼语	    Bahasa indonesia
    'ga': "Gaeilge",//爱尔兰语				Gaeilge
    'it': "lingua italiana",//意大利语		lingua italiana
    'ja': "日本語",//日语				    日本語
    'jw': "Wong Jawa",//印尼爪哇语			Wong Jawa
    'kn': "ಕನ್ನಡ",//卡纳达语				    ಕನ್ನಡ
    'kk': "Қазақша",//哈萨克语				Қазақша
    'km': "ភាសាខ្មែរ",//高棉语				    ភាសាខ្មែរ
    'ko': "한국어",//韩语					    한국어
    'ku': "Kurdî",//库尔德语				    Kurdî

    'ky': "Кыргыз тили",//吉尔吉斯语		Кыргыз тили
    'lo': "ລາວ",//老挝语				    ລາວ
    'la': "Latine",//拉丁语				    Latine
    'lv': "Latviešu",//拉脱维亚语				Latviešu
    // 'lt': "Lietuviškai",//立陶宛语				Lietuviškai
    'lb': "Lëtzebuergesch",//卢森堡语			Lëtzebuergesch
    'mk': "Македонски",//马其顿语				Македонски
    'mg': "Malagasy",//马尔加什语				Malagasy
    'ms': "Melayu",//马来语				    Melayu
    'ml': "മലയാളം",//马拉雅拉姆语			മലയാളം

    'mt': "Malti",//马耳他语				Malti
    'mi': "Maori",//毛利语				    Maori
    'mr': "मराठी",//马拉地语				    मराठी
    'mn': "Монгол хэл",//蒙古语				Монгол хэл
    'my': "မြန်မာ",//缅甸语				    မြန်မာ
    'ne': "नेपाली",//尼泊尔语				नेपाली
    'no': "norsk språk",//挪威语			norsk språk
    'ny': "Chichewa",//齐切瓦语				Chichewa
    'ps': "پښتو",//普什图语				    پښتو
    'fa': "فارسی",//波斯语				    فارسی

    'pl': "Polski",//波兰语				    Polski
    'pt': "Português",//葡萄牙语			Português
    'pa': "ਪੰਜਾਬੀ",//旁遮普语				   ਪੰਜਾਬੀ
    'ro': "românesc",//罗马尼亚语			românesc
    'ru': "Русский язык",//俄语				Русский язык
    'sm': "Samoa",//萨摩亚语				Samoa
    'gd': "Gàidhlig na h-Alba",//苏格兰盖尔语			Gàidhlig na h-Alba
    'sr': "Српски",//塞尔维亚语				    Српски
    'st': "Sesotho",//塞索托语				    Sesotho
    'sn': "Shinra",//修纳语				    Shinra

    'sd': "سنڌي",//信德语				    سنڌي
    'si': "සිංහල",//僧伽罗语				සිංහල
    'sk': "slovenského jazyk",//斯洛伐克语	    slovenského jazyk
    'sl': "Slovenščina",//斯洛文尼亚语			Slovenščina
    'so': "Somali",//索马里语				    Somali
    'es': "Español",//西班牙语				    Español
    'su': "Sunda Indonesian",//印尼巽他语       Sunda Indonesian
    'sw': "Kiswahili",//斯瓦希里语				Kiswahili
    'sv': "Svenska",//瑞典语				    Svenska
    'tl': "Filipino",//菲律宾语				    Filipino

    'tg': "Тоҷикӣ",//塔吉克语				    Тоҷикӣ
    'ta': "தமிழ் மொழி",//泰米尔语				    தமிழ் மொழி
    'te': "తెలుగు",//泰卢固语				    తెలుగు
    'th': "ไทย",//泰语					        ไทย
    'tr': "Türk dili",//土耳其语				Türk dili
    'uk': "Українська",//乌克兰语				Українська
    'ur': "اردو",//乌尔都语				    اردو
    'uz': "O'zbek",//乌兹别克语				O'zbek
    'vi': "Tiếng Việt",//越南语				Tiếng Việt
    'cy': "Cymraeg",//威尔士语				Cymraeg

    'xh': "IsiXhosa saseMzantsi Afrika",//南非科萨语    IsiXhosa saseMzantsi Afrika
    'yi': "ייִדיש",//意第绪语				            ייִדיש
    'yo': "Yorùbá",//约鲁巴语				            Yorùbá
    'zu': "I-South African Zulu"//祖鲁语                I-South African Zulu
};

module.exports = languges;

tap-i18n.json

{
    "confirm": "确认",
    "cancel": "取消",
    "dialog_tit": "提示",
    "close": "关闭",
    "confirm_you_active": "请确认您的操作",
    "unit": {
        "czr": "CZR"
    },
    "model_header": {
        "home": "首页",
        "transfer": "转账",
        "contacts": "联系人",
        "setting": "设置",
        "total": "合计",
        "testnet":"测试网络"
    },
    "page_setting": {
        "tit": "设置",
        "lang": "语言",
        "select": "请选择"
    },
    "page_contacts": {
        "tit": "联系人",
        "add_dialog": "新建联系人",
        "add_cont": {
            "tit": "新建联系人",
            "tag": "联系人",
            "address": "账户地址",
            "tag_placeholder": "请输入联系人的姓名",
            "address_placeholder": "请输入联系人的账户地址",
            "add_success": "添加成功"
        },
        "delete_dialog": {
            "title": "您正在移除",
            "remove_success": "移除成功"
        },
        "msg_info": {
            "no_tag": "请输入账户备注",
            "no_address": "请输入账户地址",
            "valid_address": "联系人的地址不合法",
            "validate_tag_length": "备注名长度不能大于8个字符",
            "exist": "联系人已经存在,"
        }
    },
    "page_transfer": {
        "from_address": "发款方",
        "to_address": "收款方",
        "amount": "金额",
        "send_all": "发送全部",
        "data": "Data",
        "data_placeholder": "十六进制数据",
        "fees": "手续费",
        "total": "合计",
        "select": "请选择",
        "no_account_info": "暂无账号,请创建或者导入账号",
        "contacts_dig": {
            "title":"选择联系人账号",
            "select_placeholder": "请选择"
        },
        "confirm_dia": {
            "title": "请确认",
            "enter_passworld_tit": "请输入密码",
            "enter_passworld_place": "请输入密码"
        },
        "msg_info": {
            "address_null": "请输入对方账户",
            "balance_zero": "余额不足,无法继续",
            "amount_zero": "转账金额必须大于0",
            "amount_error": "请输入合法的交易金额",
            "address_err": "转入的地址格式不合法",
            "send_success": "发送成功",

            "decrypt_err": "钱包解析失败,可能是密码错误",
            "send_error": "交易失败:请检查是否有足量余额和矿工费"
        }
    },
    "page_account": {
        "transfer_log": "交易记录",
        "transfer_log_null": "暂无交易记录",
        "active_icon": {
            "go_transfer": "发起转账",
            "import_keystore": "账户文件",
            "qrcode": "二维码"
        },
        "edit_dia": {
            "tit": "修改备注",
            "subtit": "为您的账户标记一个备注",
            "no_tag": "请输入账户备注",
            "validate_tag_length": "备注名长度不能大于8个字符"
        },
        "dia_tx":{
            "tit":"交易信息",
            "block_hash":"交易号",
            "status":"状态",
            "from":"发款方",
            "to":"收款方",
            "amount":"金额",
            "data":"数据",
            "send_time":"发送时间",
            "mac_time":"主链时间"
        },
        "keystore": {
            "tit": "备份钱包文件",
            "copy": "复制",
            "download": "下载钱包文件"
        },
        "msg_info": {
            "ads_copy_success": "地址已经复制",
            "key_copy_success": "复制成功"
        }
    },
    "page_home": {
        "import_account": "导入账号",
        "add_account": "新建账号",
        "acc": "账户",
        "create_dia": {
            "create_tit": "创建账户",
            "backup_tit": "备份您的新账户",
            "create_tag": "账户备注",
            "create_pwd": "设置密码",
            "create_repwd": "确认密码",
            "placeholder_tag": "请设置账户备注名",
            "placeholder_pwd": "请设置账户密码",
            "placeholder_repwd": "请确认账户密码",


            "account_download_keystore": "下载账户文件",

            "validate_tag": "请输入账户备注名",
            "validate_tag_length": "备注名长度不能大于8个字符",

            "validate_password": "请输入您设置的密码",
            "validate_re_password": "请再次输入您设置的密码",
            "validate_strong_password": "请输入一个至少8位的密码",
            "validate_password_length": "两次输入的密码不一致",

            "create_success": "创建成功",
            "create_success_des": "请保存你的账户文件,不要分享给任何人!"
        },
        "import_dia": {
            "tit": "导入账户",
            "placeholder_keystore": "请将账户文件拖入此处",
            "create_tag": "账户备注",
            "placeholder_tag": "请设置账户备注名",

            "validate_tag": "请输入账户备注名",
            "validate_tag_length": "备注名长度不能大于8个字符",
            "validate_enter_keystore": "请先导入账户文件",
            "validate_error_keystore": "账户导入失败,可能是账户文件错误",
            "imported_account_success": "导入成功",
            "exist": "此账户已经存在,备注是",
            "keystore_error": "错误:",
            "imported_success":"导入文件成功"
        },
        "remove_dia": {
            "tit": "你确定要移除吗?",
            "remove_confrim": "我确定移除",
            "backup": "请注意此账号的备份,避免财产损失",
            "input_pwd":"密码",
            "placeholder_pwd":"请输入此账户的密码",
            "validate_password": "请输入账户的密码",
            "remove_success": "移除成功"
        }
    }
}

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了