node调用谷歌翻译Api,实现自动国际化

原因:
项目国际化过程繁琐,每次都需要人工去google翻译,导致工作效率不高。
需求:
1.减少人工的重复劳动,提高工作效率。
2.使用脚本调用谷歌翻译接口自动化翻译。
3.free,作为程序员肯定接受不了付费服务,找方法解决限制。

前期准备:
1.谷歌翻译api:https://translate.google.cn/translate_a/single
2.一系列参数,
我们需要找到 tk 这个参数;这个参数决定着是否能调通翻译api;

大佬提供的代码:(非常感谢)
/**

  • 获取 google token

  • @param {*} a
    */
    function token(a) {
    var k = “”;
    var b = 406644;
    var b1 = 3293161072;

    var jd = “.”;
    var sb = “±a^+6”;
    var Zb = “±3^+b±f”;

    for (var e = [], f = 0, g = 0; g < a.length; g++) {
    var m = a.charCodeAt(g);
    128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023),
    e[f++] = m >> 18 | 240,
    e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224,
    e[f++] = m >> 6 & 63 | 128),
    e[f++] = m & 63 | 128)
    }
    a = b;
    for (f = 0; f < e.length; f++)
    a += e[f],
    a = RL(a, sb);
    a = RL(a, Zb);
    a ^= b1 || 0;
    0 > a && (a = (a & 2147483647) + 2147483648);
    a %= 1E6;
    return a.toString() + jd + (a ^ b)
    };
    function RL(a, b) {
    var t = “a”;
    var Yb = “+”;
    for (var c = 0; c < b.length - 2; c += 3) {
    var d = b.charAt(c + 2),
    d = d >= t ? d.charCodeAt(0) - 87 : Number(d),
    d = b.charAt(c + 1) == Yb ? a >>> d : a << d;
    a = b.charAt© == Yb ? a + d & 4294967295 : a ^ d
    }
    return a
    }

(我们这里就可以直接使用这段代码,可以解决我们80%的问题了,接下来我们需要针对自己的项目做进一步细化);
3.在这里我使用的是 node 去做这件事
需要用到 fs,moment,commander,https;这几个模块;
fs: 读、写文件;
https:发送请求到Google 翻译 Api;
moment:格式化时间,我是用来添加日志时用到的;
commander:用来操作命令行参数

