node调用谷歌翻译Api,实现自动国际化_node 请求谷歌翻译-程序员宅基地

技术标签: node  谷歌翻译  翻译  国家化  javascript  i18n  

原因:
项目国际化过程繁琐,每次都需要人工去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’ // 将中文翻译为英文

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

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sufei_web/article/details/89002688

智能推荐

Windows平台RTMP、RTSP播放器录像模块精细化控制_windows rtsp播放器-程序员宅基地

文章浏览阅读1.2k次。一个小小的录像功能,如果做的更加通用兼容性好的话,需要注意的点还很多,本文抛砖引玉,感兴趣的开发者可酌情参考。_windows rtsp播放器

农业大棚监控系统v0.1-程序员宅基地

文章浏览阅读360次。场景一. 分析农业大棚监控系统的数据表设计1. 设备描述表2. 设备类型表3. 设备状态表4. 大棚表5. 。。。。。二. 分析农业大棚监控系统功能设计1. 设备管理2. 监控中心2.1 实时:每隔10分钟动态刷新..._农业监控系统数据项描述表

飞桨PaddlePaddle 深度学习 波士顿房价预测任务 熟悉过程 python numpy_housing.data 飞桨 没有-程序员宅基地

文章浏览阅读260次。这个教程不赖,以前学的时候咋就没这种教程,近段时间学paddlepaddle。教程:https://www.paddlepaddle.org.cn/tutorials/projectdetail/1516091数据:https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data# 导入需要用到的packageimport numpy as npimport jsonfrom matplotlib _housing.data 飞桨 没有

Tp5—隐藏public的方法(修改Apache服务器的配置实现)_工具类应隐藏 public 构造器-程序员宅基地

文章浏览阅读6.7k次。出现问题:url :localhost/public/index.php/能用,而index.php不能用。也就是public隐藏的问题。(项目放在了www根目录下)看了下官方文档的解释点击打开链接,但是完全没有看懂。就百度看了下。找到了如何修改Apaceh配置localhost虚拟主机1:首先找到vhost所在的位置 (E:\wamp\bin\apache\apache2.4.9\conf),打..._工具类应隐藏 public 构造器

js 定时器(setTimeout/setInterval)出现变量未定义(xxx is not defined) 的解决方法_setinterval is not defined-程序员宅基地

文章浏览阅读1.7k次。js 定时器(setTimeout/setInterval)出现变量未定义(xxx is not defined) 的解决方法_setinterval is not defined

mysql 使用临时表更新_MySQL中不使用临时表更新列数据-程序员宅基地

文章浏览阅读481次。为此,请使用CASE语句。即使不使用临时表也可以使用。让我们首先创建一个表-mysql>createtableDemoTable->(->UserNamevarchar(100),->UserStatusvarchar(100)->);QueryOK,0rowsaffected(0.74sec)使用插入命令在表中插入一些记录-mysql&..._mysql临时表更新语句

随便推点

Pytorch 属性统计-程序员宅基地

文章浏览阅读894次。Pytorch 属性统计. norm. mean sum. prod. max, min, argmin, argmax. kthvalue, topknorm - p :范数import torcha = torch.full([8], 1)b = a.view(2, 4)c = a.view(2, 2, 2)# 所有元素的1范数print("a.norm(1):\t", a.norm(1))print("a.norm(1):\t", a.norm(1))print("c

MySQL5.7RPM安装.pdf-程序员宅基地

文章浏览阅读242次。解压tar -xvf mysql-5.7.20-1.el6.x86_64.rpm-bundle.tar安装yum -y localinstall mysql-community-common-5.7.20-1.el6.x86_64.rpmyum -y localinstall mysql-community-libs-5.7.20-1.el6.x86_64.rpmyum -y local...

ext3分区修复linux,ext3文件系统超级块损坏修复-程序员宅基地

文章浏览阅读1.2k次。1,一服务器/dev/sdb文件系统损坏,重启后系统启不来,进入单用户模式fsck无法修复,把/etc/fstab中的/dev/sdb注释掉后,系统成功起来。2,mount挂载/dev/sdb提示bad superblock错误,无法正常挂载:[root@localhost ~]# mount /dev/sdb /testmount: wrong fs type, bad option, bad ..._group descriptors look bad

mysql 多列最大值_mysql – 从多列获取两个最大值-程序员宅基地

文章浏览阅读946次。这不是最优雅的解决方案,但如果您无法更改表结构,则可以取消数据的转换,然后应用用户定义的变量来获取每个student_id的行号.代码将类似于以下内容:select student_id, name, col, datafrom(SELECT student_id, name, col,data,@rn:=case when student_id = @prev then @rn else 0 e..._数据库 取出相同最大的2个值

idea 看类的子类 uml 图_StarUML for Mac(UML软件建模器)-程序员宅基地

文章浏览阅读255次。StarUML for Mac是一款UML软件建模器,自动更新StarUML会自动检查最新更新,支持快速编辑中的许多缩写,一次创建元素和关系是一款强大且易用的工具。staruml下载使用这款UML软件建模器吧!软件功能UML 2兼容UML 2.x标准元模型和图表:类,对象,用例,组件,部署,复合结构,序列,通信,状态图,活动和配置文件图。附加图表支持创建实体 - 关系图(ERD),数据流图(DFD..._idea mac 子类

VUE深度作用选择器/deep/_vue /deep/-程序员宅基地

文章浏览阅读959次。为了保证每个组件的css唯一性,避免污染全局或者被全局污染,vue提供了scoped作用域。当 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。如果你希望scoped样式中的一个选择器能够作用得“更深”,例如影响子组件,可以用深度作用选择器(样式穿透)来实现。_vue /deep/

推荐文章

热门文章

相关标签