实现:

  1. 翻译主函数:
    /**
  • 翻译方法
  • @param {*} language 语言
  • @param {*} txt 需翻译的文本
    */
    function translate_google(language, txt, callback) {
    var url = https://translate.google.cn/translate_a/single?client=t&sl=zh-CN&tl=${language}&hl=${language}&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=btn&ssel=0&tsel=1&kc=1&tk=${token(txt)}&q=${txt};
    var options = new URL(url);
    var req = https.request(options, function (res) {
    console.log('STATUS: ’ + res.statusCode);
    res.setEncoding(‘utf8’);
    var val = ‘’;
    res.on(‘data’, function (chunk) {
    val += chunk;
    // 数据流,读取的时候会分布读取下来,我们需要在读取完毕的时候操作数据。
    //(一开始我在这里操作数据,会致使代码报错,是因为数据的不完整性导致)
    });
    res.on(‘end’, () => {
    callback(JSON.parse(val)[0][0][0]) // 拿去返回的参数,得到翻译值
    });
    });
    req.on(‘error’, function (e) {
    errorLog(e.message);
    });
    req.end();
    }
  1. 向文件中写入数据
    /**
  • 向文件中写入数据
  • @param {*} path 文件路径
  • @param {*} val 文本
    */
    function appendFile(path, val) {
    fs.appendFile(path, ${val}\n, ‘utf8’, function (err) {
    if (err) {
    errorLog(err);
    return false;
    }
    errorLog(数据写入 ${path} 文件成功!)
    })
    }
  1. 错误日志
    /**
  • 错误日志
  • @param {*} error 错误信息
    */
    function errorLog(error) {
    var path = ‘./translate_google_error_log.txt’;
    var val = ${getDate()}${error}
    appendFile(path, val);
    }

4.获取当前时间
function getDate() {
var timer = moment(Date.now()).format(‘YYYY-MM-DD HH:mm:ss’)
console.log(timer)
return [${timer}]:;
}

  1. 处理翻译
    function creteTranlate(language) {
    var path = ./src/languages/${language}.locale.json;
    var datas_one = {};
    var datas_two = {};
    var dataObj;
    var i = 1;
    fs.readFile(’./src/languages/zh.locale.json’, ‘utf8’, (err, dataOne) => {
    if (err) {
    errorLog(err);
    return false;
    }
    datas_one = JSON.parse(dataOne);
    fs.readFile(path, ‘utf8’, (err, dataTwo) => {
    if (err) {
    errorLog(err);
    return false;
    }
    datas_two = JSON.parse(dataTwo);
    for (let key in datas_one) {
    if (!datas_two[key]) {
    i++;
    errorLog(没有 ${key} 这个字段);
    setTimeout(() => {
    translate_google(language, datas_one[key], (res) => {
    var a = {};
    a[key] = res;
    dataObj = Object.assign(datas_two, a);
    fs.writeFile(path, JSON.stringify(dataObj), (err) => {
    if (err) {
    errorLog(err);
    return false;
    }
    errorLog(${language}语言,写入成功:*** ${key}: ${res} *** 数据。);
    })
    })
    }, i * 500) // 加上延时,降低被封ip的概率,(测试的时候,被封了好几个ip)
    // 最后是通过联手机热点完成项目改造
    }
    }
    })
    })

}

到这里基本上就已经差不多可以正常使用了
但又觉得每次修改 翻译语言很麻烦 就使用了命令行参数来进一步修改整体代码;

这里我们就需要 commander 这个模块来处理 我们的命令参数了

var program = require(‘commander’);
//定义参数,以及参数内容的描述
program
.version(‘0.0.1’)
.usage(’[option][value …]’)
.option(’-p, -path ', ‘a string argument’)
//解析commandline arguments
program.parse(process.argv)

到这里,我们就基本上可以上测试了。

附上整个代码及使用方法:
代码:
var fs = require(‘fs’);
var moment = require(‘moment’);
var program = require(‘commander’);
var https = require(‘https’);

//定义参数,以及参数内容的描述
program
.version(‘0.0.1’)
.usage(’[option][value …]’)
.option(’-p, -path ', ‘a string argument’)
//解析commandline arguments
program.parse(process.argv)
function getDate() {
var timer = moment(Date.now()).format(‘YYYY-MM-DD HH:mm:ss’)
console.log(timer)
return [${timer}]:;
}
/**

  • 获取 google token

  • @param {*} a
    */
    function token(a) {
    var k = “”;
    var b = 406644;
    var b1 = 3293161072;

    var jd = “.”;
    var sb = “±a^+6”;
    var Zb = “±3^+b±f”;

    for (var e = [], f = 0, g = 0; g < a.length; g++) {
    var m = a.charCodeAt(g);
    128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023),
    e[f++] = m >> 18 | 240,
    e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224,
    e[f++] = m >> 6 & 63 | 128),
    e[f++] = m & 63 | 128)
    }
    a = b;
    for (f = 0; f < e.length; f++)
    a += e[f],
    a = RL(a, sb);
    a = RL(a, Zb);
    a ^= b1 || 0;
    0 > a && (a = (a & 2147483647) + 2147483648);
    a %= 1E6;
    return a.toString() + jd + (a ^ b)
    };
    function RL(a, b) {
    var t = “a”;
    var Yb = “+”;
    for (var c = 0; c < b.length - 2; c += 3) {
    var d = b.charAt(c + 2),
    d = d >= t ? d.charCodeAt(0) - 87 : Number(d),
    d = b.charAt(c + 1) == Yb ? a >>> d : a << d;
    a = b.charAt© == Yb ? a + d & 4294967295 : a ^ d
    }
    return a
    }
    /**

  • 翻译方法

  • @param {*} language 语言

  • @param {*} txt 需翻译的文本
    /
    function translate_google(language, txt, callback) {
    var url = https://translate.google.cn/translate_a/single?client=t&sl=zh-CN&tl=${language}&hl=${language}&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=btn&ssel=0&tsel=1&kc=1&tk=${token(txt)}&q=${txt};
    var options = new URL(url);
    var req = https.request(options, function (res) {
    console.log('STATUS: ’ + res.statusCode);
    res.setEncoding(‘utf8’);
    var val = ‘’;
    res.on(‘data’, function (chunk) {
    val += chunk;
    });
    res.on(‘end’, () => {
    callback(JSON.parse(val)[0][0][0])
    });
    });
    req.on(‘error’, function (e) {
    errorLog(e.message);
    });
    req.end();
    }
    /
    *

  • 错误日志

  • @param {*} error 错误信息
    /
    function errorLog(error) {
    var path = ‘./translate_google_error_log.txt’;
    var val = ${getDate()}${error}
    appendFile(path, val);
    }
    /
    *

  • 向文件中写入数据

  • @param {*} path 文件路径

  • @param {*} val 文本
    */
    function appendFile(path, val) {
    fs.appendFile(path, ${val}\n, ‘utf8’, function (err) {
    if (err) {
    errorLog(err);
    return false;
    }
    console.log(数据写入 ${path} 文件成功!)
    })
    }

function creteTranlate(language) {
var path = ./src/languages/${program.Path}.locale.json;
var datas_one = {}; // 翻译源文件
var datas_two = {}; // 翻译目标文件
var dataObj;
var i = 1;
fs.readFile(’./src/languages/zh.locale.json’, ‘utf8’, (err, dataOne) => {
if (err) {
errorLog(err);
return false;
}
datas_one = JSON.parse(dataOne);
fs.readFile(path, ‘utf8’, (err, dataTwo) => {
if (err) {
errorLog(err);
return false;
}
datas_two = JSON.parse(dataTwo);
for (let key in datas_one) {
if (!datas_two[key]) { // 若已存在,则不去翻译
i++;
errorLog(没有 ${key} 这个字段);
setTimeout(() => {
translate_google(language, datas_one[key], (res) => {
var a = {};
a[key] = res;
dataObj = Object.assign(datas_two, a);
fs.writeFile(path, JSON.stringify(dataObj), (err) => {
if (err) {
errorLog(err);
return false;
}
errorLog(${language}语言,写入成功:*** ${key}: ${res} *** 数据。);
})
})
}, i * 500)
}
}
})
})

}

let language = program.Path === ‘ba’ ? ‘id’ : program.Path; // 这里是因为 谷歌翻译印尼文使用的是‘id’这个参数,我们项目中使用的是“ba”来命名印尼语文件的,做了个转换
creteTranlate(language);

使用方法:
node node_translate.js -p ‘ba’ // 将中文翻译为印尼文
node node_translate.js -p ‘vi’ // 将中文翻译为越南文
node node_translate.js -p ‘en’ // 将中文翻译为英文

截图:
在这里插入图片描述
在这里插入图片描述

不足之处,还请大佬指点一下。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值