i18n-jsautotranslate 3.16.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -103
- package/index.js +1287 -244
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var translate = {
|
|
|
14
14
|
* 格式:major.minor.patch.date
|
|
15
15
|
*/
|
|
16
16
|
// AUTO_VERSION_START
|
|
17
|
-
version: '3.
|
|
17
|
+
version: '3.18.0.20250816',
|
|
18
18
|
// AUTO_VERSION_END
|
|
19
19
|
/*
|
|
20
20
|
当前使用的版本,默认使用v2. 可使用 setUseVersion2();
|
|
@@ -177,21 +177,20 @@ var translate = {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
//从服务器加载支持的语言库
|
|
180
|
-
translate.request.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
180
|
+
if(typeof(translate.request.api.language) == 'string' && translate.request.api.language.length > 0){
|
|
181
|
+
//从接口加载语种
|
|
182
|
+
translate.request.post(translate.request.api.language, {}, function(data){
|
|
183
|
+
if(data.result == 0){
|
|
184
|
+
console.log('load language list error : '+data.info);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
//console.log(data.list);
|
|
188
|
+
translate.selectLanguageTag.customUI(data.list);
|
|
189
|
+
}, null);
|
|
190
|
+
}else if(typeof(translate.request.api.language) == 'object'){
|
|
191
|
+
//无网络环境下,自定义显示语种
|
|
192
|
+
translate.selectLanguageTag.customUI(translate.request.api.language);
|
|
193
|
+
}
|
|
195
194
|
|
|
196
195
|
}
|
|
197
196
|
},
|
|
@@ -368,7 +367,10 @@ var translate = {
|
|
|
368
367
|
if(window.self !== window.top){
|
|
369
368
|
if(typeof(window.parent.translate) == 'object' && typeof(window.parent.translate.version) == 'string'){
|
|
370
369
|
//iframe页面中存在 translate,那么也控制iframe中的进行翻译
|
|
371
|
-
window.parent.translate.
|
|
370
|
+
if(window.parent.translate.language.getCurrent() != languageName){
|
|
371
|
+
//如果父页面当前的语种不是需要翻译的语种,对其进行翻译
|
|
372
|
+
window.parent.translate.changeLanguage(languageName);
|
|
373
|
+
}
|
|
372
374
|
}
|
|
373
375
|
}
|
|
374
376
|
}catch(e){
|
|
@@ -406,7 +408,9 @@ var translate = {
|
|
|
406
408
|
|
|
407
409
|
//当用户代码设置里启用了 translate.listener.start() 然后用户加载页面后并没有翻译(这时listener是不启动的只是把listener.use标记为true),然后手动点击翻译按钮翻译为其他语种(这是不会刷新页面),翻译后也要跟着启动监听
|
|
408
410
|
if(translate.listener.use == true && translate.listener.isStart == false){
|
|
409
|
-
translate.listener.start
|
|
411
|
+
if(typeof(translate.listener.start) != 'undefined'){
|
|
412
|
+
translate.listener.start();
|
|
413
|
+
}
|
|
410
414
|
}
|
|
411
415
|
},
|
|
412
416
|
|
|
@@ -536,8 +540,26 @@ var translate = {
|
|
|
536
540
|
* 这个其实是借用了 自定义术语 的能力,设置了自定义术语的原字符等于翻译后的字符, 于是这个字符就不会被翻译了
|
|
537
541
|
* 这里可以是多个,数组,如 ['你好','世界']
|
|
538
542
|
*/
|
|
539
|
-
text:[]
|
|
540
|
-
|
|
543
|
+
text:[],
|
|
544
|
+
/*
|
|
545
|
+
下面的 textRegex 、 setTextRegexs 正则方式设置忽略不翻译text的能力,有 https://github.com/wangliangyu 提交贡献, 弥补 translate.ignore.text 固定设置的不足
|
|
546
|
+
*/
|
|
547
|
+
textRegex:[],
|
|
548
|
+
/*
|
|
549
|
+
使用方式如:
|
|
550
|
+
translate.ignore.setTextRegexs([/请求/g, /[\u4a01-\u4a05]+/g]);
|
|
551
|
+
*/
|
|
552
|
+
setTextRegexs: function(arr) {
|
|
553
|
+
if (!Array.isArray(arr)) throw new Error('参数必须为数组');
|
|
554
|
+
for (let i = 0; i < arr.length; i++) {
|
|
555
|
+
if (!(arr[i] instanceof RegExp)) {
|
|
556
|
+
throw new Error('第' + i + '项不是RegExp对象');
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
//this.textRegex = [...this.textRegex, ...arr];
|
|
560
|
+
//改为兼容 es5 的方式,提供更多兼容
|
|
561
|
+
this.textRegex = this.textRegex.concat(arr);
|
|
562
|
+
},
|
|
541
563
|
},
|
|
542
564
|
//刷新页面,你可以自定义刷新页面的方式,比如在 uniapp 打包生成 apk 时,apk中的刷新页面就不是h5的这个刷新,而是app的刷新方式,就需要自己进行重写这个刷新页面的方法了
|
|
543
565
|
refreshCurrentPage:function(){
|
|
@@ -654,6 +676,10 @@ var translate = {
|
|
|
654
676
|
}
|
|
655
677
|
//console.log(str)
|
|
656
678
|
for(var originalText in translate.nomenclature.data[translate.language.getLocal()][translate.to]){
|
|
679
|
+
if (!translate.nomenclature.data[translate.language.getLocal()][translate.to].hasOwnProperty(originalText)) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
|
|
657
683
|
var translateText = translate.nomenclature.data[translate.language.getLocal()][translate.to][originalText];
|
|
658
684
|
if(typeof(translateText) == 'function'){
|
|
659
685
|
//进行异常的预处理调出
|
|
@@ -753,8 +779,15 @@ var translate = {
|
|
|
753
779
|
|
|
754
780
|
var text = '';
|
|
755
781
|
for(var uuid in translate.nodeQueue){
|
|
782
|
+
if (!translate.nodeQueue.hasOwnProperty(uuid)) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
|
|
756
786
|
var queueValue = translate.nodeQueue[uuid];
|
|
757
787
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
788
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
758
791
|
//console.log('------'+lang)
|
|
759
792
|
if(typeof(lang) != 'string' || lang.length < 1){
|
|
760
793
|
continue;
|
|
@@ -762,6 +795,9 @@ var translate = {
|
|
|
762
795
|
//if(translate.language.getLocal() == lang){
|
|
763
796
|
//console.log(translate.nodeQueue[uuid].list[lang]);
|
|
764
797
|
for(var hash in translate.nodeQueue[uuid].list[lang]){
|
|
798
|
+
if (!translate.nodeQueue[uuid].list[lang].hasOwnProperty(hash)) {
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
765
801
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
766
802
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
767
803
|
text = text + '\n' + translate.nodeQueue[uuid].list[lang][hash].original + '='+translate.storage.get('hash_'+translate.language.getCurrent()+'_'+hash);
|
|
@@ -903,6 +939,9 @@ var translate = {
|
|
|
903
939
|
|
|
904
940
|
var data = await translate.storage.IndexedDB.list('hash_*');
|
|
905
941
|
for(var i in data){
|
|
942
|
+
if (!data.hasOwnProperty(i)) {
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
906
945
|
var originalText = data[i].value.originalText.replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
907
946
|
text = text + '\n' + originalText + '='+data[i].value.english.replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
908
947
|
}
|
|
@@ -1183,11 +1222,10 @@ var translate = {
|
|
|
1183
1222
|
}
|
|
1184
1223
|
//console.log('translateNodeslength: '+translateNodes.length);
|
|
1185
1224
|
|
|
1186
|
-
|
|
1187
|
-
setTimeout(function() {
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
}, 10); //这个要比 task.execute() 中的 settimeout 延迟执行删除 translate.inpr.....nodes 的时间要小,目的是前一个发生变动后,记入 inpr...nodes 然后翻译完成后节点发生变化又触发了listener,此时 inpr....nodes 还有,那么这个变化将不做处理,然后 inp.....nodes 再删除这个标记
|
|
1225
|
+
translate.execute(translateNodes);
|
|
1226
|
+
//setTimeout(function() {
|
|
1227
|
+
// translate.execute(translateNodes); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页
|
|
1228
|
+
//}, 10); //这个要比 task.execute() 中的 settimeout 延迟执行删除 translate.inpr.....nodes 的时间要小,目的是前一个发生变动后,记入 inpr...nodes 然后翻译完成后节点发生变化又触发了listener,此时 inpr....nodes 还有,那么这个变化将不做处理,然后 inp.....nodes 再删除这个标记
|
|
1191
1229
|
}
|
|
1192
1230
|
};
|
|
1193
1231
|
// 创建一个观察器实例并传入回调函数
|
|
@@ -1246,7 +1284,7 @@ var translate = {
|
|
|
1246
1284
|
//console.log(translate.nodeQueue[uuid]);
|
|
1247
1285
|
for(var i = 0; i < translate.listener.execute.renderFinishByApi.length; i++){
|
|
1248
1286
|
try{
|
|
1249
|
-
|
|
1287
|
+
translate.listener.execute.renderFinishByApi[i](uuid, from, to);
|
|
1250
1288
|
}catch(e){
|
|
1251
1289
|
console.log(e);
|
|
1252
1290
|
}
|
|
@@ -1336,6 +1374,10 @@ var translate = {
|
|
|
1336
1374
|
execute(){
|
|
1337
1375
|
//先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到
|
|
1338
1376
|
for(var hash in this.taskQueue){
|
|
1377
|
+
if (!this.taskQueue.hasOwnProperty(hash)) {
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1339
1381
|
var tasks = this.taskQueue[hash];
|
|
1340
1382
|
if(typeof(tasks) == 'function'){
|
|
1341
1383
|
//进行异常的预处理调出
|
|
@@ -1358,6 +1400,10 @@ var translate = {
|
|
|
1358
1400
|
|
|
1359
1401
|
//对nodeQueue进行翻译
|
|
1360
1402
|
for(var hash in this.nodes){
|
|
1403
|
+
if (!this.nodes.hasOwnProperty(hash)) {
|
|
1404
|
+
continue;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1361
1407
|
var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务
|
|
1362
1408
|
//var tagName = this.nodes[hash][0].nodeName; //以下节点的tag name
|
|
1363
1409
|
//console.log(tasks);
|
|
@@ -1438,8 +1484,16 @@ var translate = {
|
|
|
1438
1484
|
/** 执行完成后,保存翻译的历史node **/
|
|
1439
1485
|
//将当前翻译完成的node进行缓存记录,以node唯一标识为key, node、以及node当前翻译之后的内容为值进行缓存。方便下一次执行 translate.execute() 时,若值未变化则不进行翻译
|
|
1440
1486
|
for(var hash in renderTask.nodes){
|
|
1487
|
+
if (!renderTask.nodes.hasOwnProperty(hash)) {
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1441
1491
|
//console.log(translate.nodeQueue[uuid].list[lang][hash])
|
|
1442
1492
|
for(var nodeindex in renderTask.nodes[hash]){
|
|
1493
|
+
if (!renderTask.nodes[hash].hasOwnProperty(nodeindex)) {
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1443
1497
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
1444
1498
|
//var nodename = translate.element.getNodeName(translate.nodeQueue[uuid].list[lang][hash].nodes[0].node);
|
|
1445
1499
|
//console.log("nodename:"+nodename);
|
|
@@ -1566,8 +1620,13 @@ var translate = {
|
|
|
1566
1620
|
@param to 翻译为的语种
|
|
1567
1621
|
*/
|
|
1568
1622
|
isAllExecuteFinish:function(uuid, from, to){
|
|
1623
|
+
translate.listener.execute.renderFinishByApiRun(uuid, from, to);
|
|
1624
|
+
|
|
1569
1625
|
//console.log('uuid:'+uuid+', from:'+from+', to:'+to);
|
|
1570
1626
|
for(var lang in translate.translateRequest[uuid]){
|
|
1627
|
+
if (!translate.translateRequest[uuid].hasOwnProperty(lang)) {
|
|
1628
|
+
continue;
|
|
1629
|
+
}
|
|
1571
1630
|
//console.log(translate.translateRequest[uuid])
|
|
1572
1631
|
for(var i = 0; i<translate.translateRequest[uuid][lang].length; i++){
|
|
1573
1632
|
if(translate.translateRequest[uuid][lang][i].executeFinish == 0){
|
|
@@ -1581,11 +1640,12 @@ var translate = {
|
|
|
1581
1640
|
}
|
|
1582
1641
|
}
|
|
1583
1642
|
|
|
1643
|
+
//生命周期触发事件
|
|
1644
|
+
translate.lifecycle.execute.renderFinish_Trigger(uuid, to);
|
|
1645
|
+
|
|
1584
1646
|
//都执行完了,那么设置完毕
|
|
1585
1647
|
translate.state = 0;
|
|
1586
1648
|
translate.executeNumber++;
|
|
1587
|
-
|
|
1588
|
-
translate.listener.execute.renderFinishByApiRun(uuid, from, to);
|
|
1589
1649
|
}
|
|
1590
1650
|
|
|
1591
1651
|
},
|
|
@@ -1593,6 +1653,116 @@ var translate = {
|
|
|
1593
1653
|
//execute() 方法已经被执行过多少次了, 只有execute() 完全执行完,也就是界面渲染完毕后,它才会+1
|
|
1594
1654
|
executeNumber:0,
|
|
1595
1655
|
|
|
1656
|
+
lifecycle:{
|
|
1657
|
+
|
|
1658
|
+
/*
|
|
1659
|
+
translate.execute() 执行相关
|
|
1660
|
+
*/
|
|
1661
|
+
execute:{
|
|
1662
|
+
/*
|
|
1663
|
+
每当触发执行 translate.execute() 时,会先进行当前是否可以正常进行翻译的判定,比如 当前语种是否就已经是翻译之后的语种了是否没必要翻译了等。(这些初始判定可以理解成它的耗时小于1毫秒,几乎没有耗时)
|
|
1664
|
+
经过初始的判断后,发现允许被翻译,那么在向后执行之前,先触发此。
|
|
1665
|
+
也就是在进行翻译之前,触发此。
|
|
1666
|
+
|
|
1667
|
+
@param uuid:translate.nodeQueue[uuid] 这里的
|
|
1668
|
+
@param to 翻译为的语种
|
|
1669
|
+
*/
|
|
1670
|
+
start : [],
|
|
1671
|
+
start_Trigger:function(uuid, to){
|
|
1672
|
+
for(var i = 0; i < translate.lifecycle.execute.start.length; i++){
|
|
1673
|
+
try{
|
|
1674
|
+
translate.lifecycle.execute.start[i](uuid, to);
|
|
1675
|
+
}catch(e){
|
|
1676
|
+
console.log(e);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
},
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
//待整理
|
|
1683
|
+
start_old : [],
|
|
1684
|
+
startRun:function(uuid, from, to){
|
|
1685
|
+
//console.log(translate.nodeQueue[uuid]);
|
|
1686
|
+
for(var i = 0; i < translate.listener.execute.renderStartByApi.length; i++){
|
|
1687
|
+
try{
|
|
1688
|
+
translate.listener.execute.renderStartByApi[i](uuid, from, to);
|
|
1689
|
+
}catch(e){
|
|
1690
|
+
console.log(e);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
},
|
|
1694
|
+
|
|
1695
|
+
/*
|
|
1696
|
+
当扫描整个节点完成,进行翻译(1. 命中本地缓存、 2.进行网络翻译请求)之前,触发
|
|
1697
|
+
待整理
|
|
1698
|
+
*/
|
|
1699
|
+
scanNodesFinsh: [],
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
/*
|
|
1703
|
+
每当触发执行 translate.execute() 时,当缓存中未发现,需要请求翻译API进行翻译时,在发送API请求前,触发此
|
|
1704
|
+
|
|
1705
|
+
@param uuid:translate.nodeQueue[uuid] 这里的
|
|
1706
|
+
@param from 来源语种,翻译前的语种
|
|
1707
|
+
@param to 翻译为的语种
|
|
1708
|
+
@param texts 要翻译的文本,它是一个数组形态,是要进行通过API翻译接口进行翻译的文本,格式如 ['你好','世界']
|
|
1709
|
+
*/
|
|
1710
|
+
translateNetworkBefore:[],
|
|
1711
|
+
translateNetworkBefore_Trigger:function(uuid, from, to, texts){
|
|
1712
|
+
for(var i = 0; i < translate.lifecycle.execute.translateNetworkBefore.length; i++){
|
|
1713
|
+
try{
|
|
1714
|
+
translate.lifecycle.execute.translateNetworkBefore[i](uuid,from, to, texts);
|
|
1715
|
+
}catch(e){
|
|
1716
|
+
console.log(e);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
},
|
|
1720
|
+
|
|
1721
|
+
/*
|
|
1722
|
+
当 translate.execute() 触发网络翻译请求完毕(不管成功还是失败),并将翻译结果渲染到页面完毕后,触发此。
|
|
1723
|
+
@param uuid translate.nodeQueue 的uuid
|
|
1724
|
+
@param from
|
|
1725
|
+
@param to 当前是执行的翻译为什么语种
|
|
1726
|
+
@param text 网络请求翻译的文本/节点/。。。待定
|
|
1727
|
+
*/
|
|
1728
|
+
translateNetworkAfter:[], //已废弃
|
|
1729
|
+
/*
|
|
1730
|
+
|
|
1731
|
+
translateNetworkAfter_Trigger:function(uuid, to){
|
|
1732
|
+
for(var i = 0; i < translate.lifecycle.execute.translateNetworkAfter.length; i++){
|
|
1733
|
+
try{
|
|
1734
|
+
translate.lifecycle.execute.translateNetworkAfter[i](uuid, to);
|
|
1735
|
+
}catch(e){
|
|
1736
|
+
console.log(e);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
},
|
|
1740
|
+
*/
|
|
1741
|
+
|
|
1742
|
+
/*
|
|
1743
|
+
translate.execute() 的翻译渲染完毕触发
|
|
1744
|
+
这个完毕是指它当触发 translate.execute() 进行翻译后,无论是全部命中了本地缓存,还是有部分要通过翻译接口发起多个网络请求,当拿到结果(缓存中的翻译结果或多个不同的有xx语种翻译的网络请求全部完成,这个完成是包含所有成功跟失败的响应),并完成将翻译结果渲染到页面中进行显示后,触发此
|
|
1745
|
+
它跟 translateNetworkFinish 的区别是, translateNetworkFinish 仅仅针对有网络请求的才会触发,而 renderFinish 是如果全部命中了浏览器本地缓存,无需发起任何网络翻译请求这种情况时,也会触发。
|
|
1746
|
+
@param uuid translate.nodeQueue 的uuid
|
|
1747
|
+
@param to 当前是执行的翻译为什么语种
|
|
1748
|
+
*/
|
|
1749
|
+
renderFinish:[function(uuid, to){ //这里默认带着一个触发翻译为英文后,自动对英文进行元素视觉处理,追加空格的
|
|
1750
|
+
if(typeof(translate.visual) != 'undefined'){
|
|
1751
|
+
translate.visual.adjustTranslationSpacesByNodequeueUuid(uuid);
|
|
1752
|
+
}
|
|
1753
|
+
}],
|
|
1754
|
+
renderFinish_Trigger:function(uuid, to){
|
|
1755
|
+
for(var i = 0; i < translate.lifecycle.execute.renderFinish.length; i++){
|
|
1756
|
+
try{
|
|
1757
|
+
translate.lifecycle.execute.renderFinish[i](uuid, to);
|
|
1758
|
+
}catch(e){
|
|
1759
|
+
console.log(e);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
},
|
|
1765
|
+
|
|
1596
1766
|
/*translate.execute() start */
|
|
1597
1767
|
/*
|
|
1598
1768
|
执行翻译操作。翻译的是 nodeQueue 中的
|
|
@@ -1667,11 +1837,11 @@ var translate = {
|
|
|
1667
1837
|
//未指定,判断如果指定了自动获取用户本国语种了,那么进行获取
|
|
1668
1838
|
if(translate.autoDiscriminateLocalLanguage){
|
|
1669
1839
|
translate.executeByLocalLanguage();
|
|
1840
|
+
}else{
|
|
1841
|
+
//没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译
|
|
1842
|
+
translate.state = 0;
|
|
1843
|
+
return;
|
|
1670
1844
|
}
|
|
1671
|
-
|
|
1672
|
-
//没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译
|
|
1673
|
-
translate.state = 0;
|
|
1674
|
-
return;
|
|
1675
1845
|
}
|
|
1676
1846
|
|
|
1677
1847
|
//判断本地语种跟要翻译的目标语种是否一样,如果是一样,那就不需要进行任何翻译
|
|
@@ -1687,6 +1857,10 @@ var translate = {
|
|
|
1687
1857
|
|
|
1688
1858
|
|
|
1689
1859
|
/********** 翻译进行 */
|
|
1860
|
+
|
|
1861
|
+
//生命周期-触发翻译进行之前,用户自定义的钩子
|
|
1862
|
+
translate.lifecycle.execute.start_Trigger(uuid, translate.to);
|
|
1863
|
+
|
|
1690
1864
|
|
|
1691
1865
|
//先进行图片的翻译替换,毕竟图片还有加载的过程
|
|
1692
1866
|
translate.images.execute();
|
|
@@ -1732,6 +1906,27 @@ var translate = {
|
|
|
1732
1906
|
console.log('translate.execute( docs ) 传入的docs.length 过大,超过500,这很不正常,当前 docs.length : '+all.length+' ,如果你感觉真的没问题,请联系作者 http://translate.zvo.cn/43006.html 说明情况,根据你的情况进行分析。 当前只取前500个元素进行翻译');
|
|
1733
1907
|
}
|
|
1734
1908
|
|
|
1909
|
+
//初始化 translate.element.tagAttribute ,主要针对 v3.17.10 版本的适配调整,对 translate.element.tagAttribute 的设置做了改变,做旧版本的适配
|
|
1910
|
+
try{
|
|
1911
|
+
for(var te_tag in translate.element.tagAttribute){
|
|
1912
|
+
if (!translate.element.tagAttribute.hasOwnProperty(te_tag)) {
|
|
1913
|
+
continue;
|
|
1914
|
+
}
|
|
1915
|
+
if(translate.element.tagAttribute[te_tag] instanceof Array){
|
|
1916
|
+
//是 v3.17.10 之前版本的设置方式,要进行对旧版本的适配
|
|
1917
|
+
var tArray = translate.element.tagAttribute[te_tag];
|
|
1918
|
+
translate.element.tagAttribute[te_tag] = {
|
|
1919
|
+
attribute: tArray,
|
|
1920
|
+
condition: function(element){
|
|
1921
|
+
return true;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
}catch(e){
|
|
1927
|
+
console.log(e);
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1735
1930
|
//检索目标内的node元素
|
|
1736
1931
|
for(var i = 0; i< all.length & i < 500; i++){
|
|
1737
1932
|
var node = all[i];
|
|
@@ -1742,6 +1937,9 @@ var translate = {
|
|
|
1742
1937
|
if(translate.language.translateLanguagesRange.length > 0){
|
|
1743
1938
|
//如果大于0,则是有设置,那么只翻译有设置的语种,不在设置中的语种不会参与翻译
|
|
1744
1939
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
1940
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
1941
|
+
continue;
|
|
1942
|
+
}
|
|
1745
1943
|
if(translate.language.translateLanguagesRange.indexOf(lang) < 0){
|
|
1746
1944
|
//删除这个语种
|
|
1747
1945
|
delete translate.nodeQueue[uuid].list[lang];
|
|
@@ -1759,13 +1957,23 @@ var translate = {
|
|
|
1759
1957
|
console.log('您使用translate.js时可能放的位置不对,不要吧 translate.js 放在网页最顶部,这样当 translate.js 进行执行,也就是 translate.execute() 执行时,因为网页是从上往下加载,它放在网页最顶部,那么它执行时网页后面的内容都还没加载出来,这个是不会获取到网页任何内容的,也就是它是不起任何作用的');
|
|
1760
1958
|
}
|
|
1761
1959
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
1960
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
1961
|
+
continue;
|
|
1962
|
+
}
|
|
1762
1963
|
//console.log('lang:'+lang)
|
|
1763
1964
|
for(var hash in translate.nodeQueue[uuid].list[lang]){
|
|
1965
|
+
if (!translate.nodeQueue[uuid].list[lang].hasOwnProperty(hash)) {
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1764
1968
|
//console.log(hash)
|
|
1765
1969
|
if(typeof(translate.nodeQueue[uuid].list[lang][hash]) == 'function'){
|
|
1766
1970
|
//v2.10增加,避免hash冒出个 Contains 出来导致for中的.length 出错
|
|
1767
1971
|
continue;
|
|
1768
1972
|
}
|
|
1973
|
+
if(typeof(translate.nodeQueue[uuid].list[lang][hash].nodes) == 'undefined' || typeof(translate.nodeQueue[uuid].list[lang][hash].nodes.length) == 'undefined'){
|
|
1974
|
+
//v3.16.2 增加,针对深圳北理莫斯科学校龙老师提出的这里 .length 遇到了 undefined 的情况
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1769
1977
|
for(var nodeindex = translate.nodeQueue[uuid].list[lang][hash].nodes.length-1; nodeindex > -1; nodeindex--){
|
|
1770
1978
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].nodes);
|
|
1771
1979
|
var analyse = translate.element.nodeAnalyse.get(translate.nodeQueue[uuid].list[lang][hash].nodes[nodeindex].node);
|
|
@@ -1832,6 +2040,9 @@ var translate = {
|
|
|
1832
2040
|
var twoScanNodes = {};
|
|
1833
2041
|
var cacheScanNodes = []; //同上面的 twoScanNodes,只不过 twoScanNodes 是按照lang存的,而这个不再有lang区分
|
|
1834
2042
|
for(var lang in translate.nodeQueue[uuid]['list']){ //二维数组中,取语言
|
|
2043
|
+
if (!translate.nodeQueue[uuid]['list'].hasOwnProperty(lang)) {
|
|
2044
|
+
continue;
|
|
2045
|
+
}
|
|
1835
2046
|
//console.log('lang:'+lang); //lang为english这种语言标识
|
|
1836
2047
|
if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){
|
|
1837
2048
|
//console.log('lang is null : '+lang);
|
|
@@ -1847,6 +2058,9 @@ var translate = {
|
|
|
1847
2058
|
twoScanNodes[lang] = [];
|
|
1848
2059
|
//二维数组,取hash、value
|
|
1849
2060
|
for(var hash in translate.nodeQueue[uuid]['list'][lang]){
|
|
2061
|
+
if (!translate.nodeQueue[uuid]['list'][lang].hasOwnProperty(hash)) {
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
1850
2064
|
if(typeof(translate.nodeQueue[uuid]['list'][lang][hash]) == 'function'){
|
|
1851
2065
|
//跳出,增加容错。 正常情况下应该不会这样
|
|
1852
2066
|
continue;
|
|
@@ -1994,8 +2208,25 @@ var translate = {
|
|
|
1994
2208
|
//console.log('cacheScanNodes:');
|
|
1995
2209
|
//console.log(cacheScanNodes);
|
|
1996
2210
|
|
|
2211
|
+
|
|
2212
|
+
if(typeof(translate.request.api.translate) != 'string' || translate.request.api.translate == null || translate.request.api.translate.length < 1){
|
|
2213
|
+
//用户已经设置了不掉翻译接口进行翻译
|
|
2214
|
+
translate.state = 0;
|
|
2215
|
+
|
|
2216
|
+
//生命周期触发事件
|
|
2217
|
+
translate.lifecycle.execute.renderFinish_Trigger(uuid, translate.to);
|
|
2218
|
+
translate.executeNumber++;
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
1997
2224
|
/******* 进行第二次扫描、追加入翻译队列。目的是防止缓存打散扫描的待翻译文本 ********/
|
|
1998
2225
|
for(var lang in twoScanNodes){
|
|
2226
|
+
if (!twoScanNodes.hasOwnProperty(lang)) {
|
|
2227
|
+
continue;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
1999
2230
|
//记录第一次扫描的数据,以便跟第二次扫描后的进行对比
|
|
2000
2231
|
var firstScan = Object.keys(translate.nodeQueue[uuid]['list'][lang]);
|
|
2001
2232
|
var firstScan_lang_langth = firstScan.length; //第一次扫描后的数组长度
|
|
@@ -2077,6 +2308,10 @@ var translate = {
|
|
|
2077
2308
|
var fanyiLangs = [];
|
|
2078
2309
|
//console.log(translateTextArray)
|
|
2079
2310
|
for(var lang in translate.nodeQueue[uuid]['list']){ //二维数组中取语言
|
|
2311
|
+
if (!translate.nodeQueue[uuid]['list'].hasOwnProperty(lang)) {
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2080
2315
|
if(typeof(translateTextArray[lang]) == 'undefined'){
|
|
2081
2316
|
continue;
|
|
2082
2317
|
}
|
|
@@ -2112,6 +2347,10 @@ var translate = {
|
|
|
2112
2347
|
//console.log(translate.nodeQueue[uuid]['list'])
|
|
2113
2348
|
if(fanyiLangs.length == 0){
|
|
2114
2349
|
//没有需要翻译的,直接退出
|
|
2350
|
+
|
|
2351
|
+
//生命周期触发事件
|
|
2352
|
+
translate.lifecycle.execute.renderFinish_Trigger(uuid, translate.to);
|
|
2353
|
+
|
|
2115
2354
|
translate.state = 0;
|
|
2116
2355
|
translate.executeNumber++;
|
|
2117
2356
|
return;
|
|
@@ -2119,6 +2358,9 @@ var translate = {
|
|
|
2119
2358
|
|
|
2120
2359
|
//加入 translate.inProgressNodes -- start
|
|
2121
2360
|
for(var lang in translateHashArray){
|
|
2361
|
+
if (!translateHashArray.hasOwnProperty(lang)) {
|
|
2362
|
+
continue;
|
|
2363
|
+
}
|
|
2122
2364
|
if(typeof(translateHashArray[lang]) == 'undefined'){
|
|
2123
2365
|
continue;
|
|
2124
2366
|
}
|
|
@@ -2132,6 +2374,11 @@ var translate = {
|
|
|
2132
2374
|
//console.log('translate.nodeQueue[\''+uuid+'\'][\'list\'][\'chinese_simplified\'][\''+thhash+'\']');
|
|
2133
2375
|
//console.log(lang);
|
|
2134
2376
|
//console.log(translate.nodeQueue[uuid]['list'][lang][thhash].nodes);
|
|
2377
|
+
if(typeof(translate.nodeQueue[uuid]['list'][lang][thhash].nodes) == 'undefined' || typeof(translate.nodeQueue[uuid]['list'][lang][thhash].nodes.length) == 'undefined'){
|
|
2378
|
+
console.log('translate.nodeQueue[\''+uuid+'\'][\'list\'][\''+lang+'\'][\''+thhash+'\'].nodes.length is null ,理论上不应该存在,进行异常报出,但不影响使用,已容错。');
|
|
2379
|
+
continue;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2135
2382
|
for(var ipni = 0; ipni < translate.nodeQueue[uuid]['list'][lang][thhash].nodes.length; ipni++){
|
|
2136
2383
|
//取得这个翻译的node
|
|
2137
2384
|
var ipnode = translate.nodeQueue[uuid]['list'][lang][thhash].nodes[ipni].node;
|
|
@@ -2163,14 +2410,21 @@ var translate = {
|
|
|
2163
2410
|
//状态
|
|
2164
2411
|
translate.state = 20;
|
|
2165
2412
|
|
|
2166
|
-
|
|
2167
2413
|
//进行掉接口翻译
|
|
2168
2414
|
for(var lang_index in fanyiLangs){ //一维数组,取语言
|
|
2415
|
+
if (!fanyiLangs.hasOwnProperty(lang_index)) {
|
|
2416
|
+
continue;
|
|
2417
|
+
}
|
|
2169
2418
|
var lang = fanyiLangs[lang_index];
|
|
2170
|
-
|
|
2419
|
+
if(typeof(lang) != 'string'){
|
|
2420
|
+
continue;
|
|
2421
|
+
}
|
|
2171
2422
|
|
|
2172
2423
|
if(typeof(translateTextArray[lang]) == 'undefined' || translateTextArray[lang].length < 1){
|
|
2173
|
-
console.log('
|
|
2424
|
+
console.log('异常,理论上不应该存在, lang:'+lang+', translateTextArray:');
|
|
2425
|
+
console.log(translateTextArray);
|
|
2426
|
+
console.log('你无需担心,这个只是个提示,它并不影响你翻译的正常进行,只是个异常提示而已,它会自动容错处理的,不会影响翻译的使用。');
|
|
2427
|
+
|
|
2174
2428
|
translate.state = 0;
|
|
2175
2429
|
translate.executeNumber++;
|
|
2176
2430
|
return;
|
|
@@ -2193,7 +2447,8 @@ var translate = {
|
|
|
2193
2447
|
|
|
2194
2448
|
//listener
|
|
2195
2449
|
translate.listener.execute.renderStartByApiRun(uuid, lang, translate.to);
|
|
2196
|
-
|
|
2450
|
+
translate.lifecycle.execute.translateNetworkBefore_Trigger(uuid, lang, translate.to, translateTextArray[lang]);
|
|
2451
|
+
|
|
2197
2452
|
/*** 翻译开始 ***/
|
|
2198
2453
|
var url = translate.request.api.translate;
|
|
2199
2454
|
var data = {
|
|
@@ -2313,10 +2568,10 @@ var translate = {
|
|
|
2313
2568
|
translate.waitingExecute.isAllExecuteFinish(uuid, data.from, data.to);
|
|
2314
2569
|
},10);
|
|
2315
2570
|
}, function(xhr){
|
|
2316
|
-
translate.translateRequest[uuid][
|
|
2317
|
-
translate.translateRequest[uuid][
|
|
2318
|
-
translate.translateRequest[uuid][
|
|
2319
|
-
translate.waitingExecute.isAllExecuteFinish(uuid,
|
|
2571
|
+
translate.translateRequest[uuid][xhr.data.from].executeFinish = 1; //1是执行完毕
|
|
2572
|
+
translate.translateRequest[uuid][xhr.data.from].stoptime = Math.floor(Date.now() / 1000);
|
|
2573
|
+
translate.translateRequest[uuid][xhr.data.from].result = 3;
|
|
2574
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, xhr.data.from, translate.to);
|
|
2320
2575
|
});
|
|
2321
2576
|
/*** 翻译end ***/
|
|
2322
2577
|
}
|
|
@@ -2371,6 +2626,32 @@ var translate = {
|
|
|
2371
2626
|
有几个要翻译的属性,就写上几个。
|
|
2372
2627
|
同样,有几个要额外翻译的tag,就加上几行。
|
|
2373
2628
|
详细文档参考: http://translate.zvo.cn/231504.html
|
|
2629
|
+
|
|
2630
|
+
|
|
2631
|
+
//针对宁德时代提出的需求,需要对 标签本身进行一个判定,是否符合条件符合条件才会翻译,不符合条件则不要进行翻译
|
|
2632
|
+
//比如标签带有 disabled 的才会被翻译,所以要增加一个自定义入参的 function ,返回 true、false
|
|
2633
|
+
translate.element.tagAttribute['input']={
|
|
2634
|
+
//要被翻译的tag的属性,这里是要翻译 input 的 value 、 data-value 这两个属性。
|
|
2635
|
+
//数组格式,可以一个或多个属性
|
|
2636
|
+
attribute:['value','data-value'],
|
|
2637
|
+
//条件,传入一个function,返回一个布尔值。
|
|
2638
|
+
//只有当返回的布尔值是true时,才会对上面设置的 attribute 进行翻译,否则并不会对当前设定标签的 attribute 进行任何翻译操作。
|
|
2639
|
+
condition:function(element){
|
|
2640
|
+
// element 便是当前的元素,
|
|
2641
|
+
// 比如这里是 translate.element.tagAttribute['input'] 那这个 element 参数便是扫描到的具体的 input 元素
|
|
2642
|
+
// 可以针对 element 这个当前元素本身来进行判定,来决定是否进行翻译。
|
|
2643
|
+
// 返回值是布尔值 true、false
|
|
2644
|
+
// return true; //要对 attribute中设置的 ['value','data-value'] 这两个input 的属性的值进行翻译。
|
|
2645
|
+
// 如果不设置或传入 condition ,比如单纯这样设置:
|
|
2646
|
+
// translate.element.tagAttribute['input']={
|
|
2647
|
+
// attribute:['value','data-value']
|
|
2648
|
+
// }
|
|
2649
|
+
// 那么这里默认就是 return true;
|
|
2650
|
+
// return false; //不对 attribute中设置的 ['value','data-value'] 这两个input 的属性的值进行任何操作
|
|
2651
|
+
return true;
|
|
2652
|
+
}
|
|
2653
|
+
};
|
|
2654
|
+
|
|
2374
2655
|
*/
|
|
2375
2656
|
tagAttribute : {},
|
|
2376
2657
|
|
|
@@ -2431,14 +2712,29 @@ var translate = {
|
|
|
2431
2712
|
|
|
2432
2713
|
if(attribute != null && typeof(attribute) == 'string' && attribute.length > 0){
|
|
2433
2714
|
//这个node有属性,替换的是node的属性,而不是nodeValue
|
|
2434
|
-
|
|
2715
|
+
|
|
2716
|
+
var nodeAttributeValue; //这个 attribute 属性的值
|
|
2717
|
+
if(nodename == 'INPUT' && attribute.toLowerCase() == 'value'){
|
|
2718
|
+
//如果是input 的value属性,那么要直接获取,而非通过 attribute ,不然用户自己输入的通过 attribute 是获取不到的 -- catl 赵阳 提出
|
|
2719
|
+
|
|
2720
|
+
nodeAttributeValue = node.value;
|
|
2721
|
+
}else{
|
|
2722
|
+
nodeAttributeValue = node[attribute];
|
|
2723
|
+
}
|
|
2724
|
+
result['text'] = nodeAttributeValue;
|
|
2725
|
+
|
|
2435
2726
|
|
|
2436
2727
|
//替换渲染
|
|
2437
2728
|
if(typeof(originalText) != 'undefined' && originalText.length > 0){
|
|
2438
|
-
if(typeof(
|
|
2729
|
+
if(typeof(nodeAttributeValue) != 'undefined'){
|
|
2439
2730
|
//这种是主流框架,像是vue、element、react 都是用这种 DOM Property 的方式,更快
|
|
2440
|
-
var resultShowText = translate.util.textReplace(
|
|
2441
|
-
|
|
2731
|
+
var resultShowText = translate.util.textReplace(nodeAttributeValue, originalText, resultText, translate.to);
|
|
2732
|
+
if(nodename == 'INPUT' && attribute.toLowerCase() == 'value'){
|
|
2733
|
+
//input 的value 对于用户输入的必须用 .value 操作
|
|
2734
|
+
node.value = resultShowText;
|
|
2735
|
+
}else{
|
|
2736
|
+
node[attribute] = resultShowText; //2025.4.26 变更为此方式
|
|
2737
|
+
}
|
|
2442
2738
|
if(resultShowText.indexOf(resultText) > -1){
|
|
2443
2739
|
result['resultText'] = resultShowText;
|
|
2444
2740
|
}else{
|
|
@@ -2602,7 +2898,9 @@ var translate = {
|
|
|
2602
2898
|
}else{
|
|
2603
2899
|
//替换渲染
|
|
2604
2900
|
if(typeof(originalText) != 'undefined' && originalText != null && originalText.length > 0){
|
|
2901
|
+
//console.log(originalText+'|');
|
|
2605
2902
|
var resultShowText = translate.util.textReplace(node.nodeValue, originalText, resultText, translate.to);
|
|
2903
|
+
//console.log(resultShowText+'|');
|
|
2606
2904
|
node.nodeValue = resultShowText; //2025.4.26 变更为此方式
|
|
2607
2905
|
if(resultShowText.indexOf(resultText) > -1){
|
|
2608
2906
|
result['resultText'] = resultShowText;
|
|
@@ -2674,34 +2972,47 @@ var translate = {
|
|
|
2674
2972
|
//console.log('find:'+nodeNameLowerCase);
|
|
2675
2973
|
//console.log(translate.element.tagAttribute[nodeNameLowerCase]);
|
|
2676
2974
|
|
|
2677
|
-
for(var attributeName_index in translate.element.tagAttribute[nodeNameLowerCase]){
|
|
2975
|
+
for(var attributeName_index in translate.element.tagAttribute[nodeNameLowerCase].attribute){
|
|
2976
|
+
if (!translate.element.tagAttribute[nodeNameLowerCase].attribute.hasOwnProperty(attributeName_index)) {
|
|
2977
|
+
continue;
|
|
2978
|
+
}
|
|
2979
|
+
if(typeof(translate.element.tagAttribute[nodeNameLowerCase].condition) !='undefined' && !translate.element.tagAttribute[nodeNameLowerCase].condition(node)){
|
|
2980
|
+
continue;
|
|
2981
|
+
}
|
|
2678
2982
|
|
|
2679
|
-
var attributeName = translate.element.tagAttribute[nodeNameLowerCase][attributeName_index];
|
|
2983
|
+
var attributeName = translate.element.tagAttribute[nodeNameLowerCase].attribute[attributeName_index];
|
|
2680
2984
|
//console.log(attributeName);
|
|
2681
2985
|
//console.log(node.getAttribute(attributeName));
|
|
2682
2986
|
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
*/
|
|
2688
|
-
var DOMPropOrHTMLAttr = 'HTMLAtrribute';
|
|
2689
|
-
var attributeValue = node.getAttribute(attributeName);
|
|
2690
|
-
if(typeof(attributeValue) == 'undefined' || attributeValue == null){
|
|
2691
|
-
//vue、element、react 中的一些动态赋值,比如 element 中的 el-select 选中后赋予显示出来的文本,getAttribute 就取不到,因为是改动的 DOM属性,所以要用这种方式才能取出来
|
|
2692
|
-
attributeValue = node[attributeName];
|
|
2987
|
+
|
|
2988
|
+
if(nodeNameLowerCase == 'input' && attributeName.toLowerCase() == 'value'){
|
|
2989
|
+
//如果是input 的value属性,那么要直接获取,而非通过 attribute ,不然用户自己输入的通过 attribute 是获取不到的 - catl 赵阳 提出
|
|
2990
|
+
attributeValue = node.value;
|
|
2693
2991
|
DOMPropOrHTMLAttr = 'DOMProperty';
|
|
2992
|
+
}else{
|
|
2993
|
+
/*
|
|
2994
|
+
* 默认是 HtmlAtrribute 也就是 HTML特性。取值有两个:
|
|
2995
|
+
* HTMLAtrribute : HTML特性
|
|
2996
|
+
* DOMProperty : DOM属性
|
|
2997
|
+
*/
|
|
2998
|
+
var DOMPropOrHTMLAttr = 'HTMLAtrribute';
|
|
2999
|
+
var attributeValue = node.getAttribute(attributeName);
|
|
3000
|
+
if(typeof(attributeValue) == 'undefined' || attributeValue == null){
|
|
3001
|
+
//vue、element、react 中的一些动态赋值,比如 element 中的 el-select 选中后赋予显示出来的文本,getAttribute 就取不到,因为是改动的 DOM属性,所以要用这种方式才能取出来
|
|
3002
|
+
attributeValue = node[attributeName];
|
|
3003
|
+
DOMPropOrHTMLAttr = 'DOMProperty';
|
|
3004
|
+
}
|
|
3005
|
+
if(typeof(attributeValue) == 'undefined' || attributeValue == null){
|
|
3006
|
+
//这个tag标签没有这个属性,忽略
|
|
3007
|
+
continue;
|
|
3008
|
+
}
|
|
2694
3009
|
}
|
|
2695
|
-
|
|
2696
|
-
//这个tag标签没有这个属性,忽略
|
|
2697
|
-
continue;
|
|
2698
|
-
}
|
|
3010
|
+
|
|
2699
3011
|
|
|
2700
3012
|
//if(typeof(node.getAttribute(attributeName)) == 'undefined' && typeof(node[attributeName]) == 'undefined'){
|
|
2701
3013
|
// //这个tag标签没有这个 attribute,忽略
|
|
2702
3014
|
// continue
|
|
2703
3015
|
//}
|
|
2704
|
-
|
|
2705
3016
|
//判断当前元素是否在ignore忽略的tag、id、class name中 v3.15.7 增加
|
|
2706
3017
|
if(!translate.ignore.isIgnore(node)){
|
|
2707
3018
|
//加入翻译
|
|
@@ -2780,6 +3091,7 @@ var translate = {
|
|
|
2780
3091
|
|
|
2781
3092
|
//node分析
|
|
2782
3093
|
var nodeAnaly = translate.element.nodeAnalyse.get(node);
|
|
3094
|
+
//console.log(nodeAnaly)
|
|
2783
3095
|
if(nodeAnaly['text'].length > 0){
|
|
2784
3096
|
//有要翻译的目标内容,加入翻译队列
|
|
2785
3097
|
//console.log('addNodeToQueue -- '+nodeAnaly['node']+', text:' + nodeAnaly['text']);
|
|
@@ -2912,6 +3224,16 @@ var translate = {
|
|
|
2912
3224
|
textArray.push(text); //先将主 text 赋予 ,后面如果对主text进行加工分割,分割后会将主text给删除掉
|
|
2913
3225
|
//console.log(textArray);
|
|
2914
3226
|
|
|
3227
|
+
// 处理 ignore.regex
|
|
3228
|
+
for (var ri = 0; ri < translate.ignore.textRegex.length; ri++) {
|
|
3229
|
+
var regex = translate.ignore.textRegex[ri];
|
|
3230
|
+
for (var tai = 0; tai < textArray.length; tai++) {
|
|
3231
|
+
var text = textArray[tai];
|
|
3232
|
+
var ignoreTexts = text.match(regex) || []
|
|
3233
|
+
translate.ignore.text = translate.ignore.text.concat(ignoreTexts)
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
|
|
2915
3237
|
/**** v3.10.2.20241206 - 增加自定义忽略翻译的文本,忽略翻译的文本不会被翻译 - 当然这样会打乱翻译之后阅读的连贯性 ****/
|
|
2916
3238
|
for(var ti = 0; ti<translate.ignore.text.length; ti++){
|
|
2917
3239
|
if(translate.ignore.text[ti].trim().length == 0){
|
|
@@ -2924,7 +3246,6 @@ var translate = {
|
|
|
2924
3246
|
}
|
|
2925
3247
|
|
|
2926
3248
|
|
|
2927
|
-
|
|
2928
3249
|
/**** v3.10.2.20241206 - 自定义术语能力全面优化 - 当然这样会打乱翻译之后阅读的连贯性 ****/
|
|
2929
3250
|
//判断是否进行了翻译,也就是有设置目标语种,并且跟当前语种不一致
|
|
2930
3251
|
if(typeof(translate.temp_nomenclature) == 'undefined'){
|
|
@@ -2936,6 +3257,9 @@ var translate = {
|
|
|
2936
3257
|
if(typeof(translate.nomenclature.data[translate.language.getLocal()]) != 'undefined' && typeof(translate.nomenclature.data[translate.language.getLocal()][translate.to]) != 'undefined'){
|
|
2937
3258
|
var nomenclatureKeyArray;
|
|
2938
3259
|
for(var nomenclatureKey in translate.nomenclature.data[translate.language.getLocal()][translate.to]){
|
|
3260
|
+
if (!translate.nomenclature.data[translate.language.getLocal()][translate.to].hasOwnProperty(nomenclatureKey)) {
|
|
3261
|
+
continue;
|
|
3262
|
+
}
|
|
2939
3263
|
//nomenclatureKey 便是自定义术语的原始文本,值是要替换为的文本
|
|
2940
3264
|
//console.log(nomenclatureKey);
|
|
2941
3265
|
//自定义属于的指定的结果字符串
|
|
@@ -3147,6 +3471,9 @@ var translate = {
|
|
|
3147
3471
|
//console.log(langs);
|
|
3148
3472
|
|
|
3149
3473
|
for(var lang in langs) {
|
|
3474
|
+
if (!langs.hasOwnProperty(lang)) {
|
|
3475
|
+
continue;
|
|
3476
|
+
}
|
|
3150
3477
|
//创建二维数组, key为语种,如 english
|
|
3151
3478
|
/*
|
|
3152
3479
|
放到了 translate.addNodeQueueItem 进行判断
|
|
@@ -3421,11 +3748,10 @@ var translate = {
|
|
|
3421
3748
|
language:{
|
|
3422
3749
|
/*
|
|
3423
3750
|
英语的变种语种,也就是在英语26个字母的基础上加了点别的特殊字母另成的一种语言,而这些语言是没法直接通过识别字符来判断出是哪种语种的
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
法语、意大利语、德语
|
|
3751
|
+
|
|
3752
|
+
法语、意大利语、德语、葡萄牙语
|
|
3427
3753
|
*/
|
|
3428
|
-
englishVarietys : ['french','italian','deutsch'],
|
|
3754
|
+
englishVarietys : ['french','italian','deutsch', 'portuguese'],
|
|
3429
3755
|
|
|
3430
3756
|
//当前本地语种,本地语言,默认是简体中文。设置请使用 translate.language.setLocal(...)。不可直接使用,使用需用 getLocal()
|
|
3431
3757
|
local:'',
|
|
@@ -3487,6 +3813,14 @@ var translate = {
|
|
|
3487
3813
|
清除历史翻译语种的缓存
|
|
3488
3814
|
*/
|
|
3489
3815
|
clearCacheLanguage:function(){
|
|
3816
|
+
if(typeof(translate.language.setUrlParamControl_use) != 'undefined'){
|
|
3817
|
+
if(translate.language.setUrlParamControl_use){
|
|
3818
|
+
console.log('使用提示:')
|
|
3819
|
+
console.log('translate.language.setUrlParamControl(...) 的作用是 可以通过URL传一个语种,来指定当前页面以什么语种显示。 参考文档: http://translate.zvo.cn/4075.html');
|
|
3820
|
+
console.log('translate.language.clearCacheLanguage() 是清除历史翻译语种缓存,也就是清除之前指定翻译为什么语种。 参考文档:http://translate.zvo.cn/4080.html')
|
|
3821
|
+
console.log('如果你执行了 translate.language.setUrlParamControl(...) 那么是要根据url传参来切换语种的,但是后面又出现了 translate.language.clearCacheLanguage() 它会阻止 translate.language.setUrlParamControl(...) 它的设置,即使有url传递翻译为什么语言,也会因为 translate.language.clearCacheLanguage() 给清除掉,使URL传参的语种不起任何作用。')
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3490
3824
|
translate.to = '';
|
|
3491
3825
|
translate.storage.set('to','');
|
|
3492
3826
|
},
|
|
@@ -3494,6 +3828,7 @@ var translate = {
|
|
|
3494
3828
|
//设置可以根据当前访问url的某个get参数来控制使用哪种语言显示。
|
|
3495
3829
|
//比如当前语种是简体中文,网页url是http://translate.zvo.cn/index.html ,那么可以通过在url后面增加 language 参数指定翻译语种,来使网页内容以英文形态显示 http://translate.zvo.cn/index.html?language=english
|
|
3496
3830
|
setUrlParamControl:function(paramName){
|
|
3831
|
+
translate.language.setUrlParamControl_use = true; //标记已执行了 translate.language.setUrlParamControl ,仅仅只是标记,无其他作用
|
|
3497
3832
|
if(typeof(paramName) == 'undefined' || paramName.length < 1){
|
|
3498
3833
|
paramName = 'language';
|
|
3499
3834
|
}
|
|
@@ -3508,25 +3843,85 @@ var translate = {
|
|
|
3508
3843
|
translate.storage.set('to', paramValue);
|
|
3509
3844
|
translate.to = paramValue;
|
|
3510
3845
|
},
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3846
|
+
/*
|
|
3847
|
+
获取翻译区域的原始文本,翻译前的文本。 这里会把空白符等过滤掉,只返回纯显示的文本
|
|
3848
|
+
也就是获取 translate.setDocument(...) 定义的翻译区域中,翻译前,要参与翻译的文本。
|
|
3849
|
+
其中像是 translate.ignore.tag 这种忽略翻译的标签,这里也不会获取的,这里只是获取实际要参与翻译的文本。
|
|
3850
|
+
*/
|
|
3851
|
+
getTranslateAreaText:function(){
|
|
3852
|
+
//v3.16.1 优化,获取本地语种,针对开源中国只对 readme 部分进行翻译的场景,将针对设置的 translate.setDocument() 区域的元素的显示文本进行判定语种
|
|
3853
|
+
var translateAreaText = ''; //翻译区域内当前的文本
|
|
3854
|
+
|
|
3855
|
+
/** 构建虚拟容器,将要翻译的区域放入虚拟容器,以便后续处理 **/
|
|
3856
|
+
var virtualContainer = document.createElement('div'); // 创建虚拟容器,处理、判断也都是针对这个虚拟容器
|
|
3857
|
+
if(translate.documents != null && typeof(translate.documents) != 'undefined' && translate.documents.length > 0){
|
|
3858
|
+
// setDocuments 指定的
|
|
3859
|
+
for(var docs_index = 0; docs_index < translate.documents.length; docs_index++){
|
|
3860
|
+
var doc = translate.documents[docs_index];
|
|
3861
|
+
if(typeof(doc) != 'undefined' && doc != null && typeof(doc.innerText) != 'undefined' && doc.innerText != null && doc.innerText.length > 0){
|
|
3862
|
+
virtualContainer.appendChild(doc.cloneNode(true));
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
}else{
|
|
3866
|
+
//未使用 setDocuments指定,那就是整个网页了
|
|
3867
|
+
//return document.all; //翻译所有的 这是 v3.5.0之前的
|
|
3868
|
+
//v3.5.0 之后采用 拿 html的最上层的demo,而不是 document.all 拿到可能几千个dom
|
|
3869
|
+
if(typeof(document.head) != 'undefined'){
|
|
3870
|
+
virtualContainer.appendChild(document.head.cloneNode(true));
|
|
3871
|
+
}
|
|
3872
|
+
if(typeof(document.body) != 'undefined'){
|
|
3873
|
+
virtualContainer.appendChild(document.body.cloneNode(true));
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
//console.log(virtualContainer);
|
|
3877
|
+
|
|
3878
|
+
|
|
3879
|
+
/** 对虚拟容器中的元素进行处理,移除忽略的 tag (这里暂时就只是移除忽略的tag, 其他忽略的后续再加) **/
|
|
3880
|
+
// 遍历标签列表
|
|
3881
|
+
//console.log('---- remove element');
|
|
3882
|
+
for (var i = 0; i < translate.ignore.tag.length; i++) {
|
|
3883
|
+
var tagName = translate.ignore.tag[i];
|
|
3884
|
+
var elements = virtualContainer.querySelectorAll(tagName);
|
|
3885
|
+
// 将 NodeList 转换为数组
|
|
3886
|
+
var elementArray = Array.prototype.slice.call(elements);
|
|
3887
|
+
// 遍历并移除每个匹配的元素
|
|
3888
|
+
for (var j = 0; j < elementArray.length; j++) {
|
|
3889
|
+
var element = elementArray[j];
|
|
3890
|
+
if (element.parentNode) {
|
|
3891
|
+
//console.log(element);
|
|
3892
|
+
element.parentNode.removeChild(element);
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
//console.log('---- remove element end');
|
|
3517
3897
|
|
|
3518
|
-
|
|
3519
|
-
|
|
3898
|
+
|
|
3899
|
+
/*** 取过滤完后的文本字符 ***/
|
|
3900
|
+
translateAreaText = virtualContainer.innerText;
|
|
3901
|
+
if(translateAreaText == null || typeof(translateAreaText) == 'undefined' || translateAreaText.length < 1){
|
|
3520
3902
|
//未取到,默认赋予简体中文
|
|
3521
3903
|
translate.language.local = 'chinese_simplified';
|
|
3522
3904
|
return;
|
|
3523
3905
|
}
|
|
3906
|
+
// 移除所有空白字符(包括空格、制表符、换行符等)
|
|
3907
|
+
translateAreaText = translateAreaText.replace(/\s/g, '');
|
|
3908
|
+
|
|
3909
|
+
//console.log('translateAreaText:\n'+translateAreaText);
|
|
3910
|
+
return translateAreaText;
|
|
3911
|
+
},
|
|
3912
|
+
//自动识别当前页面是什么语种
|
|
3913
|
+
autoRecognitionLocalLanguage:function(){
|
|
3914
|
+
if(translate.language.local != null && translate.language.local.length > 2){
|
|
3915
|
+
//已设置过了,不需要再设置
|
|
3916
|
+
return translate.language.local;
|
|
3917
|
+
}
|
|
3524
3918
|
|
|
3525
|
-
|
|
3919
|
+
var translateAreaText = translate.language.getTranslateAreaText();
|
|
3526
3920
|
|
|
3527
3921
|
//默认赋予简体中文
|
|
3528
3922
|
translate.language.local = 'chinese_simplified';
|
|
3529
|
-
var recognition = translate.language.recognition(
|
|
3923
|
+
var recognition = translate.language.recognition(translateAreaText);
|
|
3924
|
+
//console.log(recognition);
|
|
3530
3925
|
translate.language.local = recognition.languageName;
|
|
3531
3926
|
return translate.language.local;
|
|
3532
3927
|
/* v3.1优化
|
|
@@ -3676,6 +4071,109 @@ var translate = {
|
|
|
3676
4071
|
//console.log('get end');
|
|
3677
4072
|
return langStrs;
|
|
3678
4073
|
},
|
|
4074
|
+
/*
|
|
4075
|
+
语种识别策略
|
|
4076
|
+
|
|
4077
|
+
str 要识别的字符串
|
|
4078
|
+
data 对于str字符串识别的结果,格式如:
|
|
4079
|
+
{
|
|
4080
|
+
languageName: 'english',
|
|
4081
|
+
languageArray:[
|
|
4082
|
+
english:[
|
|
4083
|
+
list[
|
|
4084
|
+
{beforeText: ' ', afterText: ' ', text: 'hello word'},
|
|
4085
|
+
{beforeText: ' ', afterText: ' ', text: 'who?'},
|
|
4086
|
+
],
|
|
4087
|
+
number:12
|
|
4088
|
+
],
|
|
4089
|
+
japanese:[
|
|
4090
|
+
......
|
|
4091
|
+
]
|
|
4092
|
+
]
|
|
4093
|
+
}
|
|
4094
|
+
有关这里面具体参数的说明,参考 translate.language.recognition 的说明
|
|
4095
|
+
languagesSize key:语言名, value:语言字符数
|
|
4096
|
+
allSize 当前所有发现的语种,加起来的总字符数,也就是 languagesSize 遍历所有的value相加的数
|
|
4097
|
+
|
|
4098
|
+
最后,要 return data;
|
|
4099
|
+
*/
|
|
4100
|
+
recognitionAlgorithm:function(str, data, languagesSize, allSize){
|
|
4101
|
+
|
|
4102
|
+
/*
|
|
4103
|
+
如果英语跟罗曼语族(法语意大利语等多个语言)一起出现,且当前 data.languageName 认定是英语(也就是英文字符占比最大),那么要判定一下:
|
|
4104
|
+
如果 罗曼语族的字符数/英文的字符数 > 0.008 , 那么认为当前是罗曼语族的中的某个语种, 在对其判定出具体是罗曼语族中的哪个语种赋予最终结果。
|
|
4105
|
+
*/
|
|
4106
|
+
if(typeof(languagesSize['english']) != 'undefined' && typeof(languagesSize['romance']) != 'undefined' && data.languageName == 'english'){
|
|
4107
|
+
if(languagesSize['romance']/languagesSize['english'] > 0.008){
|
|
4108
|
+
//排定是罗曼语族了,那么判断一下到底是 法语、西班牙语、葡萄牙语、意大利语 中的哪一种呢
|
|
4109
|
+
|
|
4110
|
+
//先判定是否有设置本地语种是罗曼语族中其中的某一个
|
|
4111
|
+
if(typeof(translate.language.local) != 'undefined' && translate.language.local.length > 1){
|
|
4112
|
+
if(translate.language.englishVarietys.indexOf(translate.language.local) > -1){
|
|
4113
|
+
//发现当前设置的是小语种,那么将当前识别的语种识别为 本地设置的这个小语种。
|
|
4114
|
+
data.languageName = translate.language.local;
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
|
|
4118
|
+
if(data.languageName == 'english'){
|
|
4119
|
+
//还是英语,那就是没有经过上面本地语种的判定,那进行罗曼语的具体语种识别
|
|
4120
|
+
|
|
4121
|
+
var romanceSentenceLanguage = translate.language.romanceSentenceAnaly(str);
|
|
4122
|
+
if(romanceSentenceLanguage.length == 0){
|
|
4123
|
+
console.log('语种识别异常,应该是 法语、西班牙语、葡萄牙语、意大利语 中的一种才是,除非是除了这四种语种之外的别的 罗曼语族 中的语种,当前已将 '+ str +'识别为英语。 你可以联系我们求助 https://translate.zvo.cn/4030.html');
|
|
4124
|
+
}else{
|
|
4125
|
+
data.languageName = romanceSentenceLanguage;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
}
|
|
4129
|
+
}
|
|
4130
|
+
|
|
4131
|
+
|
|
4132
|
+
/*
|
|
4133
|
+
日语判定
|
|
4134
|
+
如果发现日语存在,且当前 data.languageName 认定不是日语,那么要判定一下:
|
|
4135
|
+
如果 日语的字符数/所有字符数 的字符数 > 0.08 , 那么认为当前是日语的
|
|
4136
|
+
*/
|
|
4137
|
+
if( typeof(languagesSize['japanese']) != 'undefined' && data.languageName != 'japanese'){
|
|
4138
|
+
if(languagesSize['japanese']/allSize > 0.08){
|
|
4139
|
+
data.languageName = 'japanese'
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
/*
|
|
4144
|
+
如果发现英语、简体中文或繁体中文 一起存在,且当前 data.languageName 认定是英语时,那么要判定一下:
|
|
4145
|
+
如果 (简体中文+繁体中文)的字符数/英语 > 0.05 , 那么认为当前是简体中文(不认为是繁体中文,因为下面还有 简体中文跟繁体中文的判定)
|
|
4146
|
+
*/
|
|
4147
|
+
if( (typeof(languagesSize['chinese_simplified']) != 'undefined' || typeof(languagesSize['chinese_traditional']) != 'undefined' ) && typeof(languagesSize['english']) != 'undefined' && data.languageName == 'english'){
|
|
4148
|
+
var size = 0;
|
|
4149
|
+
if(typeof(languagesSize['chinese_simplified']) != 'undefined'){
|
|
4150
|
+
size = size + languagesSize['chinese_simplified'];
|
|
4151
|
+
}
|
|
4152
|
+
if(typeof(languagesSize['chinese_traditional']) != 'undefined'){
|
|
4153
|
+
size = size + languagesSize['chinese_traditional'];
|
|
4154
|
+
}
|
|
4155
|
+
if(size/languagesSize['english'] > 0.05){
|
|
4156
|
+
data.languageName = 'chinese_simplified'
|
|
4157
|
+
}
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
|
|
4161
|
+
/*
|
|
4162
|
+
如果简体中文跟繁体中文一起出现,且当前 data.languageName 认定是简体中文(也就是简体中文字符占比最大),那么要判定一下繁体中文:
|
|
4163
|
+
如果 繁体中文的字符数/简体中文的字符数 > 0.08 , 那么认为当前是繁体中文的
|
|
4164
|
+
*/
|
|
4165
|
+
if(typeof(languagesSize['chinese_simplified']) != 'undefined' && typeof(languagesSize['chinese_traditional']) != 'undefined' && data.languageName == 'chinese_simplified'){
|
|
4166
|
+
if(languagesSize['chinese_traditional']/languagesSize['chinese_simplified'] > 0.03){
|
|
4167
|
+
data.languageName = 'chinese_traditional'
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
/* if(langkeys.indexOf('chinese_simplified') > -1 && langkeys.indexOf('chinese_traditional') > -1){
|
|
4171
|
+
langsNumber['chinese_simplified'] = 0;
|
|
4172
|
+
} */
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
return data;
|
|
4176
|
+
},
|
|
3679
4177
|
|
|
3680
4178
|
/*
|
|
3681
4179
|
* 识别字符串是什么语种。它是 get() 的扩展,以代替get返回更多
|
|
@@ -3686,12 +4184,14 @@ var translate = {
|
|
|
3686
4184
|
{
|
|
3687
4185
|
languageName: 'english',
|
|
3688
4186
|
languageArray:[
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
4187
|
+
english:[
|
|
4188
|
+
list[
|
|
4189
|
+
{beforeText: ' ', afterText: ' ', text: 'hello word'},
|
|
4190
|
+
{beforeText: ' ', afterText: ' ', text: 'who?'},
|
|
4191
|
+
],
|
|
4192
|
+
number:12
|
|
3692
4193
|
],
|
|
3693
|
-
|
|
3694
|
-
{beforeText: ' ', afterText: ' ', text: 'ẽ '},
|
|
4194
|
+
japanese:[
|
|
3695
4195
|
......
|
|
3696
4196
|
]
|
|
3697
4197
|
]
|
|
@@ -3711,7 +4211,12 @@ var translate = {
|
|
|
3711
4211
|
var langsNumber = []; //key 语言名, value 语言字符数
|
|
3712
4212
|
var langsNumberOriginal = []; //同上,只不过这个不会进行清空字符数
|
|
3713
4213
|
var allNumber = 0;//总字数
|
|
4214
|
+
|
|
4215
|
+
/** 进行字数统计相关 - start **/
|
|
3714
4216
|
for(var key in langs){
|
|
4217
|
+
if (!langs.hasOwnProperty(key)) {
|
|
4218
|
+
continue;
|
|
4219
|
+
}
|
|
3715
4220
|
if(typeof(langs[key]) != 'object'){
|
|
3716
4221
|
continue;
|
|
3717
4222
|
}
|
|
@@ -3723,53 +4228,17 @@ var translate = {
|
|
|
3723
4228
|
langsNumber[key] = langStrLength;
|
|
3724
4229
|
langsNumberOriginal[key] = langStrLength;
|
|
3725
4230
|
}
|
|
4231
|
+
/** 进行字数统计相关 - end **/
|
|
3726
4232
|
|
|
3727
|
-
//过滤 语种的字符数小于总字符数 百分之五的,低于这个数,将忽略
|
|
3728
|
-
var langkeys = [];
|
|
3729
|
-
for(var lang in langsNumber){
|
|
3730
|
-
if(langsNumber[lang]/allNumber > 0.01){
|
|
3731
|
-
langkeys[langkeys.length] = lang+'';
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
4233
|
|
|
3735
|
-
if(langkeys.length > 1 && langkeys.indexOf('english') > -1){
|
|
3736
|
-
//console.log('出现了english, 并且english跟其他语种一起出现那么删除english,因为什么法语德语乱七八糟的都有英语。而且中文跟英文一起,如果认为是英文的话,有时候中文会不被翻译');
|
|
3737
|
-
//这里先判断一下是否有发现了 罗曼语族
|
|
3738
|
-
if(langkeys.indexOf('romance') > -1){
|
|
3739
|
-
//发现了,那么判断一下到底是 法语、西班牙语、葡萄牙语、意大利语 中的哪一种呢
|
|
3740
|
-
var romanceSentenceLanguage = translate.language.romanceSentenceAnaly(str);
|
|
3741
|
-
if(romanceSentenceLanguage.length == 0){
|
|
3742
|
-
console.log('语种识别异常,应该是 法语、西班牙语、葡萄牙语、意大利语 中的一种才是,除非是除了这四种语种之外的别的 罗曼语族 中的语种,当前已将 '+ str +'识别为英语。 你可以联系我们求助 https://translate.zvo.cn/4030.html');
|
|
3743
|
-
}else{
|
|
3744
|
-
//console.log(langsNumber);
|
|
3745
|
-
langsNumber[romanceSentenceLanguage] = langsNumber['romance']+langsNumber['english'];
|
|
3746
|
-
//console.log('set romance to '+romanceSentenceLanguage+' : \t'+str);
|
|
3747
|
-
langsNumber['english'] = 0;
|
|
3748
|
-
}
|
|
3749
|
-
}else{
|
|
3750
|
-
langsNumber['english'] = 0;
|
|
3751
|
-
}
|
|
3752
|
-
}
|
|
3753
|
-
|
|
3754
|
-
//如果简体中文跟繁体中文一起出现,那么会判断当前句子为繁体中文,将简体中文字符数置0
|
|
3755
|
-
if(langkeys.indexOf('chinese_simplified') > -1 && langkeys.indexOf('chinese_traditional') > -1){
|
|
3756
|
-
//langkeys.splice(langkeys.indexOf('chinese_simplified'), 1);
|
|
3757
|
-
langsNumber['chinese_simplified'] = 0;
|
|
3758
|
-
}
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
//如果发现日语字符,那么将发现的简体中文、繁体中文字符数量置零
|
|
3762
|
-
if(langkeys.length > 1 && langkeys.indexOf('japanese') > -1){
|
|
3763
|
-
langsNumber['chinese_simplified'] = 0;
|
|
3764
|
-
langsNumber['chinese_traditional'] = 0;
|
|
3765
|
-
}
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
4234
|
|
|
3769
4235
|
//从 langsNumber 中找出字数最多的来
|
|
3770
4236
|
var maxLang = ''; //字数最多的语种
|
|
3771
4237
|
var maxNumber = 0;
|
|
3772
4238
|
for(var lang in langsNumber){
|
|
4239
|
+
if (!langsNumber.hasOwnProperty(lang)) {
|
|
4240
|
+
continue;
|
|
4241
|
+
}
|
|
3773
4242
|
if(langsNumber[lang] > maxNumber){
|
|
3774
4243
|
maxLang = lang;
|
|
3775
4244
|
maxNumber = langsNumber[lang];
|
|
@@ -3779,6 +4248,9 @@ var translate = {
|
|
|
3779
4248
|
//重新组合返回值的 languageArray
|
|
3780
4249
|
var languageArray = {};
|
|
3781
4250
|
for(var lang in langs){
|
|
4251
|
+
if (!langs.hasOwnProperty(lang)) {
|
|
4252
|
+
continue;
|
|
4253
|
+
}
|
|
3782
4254
|
languageArray[lang] = {};
|
|
3783
4255
|
languageArray[lang].number = langsNumberOriginal[lang];
|
|
3784
4256
|
languageArray[lang].list = langs[lang];
|
|
@@ -3788,19 +4260,9 @@ var translate = {
|
|
|
3788
4260
|
languageName: maxLang,
|
|
3789
4261
|
languageArray: languageArray
|
|
3790
4262
|
};
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
//如果识别的语种是英语,那便不仅仅是英语,因为法语、德语、意大利语也是在英语里面,还要判断一下是否用户自己设置了具体语种是否是英语延伸的小语种
|
|
3795
|
-
|
|
3796
|
-
var localLang = translate.language.getLocal(); //本地语种
|
|
3797
|
-
if(translate.language.englishVarietys.indexOf(localLang) > -1){
|
|
3798
|
-
//发现当前设置的是小语种,那么将当前识别的语种识别为 本地设置的这个小语种。
|
|
3799
|
-
result.languageName = localLang;
|
|
3800
|
-
}
|
|
3801
|
-
}
|
|
3802
|
-
|
|
3803
|
-
return result;
|
|
4263
|
+
|
|
4264
|
+
//最后进行一层简单的算法处理
|
|
4265
|
+
return translate.language.recognitionAlgorithm(str, result, langsNumber, allNumber);
|
|
3804
4266
|
},
|
|
3805
4267
|
/*
|
|
3806
4268
|
传入一个char,返回这个char属于什么语种,返回如 如果返回空字符串,那么表示未获取到是什么语种
|
|
@@ -4448,6 +4910,10 @@ var translate = {
|
|
|
4448
4910
|
return;
|
|
4449
4911
|
}
|
|
4450
4912
|
|
|
4913
|
+
if(typeof(translate.request.api.ip) != 'string' || translate.request.api.ip == null || translate.request.api.ip.length < 1){
|
|
4914
|
+
return;
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4451
4917
|
//如果用户浏览器没读到默认语言,或者默认语言没有对应到translate.js支持的语种,那么在采用ip识别的方式
|
|
4452
4918
|
translate.request.post(translate.request.api.ip, {}, function(data){
|
|
4453
4919
|
//console.log(data);
|
|
@@ -4517,7 +4983,7 @@ var translate = {
|
|
|
4517
4983
|
|
|
4518
4984
|
//判断它后面是否还有文本
|
|
4519
4985
|
if(originalIndex+1 < text.length){
|
|
4520
|
-
|
|
4986
|
+
let char = text.charAt(originalIndex+translateOriginal.length);
|
|
4521
4987
|
//console.log(char);
|
|
4522
4988
|
if(/。/.test(char)){
|
|
4523
4989
|
replaceResultText = replaceResultText + '. ';
|
|
@@ -4531,8 +4997,12 @@ var translate = {
|
|
|
4531
4997
|
}else if([' ', '\n','\t',']','|', '_','-','/'].indexOf(char) !== -1){
|
|
4532
4998
|
// 如果后面的字符是 这些字符,那么不用添加空格隔开
|
|
4533
4999
|
}else{
|
|
4534
|
-
|
|
4535
|
-
|
|
5000
|
+
//补充上一个空格,用于将两个单词隔开。 不过 ,如果当前 replaceResultText 的最后一个字符也是空格,那就不需要再加空格了。 这里就只判断空格就好了,至于其他的换行等基本不会出现这个情况,所以不考虑
|
|
5001
|
+
if(replaceResultText.length > 0 && replaceResultText.charAt(replaceResultText.length-1) == ' '){
|
|
5002
|
+
//replaceResultText 本身有值,且最后一个字符就是空格,就不需要再追加空格进行隔开了
|
|
5003
|
+
}else{
|
|
5004
|
+
replaceResultText = replaceResultText + ' ';
|
|
5005
|
+
}
|
|
4536
5006
|
}
|
|
4537
5007
|
|
|
4538
5008
|
}
|
|
@@ -4553,16 +5023,23 @@ var translate = {
|
|
|
4553
5023
|
replaceOriginalText = ':'+replaceOriginalText;
|
|
4554
5024
|
}else if([' ', '\n','\t','[', '|', '_','-','/'].indexOf(char) !== -1){
|
|
4555
5025
|
// 如果前面的字符是 这些字符,那么不用添加空格隔开
|
|
5026
|
+
//console.log('不需要空格隔开的');
|
|
4556
5027
|
}else{
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
5028
|
+
//补充上一个空格,用于将两个单词隔开。 不过 ,如果当前 replaceResultText 的第一个字符也是空格,那就不需要再加空格了。 这里就只判断空格就好了,至于其他的换行等基本不会出现这个情况,所以不考虑
|
|
5029
|
+
if(replaceResultText.length > 0 && replaceResultText.charAt(0) == ' '){
|
|
5030
|
+
//replaceResultText 本身有值,且最后一个字符就是空格,就不需要再追加空格进行隔开了
|
|
5031
|
+
}else{
|
|
5032
|
+
replaceResultText = ' '+replaceResultText;
|
|
5033
|
+
}
|
|
5034
|
+
//console.log('before add space : '+replaceResultText);
|
|
4560
5035
|
}
|
|
4561
5036
|
}
|
|
4562
5037
|
}else{
|
|
4563
5038
|
//如果是其他语种比如英语法语翻译为中文、日文,那么标点符号也要判断的,这个因为目前这个场景还没咋遇到,就不判断了,遇到了在加。
|
|
4564
5039
|
|
|
4565
5040
|
}
|
|
5041
|
+
//console.log(replaceResultText)
|
|
5042
|
+
//console.log(replaceResultText.length)
|
|
4566
5043
|
|
|
4567
5044
|
let replaceResult = translate.util.replaceFromIndex(text, currentReplaceEndIndex, replaceOriginalText, replaceResultText);
|
|
4568
5045
|
if(replaceResult.replaceEndIndex < 1){
|
|
@@ -4658,6 +5135,9 @@ var translate = {
|
|
|
4658
5135
|
}
|
|
4659
5136
|
|
|
4660
5137
|
for(var item in numbers){
|
|
5138
|
+
if (!numbers.hasOwnProperty(item)) {
|
|
5139
|
+
continue;
|
|
5140
|
+
}
|
|
4661
5141
|
if(numbers[item]===maxNum){
|
|
4662
5142
|
maxStr.push(item)
|
|
4663
5143
|
}
|
|
@@ -5025,6 +5505,7 @@ var translate = {
|
|
|
5025
5505
|
value: translate.js 的语种标识
|
|
5026
5506
|
*/
|
|
5027
5507
|
browserLanguage:{
|
|
5508
|
+
'zh':'chinese_simplified',
|
|
5028
5509
|
'zh-CN':'chinese_simplified',
|
|
5029
5510
|
'zh-TW':'chinese_traditional',
|
|
5030
5511
|
'zh-HK':'chinese_traditional',
|
|
@@ -5198,7 +5679,43 @@ var translate = {
|
|
|
5198
5679
|
}
|
|
5199
5680
|
|
|
5200
5681
|
return result;
|
|
5682
|
+
},
|
|
5683
|
+
|
|
5684
|
+
/*js translate.util.getElementPosition start*/
|
|
5685
|
+
/*
|
|
5686
|
+
计算一个元素在浏览器中的坐标系,其绝对定位、以及实际显示出来所占用的区域,宽、高
|
|
5687
|
+
*/
|
|
5688
|
+
getElementPosition:function (node) {
|
|
5689
|
+
// 获取元素的边界矩形信息(相对于视口)
|
|
5690
|
+
const rect = node.getBoundingClientRect();
|
|
5691
|
+
|
|
5692
|
+
// 获取当前页面的滚动位置(兼容不同浏览器)
|
|
5693
|
+
const scrollX = window.scrollX || document.documentElement.scrollLeft;
|
|
5694
|
+
const scrollY = window.scrollY || document.documentElement.scrollTop;
|
|
5695
|
+
|
|
5696
|
+
// 计算元素在文档中的起始坐标
|
|
5697
|
+
const startX = rect.left + scrollX;
|
|
5698
|
+
const startY = rect.top + scrollY;
|
|
5699
|
+
|
|
5700
|
+
// 计算元素的宽度和高度
|
|
5701
|
+
const width = rect.right - rect.left;
|
|
5702
|
+
const height = rect.bottom - rect.top;
|
|
5703
|
+
|
|
5704
|
+
// 计算元素在文档中的结束坐标
|
|
5705
|
+
const endX = startX + width;
|
|
5706
|
+
const endY = startY + height;
|
|
5707
|
+
|
|
5708
|
+
// 返回包含所有信息的对象(使用ES5兼容语法)
|
|
5709
|
+
return {
|
|
5710
|
+
startX: startX,
|
|
5711
|
+
startY: startY,
|
|
5712
|
+
endX: endX,
|
|
5713
|
+
endY: endY,
|
|
5714
|
+
width: width,
|
|
5715
|
+
height: height
|
|
5716
|
+
};
|
|
5201
5717
|
}
|
|
5718
|
+
/*js translate.util.getElementPosition end*/
|
|
5202
5719
|
},
|
|
5203
5720
|
//机器翻译采用哪种翻译服务
|
|
5204
5721
|
service:{
|
|
@@ -5227,6 +5744,9 @@ var translate = {
|
|
|
5227
5744
|
if(typeof(serviceName) == 'string'){
|
|
5228
5745
|
translate.service.name = serviceName;
|
|
5229
5746
|
if(serviceName != 'translate.service'){
|
|
5747
|
+
//增加元素整体翻译能力
|
|
5748
|
+
translate.whole.enableAll();
|
|
5749
|
+
|
|
5230
5750
|
if(serviceName.toLowerCase() == 'giteeai'){
|
|
5231
5751
|
//设定翻译接口为GiteeAI的
|
|
5232
5752
|
translate.request.api.host=['https://giteeai.zvo.cn/','https://deutsch.enterprise.api.translate.zvo.cn:1000/','https://api.translate.zvo.cn:1000/'];
|
|
@@ -5237,9 +5757,6 @@ var translate = {
|
|
|
5237
5757
|
translate.request.api.host=['https://siliconflow.zvo.cn/','https://america.api.translate.zvo.cn:1414/','https://deutsch.enterprise.api.translate.zvo.cn:1414/'];
|
|
5238
5758
|
return;
|
|
5239
5759
|
}
|
|
5240
|
-
|
|
5241
|
-
//增加元素整体翻译能力
|
|
5242
|
-
translate.whole.enableAll();
|
|
5243
5760
|
}
|
|
5244
5761
|
}
|
|
5245
5762
|
},
|
|
@@ -5254,6 +5771,7 @@ var translate = {
|
|
|
5254
5771
|
},
|
|
5255
5772
|
|
|
5256
5773
|
language:{
|
|
5774
|
+
|
|
5257
5775
|
json:[{"id":"ukrainian","name":"Україна","serviceId":"uk"},{"id":"norwegian","name":"Norge","serviceId":"no"},{"id":"welsh","name":"Iaith Weleg","serviceId":"cy"},{"id":"dutch","name":"nederlands","serviceId":"nl"},{"id":"japanese","name":"日本語","serviceId":"ja"},{"id":"filipino","name":"Pilipino","serviceId":"fil"},{"id":"english","name":"English","serviceId":"en"},{"id":"lao","name":"ກະຣຸນາ","serviceId":"lo"},{"id":"telugu","name":"తెలుగుName","serviceId":"te"},{"id":"romanian","name":"Română","serviceId":"ro"},{"id":"nepali","name":"नेपालीName","serviceId":"ne"},{"id":"french","name":"Français","serviceId":"fr"},{"id":"haitian_creole","name":"Kreyòl ayisyen","serviceId":"ht"},{"id":"czech","name":"český","serviceId":"cs"},{"id":"swedish","name":"Svenska","serviceId":"sv"},{"id":"russian","name":"Русский язык","serviceId":"ru"},{"id":"malagasy","name":"Malagasy","serviceId":"mg"},{"id":"burmese","name":"ဗာရမ်","serviceId":"my"},{"id":"pashto","name":"پښتوName","serviceId":"ps"},{"id":"thai","name":"คนไทย","serviceId":"th"},{"id":"armenian","name":"Արմենյան","serviceId":"hy"},{"id":"chinese_simplified","name":"简体中文","serviceId":"zh-CHS"},{"id":"persian","name":"Persian","serviceId":"fa"},{"id":"chinese_traditional","name":"繁體中文","serviceId":"zh-CHT"},{"id":"kurdish","name":"Kurdî","serviceId":"ku"},{"id":"turkish","name":"Türkçe","serviceId":"tr"},{"id":"hindi","name":"हिन्दी","serviceId":"hi"},{"id":"bulgarian","name":"български","serviceId":"bg"},{"id":"malay","name":"Malay","serviceId":"ms"},{"id":"swahili","name":"Kiswahili","serviceId":"sw"},{"id":"oriya","name":"ଓଡିଆ","serviceId":"or"},{"id":"icelandic","name":"ÍslandName","serviceId":"is"},{"id":"irish","name":"Íris","serviceId":"ga"},{"id":"khmer","name":"ភាសាខ្មែរName","serviceId":"km"},{"id":"gujarati","name":"ગુજરાતી","serviceId":"gu"},{"id":"slovak","name":"Slovenská","serviceId":"sk"},{"id":"kannada","name":"ಕನ್ನಡ್Name","serviceId":"kn"},{"id":"hebrew","name":"היברית","serviceId":"he"},{"id":"hungarian","name":"magyar","serviceId":"hu"},{"id":"marathi","name":"मराठीName","serviceId":"mr"},{"id":"tamil","name":"தாமில்","serviceId":"ta"},{"id":"estonian","name":"eesti keel","serviceId":"et"},{"id":"malayalam","name":"മലമാലം","serviceId":"ml"},{"id":"inuktitut","name":"ᐃᓄᒃᑎᑐᑦ","serviceId":"iu"},{"id":"arabic","name":"بالعربية","serviceId":"ar"},{"id":"deutsch","name":"Deutsch","serviceId":"de"},{"id":"slovene","name":"slovenščina","serviceId":"sl"},{"id":"bengali","name":"বেঙ্গালী","serviceId":"bn"},{"id":"urdu","name":"اوردو","serviceId":"ur"},{"id":"azerbaijani","name":"azerbaijani","serviceId":"az"},{"id":"portuguese","name":"português","serviceId":"pt"},{"id":"samoan","name":"lifiava","serviceId":"sm"},{"id":"afrikaans","name":"afrikaans","serviceId":"af"},{"id":"tongan","name":"汤加语","serviceId":"to"},{"id":"greek","name":"ελληνικά","serviceId":"el"},{"id":"indonesian","name":"IndonesiaName","serviceId":"id"},{"id":"spanish","name":"Español","serviceId":"es"},{"id":"danish","name":"dansk","serviceId":"da"},{"id":"amharic","name":"amharic","serviceId":"am"},{"id":"punjabi","name":"ਪੰਜਾਬੀName","serviceId":"pa"},{"id":"albanian","name":"albanian","serviceId":"sq"},{"id":"lithuanian","name":"Lietuva","serviceId":"lt"},{"id":"italian","name":"italiano","serviceId":"it"},{"id":"vietnamese","name":"Tiếng Việt","serviceId":"vi"},{"id":"korean","name":"한국어","serviceId":"ko"},{"id":"maltese","name":"Malti","serviceId":"mt"},{"id":"finnish","name":"suomi","serviceId":"fi"},{"id":"catalan","name":"català","serviceId":"ca"},{"id":"croatian","name":"hrvatski","serviceId":"hr"},{"id":"bosnian","name":"bosnian","serviceId":"bs-Latn"},{"id":"polish","name":"Polski","serviceId":"pl"},{"id":"latvian","name":"latviešu","serviceId":"lv"},{"id":"maori","name":"Maori","serviceId":"mi"}],
|
|
5258
5776
|
/*
|
|
5259
5777
|
获取map形式的语言列表
|
|
@@ -5282,11 +5800,22 @@ var translate = {
|
|
|
5282
5800
|
var textArray = JSON.parse(decodeURIComponent(data.text));
|
|
5283
5801
|
let translateTextArray = translate.util.split(textArray, 40000, 900);
|
|
5284
5802
|
|
|
5285
|
-
translate.request.send(translate.service.edge.api.auth, {}, function(auth){
|
|
5803
|
+
translate.request.send(translate.service.edge.api.auth, {},{}, function(auth){
|
|
5804
|
+
var appendXhrData = {
|
|
5805
|
+
"from":data.from+'',
|
|
5806
|
+
"to":data.to,
|
|
5807
|
+
"text":data.text
|
|
5808
|
+
};
|
|
5286
5809
|
var from = data.from;
|
|
5287
5810
|
if(from != 'auto'){
|
|
5288
|
-
from
|
|
5811
|
+
if(from == 'romance'){
|
|
5812
|
+
//这里额外加了一个罗曼语族(romance)会自动认为是法语(fr)
|
|
5813
|
+
from = 'fr';
|
|
5814
|
+
}else{
|
|
5815
|
+
from = translate.service.edge.language.getMap()[data.from];
|
|
5816
|
+
}
|
|
5289
5817
|
}
|
|
5818
|
+
|
|
5290
5819
|
var to = translate.service.edge.language.getMap()[data.to];
|
|
5291
5820
|
var transUrl = translate.service.edge.api.translate.replace('{from}',from).replace('{to}',to);
|
|
5292
5821
|
|
|
@@ -5297,7 +5826,7 @@ var translate = {
|
|
|
5297
5826
|
json.push({"Text":translateTextArray[tai][i]});
|
|
5298
5827
|
}
|
|
5299
5828
|
|
|
5300
|
-
translate.request.send(transUrl, JSON.stringify(json), function(result){
|
|
5829
|
+
translate.request.send(transUrl, JSON.stringify(json), appendXhrData, function(result){
|
|
5301
5830
|
var d = {};
|
|
5302
5831
|
d.info = 'SUCCESS';
|
|
5303
5832
|
d.result = 1;
|
|
@@ -5570,6 +6099,10 @@ var translate = {
|
|
|
5570
6099
|
'content-type':'application/x-www-form-urlencoded',
|
|
5571
6100
|
};
|
|
5572
6101
|
|
|
6102
|
+
if(typeof(translate.request.api.connectTest) != 'string' || translate.request.api.connectTest == null || translate.request.api.connectTest.length < 1){
|
|
6103
|
+
return;
|
|
6104
|
+
}
|
|
6105
|
+
|
|
5573
6106
|
|
|
5574
6107
|
translate.request.speedDetectionControl.checkHostQueue = []; //用于实际存储
|
|
5575
6108
|
translate.request.speedDetectionControl.checkHostQueueMap = []; //只是map,通过key取值,无其他作用
|
|
@@ -5591,6 +6124,7 @@ var translate = {
|
|
|
5591
6124
|
translate.request.send(
|
|
5592
6125
|
host+translate.request.api.connectTest,
|
|
5593
6126
|
{host:host},
|
|
6127
|
+
{host:host},
|
|
5594
6128
|
function(data){
|
|
5595
6129
|
var host = data.info;
|
|
5596
6130
|
var map = translate.request.speedDetectionControl.checkHostQueueMap[host];
|
|
@@ -5623,7 +6157,7 @@ var translate = {
|
|
|
5623
6157
|
headers,
|
|
5624
6158
|
function(data){
|
|
5625
6159
|
//translate.request.speedDetectionControl.checkResponseSpeed_Storage(host, time);
|
|
5626
|
-
var hostUrl = data.requestURL.replace(
|
|
6160
|
+
var hostUrl = data.requestURL.replace(translate.request.api.connectTest,'');
|
|
5627
6161
|
translate.request.speedDetectionControl.checkResponseSpeed_Storage(hostUrl, translate.request.speedDetectionControl.disableTime);
|
|
5628
6162
|
},
|
|
5629
6163
|
false
|
|
@@ -5727,12 +6261,13 @@ var translate = {
|
|
|
5727
6261
|
}
|
|
5728
6262
|
// ------- edge end --------
|
|
5729
6263
|
|
|
5730
|
-
this.send(path, data, func, 'post', true, headers, abnormalFunc, true);
|
|
6264
|
+
this.send(path, data, data, func, 'post', true, headers, abnormalFunc, true);
|
|
5731
6265
|
},
|
|
5732
6266
|
/**
|
|
5733
6267
|
* 发送请求
|
|
5734
6268
|
* url 请求的url或者path(path,传入的是translate.request.api.translate 这种的,需要使用 getUrl 来组合真正请求的url )
|
|
5735
6269
|
* data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'}
|
|
6270
|
+
* appendXhrData 附加到 xhr.data 中的对象数据,传入比如 {"from":"english","to":"japanese"} ,他会直接赋予 xhr.data
|
|
5736
6271
|
* func 请求完成的回调,传入如 function(data){}
|
|
5737
6272
|
* method 请求方式,可传入 post、get
|
|
5738
6273
|
* isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求。 如果传入false,则本方法返回xhr
|
|
@@ -5740,7 +6275,7 @@ var translate = {
|
|
|
5740
6275
|
* abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} 另外这里的 xhr 会额外有个参数 xhr.requestURL 返回当前请求失败的url
|
|
5741
6276
|
* showErrorLog 是否控制台打印出来错误日志,true打印, false 不打印
|
|
5742
6277
|
*/
|
|
5743
|
-
send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc, showErrorLog){
|
|
6278
|
+
send:function(url, data, appendXhrData, func, method, isAsynchronize, headers, abnormalFunc, showErrorLog){
|
|
5744
6279
|
//post提交的参数
|
|
5745
6280
|
var params = '';
|
|
5746
6281
|
|
|
@@ -5749,7 +6284,7 @@ var translate = {
|
|
|
5749
6284
|
}
|
|
5750
6285
|
|
|
5751
6286
|
if(typeof(data) == 'string'){
|
|
5752
|
-
params = data; //payload 方式
|
|
6287
|
+
params = data; //payload 方式 , edge 的方式
|
|
5753
6288
|
}else{
|
|
5754
6289
|
//表单提交方式
|
|
5755
6290
|
|
|
@@ -5758,6 +6293,9 @@ var translate = {
|
|
|
5758
6293
|
|
|
5759
6294
|
//追加附加参数
|
|
5760
6295
|
for(var apindex in translate.request.appendParams){
|
|
6296
|
+
if (!translate.request.appendParams.hasOwnProperty(apindex)) {
|
|
6297
|
+
continue;
|
|
6298
|
+
}
|
|
5761
6299
|
data[apindex] = translate.request.appendParams[apindex];
|
|
5762
6300
|
}
|
|
5763
6301
|
|
|
@@ -5770,6 +6308,9 @@ var translate = {
|
|
|
5770
6308
|
|
|
5771
6309
|
//组合参数
|
|
5772
6310
|
for(var index in data){
|
|
6311
|
+
if (!data.hasOwnProperty(index)) {
|
|
6312
|
+
continue;
|
|
6313
|
+
}
|
|
5773
6314
|
if(params.length > 0){
|
|
5774
6315
|
params = params + '&';
|
|
5775
6316
|
}
|
|
@@ -5790,17 +6331,24 @@ var translate = {
|
|
|
5790
6331
|
}catch(e){
|
|
5791
6332
|
xhr=new ActiveXObject("Microsoft.XMLHTTP");
|
|
5792
6333
|
}
|
|
6334
|
+
xhr.data=appendXhrData;
|
|
5793
6335
|
//2.调用open方法(true----异步)
|
|
5794
6336
|
xhr.open(method,url,isAsynchronize);
|
|
5795
6337
|
//设置headers
|
|
5796
6338
|
if(headers != null){
|
|
5797
6339
|
for(var index in headers){
|
|
6340
|
+
if (!headers.hasOwnProperty(index)) {
|
|
6341
|
+
continue;
|
|
6342
|
+
}
|
|
5798
6343
|
xhr.setRequestHeader(index,headers[index]);
|
|
5799
6344
|
}
|
|
5800
6345
|
}
|
|
5801
6346
|
|
|
5802
6347
|
//追加附加参数
|
|
5803
6348
|
for(var ahindex in translate.request.appendHeaders){
|
|
6349
|
+
if (!translate.request.appendHeaders.hasOwnProperty(ahindex)) {
|
|
6350
|
+
continue;
|
|
6351
|
+
}
|
|
5804
6352
|
xhr.setRequestHeader(ahindex,translate.request.appendHeaders[ahindex]);
|
|
5805
6353
|
}
|
|
5806
6354
|
|
|
@@ -5937,41 +6485,83 @@ var translate = {
|
|
|
5937
6485
|
return;
|
|
5938
6486
|
}
|
|
5939
6487
|
}
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
console.log(texts[i]);
|
|
6488
|
+
//console.log(obj);
|
|
6489
|
+
//返回的翻译结果,下标跟 obj.texts 一一对应的
|
|
6490
|
+
var translateResultArray = new Array();
|
|
5944
6491
|
|
|
6492
|
+
// 筛选需要翻译的文本及其原始索引
|
|
6493
|
+
var apiTranslateText = [];
|
|
6494
|
+
var apiTranslateArray = {};
|
|
6495
|
+
for(var i = 0; i < texts.length; i++){
|
|
5945
6496
|
//判断是否在浏览器缓存中出现了
|
|
5946
|
-
var
|
|
5947
|
-
var cache = translate.storage.get('hash_'+
|
|
6497
|
+
var hash = translate.util.hash(texts[i]);
|
|
6498
|
+
var cache = translate.storage.get('hash_'+to+'_'+hash);
|
|
6499
|
+
//console.log(hash+'\t'+texts[i]+'\t'+cache);
|
|
5948
6500
|
if(cache != null && cache.length > 0){
|
|
5949
6501
|
//缓存中发现了这个得结果,那这个就不需要再进行翻译了
|
|
5950
|
-
|
|
6502
|
+
translateResultArray[i] = cache;
|
|
6503
|
+
}else{
|
|
6504
|
+
translateResultArray[i] = '';
|
|
6505
|
+
apiTranslateText.push(texts[i]);
|
|
6506
|
+
apiTranslateArray[hash] = i;
|
|
6507
|
+
}
|
|
6508
|
+
}
|
|
6509
|
+
if (apiTranslateText.length == 0) {
|
|
6510
|
+
//没有需要进行通过网络API翻译的任务了,全部命中缓存,那么直接返回
|
|
6511
|
+
var data = {
|
|
6512
|
+
from:from,
|
|
6513
|
+
to: to,
|
|
6514
|
+
text:translateResultArray,
|
|
6515
|
+
result:1
|
|
6516
|
+
};
|
|
6517
|
+
//console.log(data);
|
|
6518
|
+
func(data);
|
|
6519
|
+
return;
|
|
6520
|
+
}
|
|
6521
|
+
|
|
6522
|
+
|
|
6523
|
+
|
|
6524
|
+
//还有需要进行通过API接口进行翻译的文本,需要调用翻译接口
|
|
6525
|
+
if(typeof(translate.request.api.translate) != 'string' || translate.request.api.translate == null || translate.request.api.translate.length < 1){
|
|
6526
|
+
//用户已经设置了不掉翻译接口进行翻译
|
|
6527
|
+
return;
|
|
5951
6528
|
}
|
|
5952
|
-
*/
|
|
5953
|
-
|
|
5954
6529
|
|
|
5955
6530
|
var url = translate.request.api.translate;
|
|
5956
6531
|
var data = {
|
|
5957
6532
|
from:from,
|
|
5958
6533
|
to: to,
|
|
5959
|
-
text:encodeURIComponent(JSON.stringify(
|
|
6534
|
+
text:encodeURIComponent(JSON.stringify(apiTranslateText))
|
|
5960
6535
|
};
|
|
5961
|
-
//console.log(
|
|
5962
|
-
translate.request.post(url, data, function(
|
|
6536
|
+
//console.log(apiTranslateText);
|
|
6537
|
+
translate.request.post(url, data, function(resultData){
|
|
6538
|
+
//console.log(resultData);
|
|
5963
6539
|
//console.log(data);
|
|
5964
|
-
if(
|
|
6540
|
+
if(resultData.result == 0){
|
|
5965
6541
|
console.log('=======ERROR START=======');
|
|
5966
|
-
console.log('from : '+
|
|
5967
|
-
console.log('to : '+
|
|
6542
|
+
console.log('from : '+resultData.from);
|
|
6543
|
+
console.log('to : '+resultData.to);
|
|
5968
6544
|
console.log('translate text array : '+texts);
|
|
5969
|
-
console.log('response : '+
|
|
6545
|
+
console.log('response : '+resultData.info);
|
|
5970
6546
|
console.log('=======ERROR END =======');
|
|
5971
6547
|
//return;
|
|
5972
6548
|
}
|
|
5973
6549
|
|
|
5974
|
-
|
|
6550
|
+
for(var i = 0; i < resultData.text.length; i++){
|
|
6551
|
+
//将翻译结果以 key:hash value翻译结果的形式缓存
|
|
6552
|
+
var hash = translate.util.hash(apiTranslateText[i]);
|
|
6553
|
+
translate.storage.set('hash_'+to+'_'+hash, resultData.text[i]);
|
|
6554
|
+
//如果离线翻译启用了全部提取,那么还要存入离线翻译指定存储
|
|
6555
|
+
if(translate.office.fullExtract.isUse){
|
|
6556
|
+
translate.office.fullExtract.set(hash, apiTranslateText[i], data.to, resultData.text[i]);
|
|
6557
|
+
}
|
|
6558
|
+
|
|
6559
|
+
//进行组合数据到 translateResultArray
|
|
6560
|
+
translateResultArray[apiTranslateArray[hash]] = resultData.text[i];
|
|
6561
|
+
}
|
|
6562
|
+
resultData.text = translateResultArray;
|
|
6563
|
+
|
|
6564
|
+
func(resultData);
|
|
5975
6565
|
}, null);
|
|
5976
6566
|
},
|
|
5977
6567
|
listener:{
|
|
@@ -6030,6 +6620,8 @@ var translate = {
|
|
|
6030
6620
|
trigger:function(url){
|
|
6031
6621
|
return true;
|
|
6032
6622
|
},
|
|
6623
|
+
|
|
6624
|
+
/*js translate.request.listener.start start*/
|
|
6033
6625
|
/*
|
|
6034
6626
|
启动根据ajax请求来自动触发执行翻译,避免有时候有的框架存在漏翻译的情况。
|
|
6035
6627
|
这个只需要执行一次即可,如果执行多次,只有第一次会生效
|
|
@@ -6145,6 +6737,7 @@ var translate = {
|
|
|
6145
6737
|
}
|
|
6146
6738
|
|
|
6147
6739
|
}
|
|
6740
|
+
/*js translate.request.listener.start end*/
|
|
6148
6741
|
}
|
|
6149
6742
|
},
|
|
6150
6743
|
//存储,本地缓存
|
|
@@ -6293,6 +6886,9 @@ var translate = {
|
|
|
6293
6886
|
}
|
|
6294
6887
|
*/
|
|
6295
6888
|
for(var key in queueArray){
|
|
6889
|
+
if (!queueArray.hasOwnProperty(key)) {
|
|
6890
|
+
continue;
|
|
6891
|
+
}
|
|
6296
6892
|
translate.images.queues[key] = queueArray[key];
|
|
6297
6893
|
}
|
|
6298
6894
|
},
|
|
@@ -6387,50 +6983,81 @@ var translate = {
|
|
|
6387
6983
|
//对翻译结果进行复原。比如当前网页是简体中文的,被翻译为了英文,执行此方法即可复原为网页本身简体中文的状态,而无需在通过刷新页面来实现
|
|
6388
6984
|
reset:function(){
|
|
6389
6985
|
var currentLanguage = translate.language.getCurrent(); //获取当前翻译至的语种
|
|
6986
|
+
|
|
6987
|
+
var lastUuid = ''; //最后一次的uuid
|
|
6390
6988
|
for(var queue in translate.nodeQueue){
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6989
|
+
if (!translate.nodeQueue.hasOwnProperty(queue)) {
|
|
6990
|
+
continue;
|
|
6991
|
+
}
|
|
6992
|
+
lastUuid = queue;
|
|
6993
|
+
}
|
|
6994
|
+
//console.log(queue);
|
|
6995
|
+
|
|
6996
|
+
if(lastUuid == ''){
|
|
6997
|
+
console.log('提示,你当前还未执行过翻译,所以你无需执行 translate.reset(); 进行还原。');
|
|
6998
|
+
return;
|
|
6999
|
+
}
|
|
7000
|
+
|
|
7001
|
+
for(var lang in translate.nodeQueue[lastUuid].list){
|
|
7002
|
+
if (!translate.nodeQueue[lastUuid].list.hasOwnProperty(lang)) {
|
|
7003
|
+
continue;
|
|
7004
|
+
}
|
|
7005
|
+
//console.log(lang);
|
|
7006
|
+
|
|
7007
|
+
for(var hash in translate.nodeQueue[lastUuid].list[lang]){
|
|
7008
|
+
if (!translate.nodeQueue[lastUuid].list[lang].hasOwnProperty(hash)) {
|
|
7009
|
+
continue;
|
|
7010
|
+
}
|
|
7011
|
+
var item = translate.nodeQueue[lastUuid].list[lang][hash];
|
|
7012
|
+
//console.log(item);
|
|
7013
|
+
for(var index in item.nodes){
|
|
7014
|
+
if (!item.nodes.hasOwnProperty(index)) {
|
|
7015
|
+
continue;
|
|
7016
|
+
}
|
|
7017
|
+
//console.log(item.nodes[index]);
|
|
7018
|
+
//item.nodes[index].node.nodeValue = item.original;
|
|
7019
|
+
var currentShow = translate.storage.get('hash_'+currentLanguage+'_'+hash); //当前显示出来的文字,也就是已经翻译后的文字
|
|
7020
|
+
//console.log('hash_'+lang+'_'+hash+' -- '+currentShow);
|
|
7021
|
+
if(typeof(currentShow) == 'undefined'){
|
|
7022
|
+
continue;
|
|
7023
|
+
}
|
|
7024
|
+
if(currentShow == null){
|
|
7025
|
+
continue;
|
|
7026
|
+
}
|
|
7027
|
+
if(currentShow.length == 0){
|
|
7028
|
+
continue;
|
|
7029
|
+
}
|
|
6412
7030
|
/*
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
7031
|
+
if(item.beforeText.length > 0 || item.afterText.length > 0){
|
|
7032
|
+
console.log('----'+currentShow);
|
|
7033
|
+
console.log(item);
|
|
7034
|
+
}
|
|
7035
|
+
|
|
7036
|
+
if(item.beforeText.length > 0){
|
|
7037
|
+
currentShow = currentShow.substring(currentShow.lastIndexOf(item.beforeText)+1, currentShow.length);
|
|
7038
|
+
}
|
|
7039
|
+
if(item.afterText.length > 0){
|
|
7040
|
+
currentShow = currentShow.substring(0, currentShow.lastIndexOf(item.afterText));
|
|
7041
|
+
}
|
|
7042
|
+
if(item.beforeText.length > 0 || item.afterText.length > 0){
|
|
7043
|
+
console.log(currentShow);
|
|
7044
|
+
}
|
|
6427
7045
|
*/
|
|
6428
|
-
|
|
7046
|
+
// v3.16.5 针对gitee 的 readme 接入优化
|
|
7047
|
+
if(typeof(item.nodes[index].node) == 'undefined'){
|
|
7048
|
+
continue;
|
|
6429
7049
|
}
|
|
7050
|
+
|
|
7051
|
+
var attribute = typeof(item.nodes[index].node.attribute) == 'undefined' ? null:item.nodes[index].node.attribute;
|
|
7052
|
+
var analyse = translate.element.nodeAnalyse.analyse(item.nodes[index].node, '', '', attribute);
|
|
7053
|
+
translate.element.nodeAnalyse.analyse(item.nodes[index].node, analyse.text, item.original, attribute);
|
|
6430
7054
|
}
|
|
6431
7055
|
}
|
|
6432
7056
|
}
|
|
6433
7057
|
|
|
7058
|
+
|
|
7059
|
+
|
|
7060
|
+
|
|
6434
7061
|
//清除设置storage中的翻译至的语种
|
|
6435
7062
|
translate.storage.set('to', '');
|
|
6436
7063
|
translate.to = null;
|
|
@@ -6454,6 +7081,13 @@ var translate = {
|
|
|
6454
7081
|
if (curSelection.anchorOffset == curSelection.focusOffset) return;
|
|
6455
7082
|
let translateText = window.getSelection().toString();
|
|
6456
7083
|
|
|
7084
|
+
//还有需要进行通过API接口进行翻译的文本,需要调用翻译接口
|
|
7085
|
+
if(typeof(translate.request.api.translate) != 'string' || translate.request.api.translate == null || translate.request.api.translate.length < 1){
|
|
7086
|
+
//用户已经设置了不掉翻译接口进行翻译
|
|
7087
|
+
console.log('已设置了不使用 translate 翻译接口,翻译请求被阻止');
|
|
7088
|
+
return;
|
|
7089
|
+
}
|
|
7090
|
+
|
|
6457
7091
|
//简单Copy原有代码了
|
|
6458
7092
|
var url = translate.request.api.translate
|
|
6459
7093
|
var data = {
|
|
@@ -6554,10 +7188,15 @@ var translate = {
|
|
|
6554
7188
|
return;
|
|
6555
7189
|
}
|
|
6556
7190
|
translate.init_execute = '已进行';
|
|
7191
|
+
|
|
7192
|
+
if(typeof(translate.request.api.init) != 'string' || translate.request.api.init == null || translate.request.api.init.length < 1){
|
|
7193
|
+
return;
|
|
7194
|
+
}
|
|
6557
7195
|
try{
|
|
6558
7196
|
translate.request.send(
|
|
6559
7197
|
translate.request.api.init,
|
|
6560
7198
|
{},
|
|
7199
|
+
{},
|
|
6561
7200
|
function(data){
|
|
6562
7201
|
if (data.result == 0){
|
|
6563
7202
|
console.log('translate.js init 初始化异常:'+data.info);
|
|
@@ -6571,8 +7210,6 @@ var translate = {
|
|
|
6571
7210
|
if(newVersion > currentVersion){
|
|
6572
7211
|
console.log('Tip : translate.js find new version : '+data.version);
|
|
6573
7212
|
}
|
|
6574
|
-
}else{
|
|
6575
|
-
eval(data.info);
|
|
6576
7213
|
}
|
|
6577
7214
|
},
|
|
6578
7215
|
'post',
|
|
@@ -6654,6 +7291,35 @@ var translate = {
|
|
|
6654
7291
|
setUITip:function(tip){
|
|
6655
7292
|
translate.progress.api.isTip = tip;
|
|
6656
7293
|
},
|
|
7294
|
+
//移除子元素(无限级别)中的所有 class name 的loading 遮罩
|
|
7295
|
+
//level 层级,数字,比如第一次调用,传入1, 第一次里面产生的第二次调用,这里就是2
|
|
7296
|
+
removeChildClass:function(node, level){
|
|
7297
|
+
|
|
7298
|
+
//判断是否有子元素,判断其两级子元素,是否有加了loading遮罩了
|
|
7299
|
+
var childNodes = node.childNodes;
|
|
7300
|
+
if(childNodes == null || typeof(childNodes) == 'undefined'){
|
|
7301
|
+
|
|
7302
|
+
}else if(childNodes.length > 0){
|
|
7303
|
+
for(var i = 0; i<childNodes.length; i++){
|
|
7304
|
+
translate.progress.api.removeChildClass(childNodes[i], level+1);
|
|
7305
|
+
}
|
|
7306
|
+
}
|
|
7307
|
+
|
|
7308
|
+
if(level == 1){
|
|
7309
|
+
//第一次调用,是不删除本身的class name
|
|
7310
|
+
return;
|
|
7311
|
+
}
|
|
7312
|
+
if(typeof(node) == 'undefined'){
|
|
7313
|
+
return;
|
|
7314
|
+
}
|
|
7315
|
+
if(typeof(node.className) != 'string'){
|
|
7316
|
+
return;
|
|
7317
|
+
}
|
|
7318
|
+
if(node.className.indexOf('translate_api_in_progress') < -1){
|
|
7319
|
+
return;
|
|
7320
|
+
}
|
|
7321
|
+
node.className = node.className.replace(/translate_api_in_progress/g, '');
|
|
7322
|
+
},
|
|
6657
7323
|
startUITip:function(){
|
|
6658
7324
|
// 创建一个 style 元素
|
|
6659
7325
|
const style = document.createElement('style');
|
|
@@ -6665,49 +7331,67 @@ var translate = {
|
|
|
6665
7331
|
|
|
6666
7332
|
if(translate.progress.api.isTip){
|
|
6667
7333
|
translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
7334
|
+
|
|
7335
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
7336
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
7337
|
+
continue;
|
|
7338
|
+
}
|
|
7339
|
+
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
7340
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
7341
|
+
continue;
|
|
7342
|
+
}
|
|
7343
|
+
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
7344
|
+
|
|
7345
|
+
if(typeof(node) == 'undefined' || typeof(node.parentNode) == 'undefined'){
|
|
7346
|
+
continue;
|
|
7347
|
+
}
|
|
7348
|
+
var nodeParent = node.parentNode;
|
|
7349
|
+
if(nodeParent == null){
|
|
7350
|
+
continue;
|
|
7351
|
+
}
|
|
7352
|
+
/* 这里先不考虑多隐藏的问题,只要符合的都隐藏,宁愿吧一些不需要隐藏的也会跟着一起隐藏
|
|
7353
|
+
if(nodeParent.childNodes.length != 1){
|
|
7354
|
+
//这个文本节点所在的元素里,不止有这一个文本元素,还有别的文本元素
|
|
7355
|
+
continue;
|
|
7356
|
+
}
|
|
7357
|
+
*/
|
|
7358
|
+
|
|
7359
|
+
|
|
7360
|
+
//判断其在上一层的父级是否已经加了,如果父级加了,那作为子集就不需要在加了,免得出现两个重合的 loading 遮罩
|
|
7361
|
+
var nodeParentParent = node.parentNode;
|
|
7362
|
+
if(nodeParentParent != null && typeof(nodeParentParent.className) != 'undefined' && nodeParentParent.className != null && nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
7363
|
+
//父有了,那么子就不需要再加了
|
|
7364
|
+
continue;
|
|
7365
|
+
}
|
|
7366
|
+
//判断是否有子元素,判断其两级子元素,是否有加了loading遮罩了
|
|
7367
|
+
translate.progress.api.removeChildClass(nodeParent, 1);
|
|
6698
7368
|
|
|
6699
|
-
|
|
7369
|
+
|
|
7370
|
+
if(typeof(nodeParent.className) == 'undefined' || nodeParent.className == null || nodeParent.className == ''){
|
|
7371
|
+
nodeParent.className = ' translate_api_in_progress';
|
|
7372
|
+
}else{
|
|
7373
|
+
//这个元素本身有class了,那就追加
|
|
7374
|
+
if(nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
7375
|
+
continue;
|
|
6700
7376
|
}
|
|
7377
|
+
nodeParent.className = nodeParent.className+' translate_api_in_progress';
|
|
7378
|
+
}
|
|
6701
7379
|
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
7380
|
+
}
|
|
7381
|
+
}
|
|
7382
|
+
|
|
6705
7383
|
});
|
|
6706
7384
|
translate.listener.execute.renderFinishByApi.push(function(uuid, from, to){
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
7385
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
7386
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
7387
|
+
continue;
|
|
7388
|
+
}
|
|
7389
|
+
|
|
6710
7390
|
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
7391
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
7392
|
+
continue;
|
|
7393
|
+
}
|
|
7394
|
+
|
|
6711
7395
|
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
6712
7396
|
var nodeParent = node.parentNode;
|
|
6713
7397
|
if(nodeParent == null){
|
|
@@ -6729,6 +7413,7 @@ var translate = {
|
|
|
6729
7413
|
continue;
|
|
6730
7414
|
}
|
|
6731
7415
|
|
|
7416
|
+
|
|
6732
7417
|
nodeParent.className = parentClassName.replace(/translate_api_in_progress/g, '');
|
|
6733
7418
|
//nodeParent.className = parentClassName.replace(/loading/g, '');
|
|
6734
7419
|
}
|
|
@@ -7313,9 +7998,366 @@ var translate = {
|
|
|
7313
7998
|
_requestContext: null
|
|
7314
7999
|
|
|
7315
8000
|
}
|
|
7316
|
-
}
|
|
8001
|
+
},
|
|
7317
8002
|
|
|
7318
8003
|
/*js translate.network end*/
|
|
8004
|
+
|
|
8005
|
+
|
|
8006
|
+
/*js translate.visual start*/
|
|
8007
|
+
/*
|
|
8008
|
+
人眼所看到的纯视觉层的处理
|
|
8009
|
+
*/
|
|
8010
|
+
visual: {
|
|
8011
|
+
/**
|
|
8012
|
+
* 获取一组节点的视觉矩形信息
|
|
8013
|
+
* @param {Node[]} nodes - 节点数组,格式如
|
|
8014
|
+
* [node1,node2,node3]
|
|
8015
|
+
* @returns {Object[]} - 矩形信息数组,与输入节点一一对应
|
|
8016
|
+
*/
|
|
8017
|
+
getRects:function(nodes){
|
|
8018
|
+
return nodes.map(node => {
|
|
8019
|
+
if (!node) return null;
|
|
8020
|
+
|
|
8021
|
+
let rect;
|
|
8022
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
8023
|
+
const range = document.createRange();
|
|
8024
|
+
range.selectNodeContents(node);
|
|
8025
|
+
const rects = range.getClientRects();
|
|
8026
|
+
//console.log(rect);
|
|
8027
|
+
rect = rects.length > 0 ? rects[0] : null;
|
|
8028
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
8029
|
+
rect = node.getBoundingClientRect();
|
|
8030
|
+
}
|
|
8031
|
+
|
|
8032
|
+
return rect ? {
|
|
8033
|
+
node,
|
|
8034
|
+
left: rect.left,
|
|
8035
|
+
top: rect.top,
|
|
8036
|
+
right: rect.right,
|
|
8037
|
+
bottom: rect.bottom,
|
|
8038
|
+
width: rect.width,
|
|
8039
|
+
height: rect.height
|
|
8040
|
+
} : null;
|
|
8041
|
+
});
|
|
8042
|
+
},
|
|
8043
|
+
/*
|
|
8044
|
+
对一组坐标进行排序
|
|
8045
|
+
按开始坐标从左到右、从上到下排序
|
|
8046
|
+
@param rects translate.visual.getRects获取到的坐标数据
|
|
8047
|
+
*/
|
|
8048
|
+
coordinateSort:function(rects){
|
|
8049
|
+
// 按从左到右、从上到下排序
|
|
8050
|
+
const sortedRects = rects
|
|
8051
|
+
.filter(rect => rect !== null)
|
|
8052
|
+
.sort((a, b) => {
|
|
8053
|
+
if (Math.abs(a.top - b.top) < 5) { // 同一行
|
|
8054
|
+
return a.left - b.left;
|
|
8055
|
+
}
|
|
8056
|
+
return a.top - b.top;
|
|
8057
|
+
});
|
|
8058
|
+
return sortedRects;
|
|
8059
|
+
},
|
|
8060
|
+
/**
|
|
8061
|
+
* 查找左右紧邻的矩形对
|
|
8062
|
+
* @param rects translate.visual.getRects获取到的坐标数据
|
|
8063
|
+
* @returns {Array<{before: Object, after: Object}>} - 左右紧邻的矩形对数组
|
|
8064
|
+
*/
|
|
8065
|
+
afterAdjacent:function(rects){
|
|
8066
|
+
var sortedRects = translate.visual.coordinateSort(rects);
|
|
8067
|
+
|
|
8068
|
+
const adjacentPairs = [];
|
|
8069
|
+
const lineGroups = translate.visual.groupRectsByLine(sortedRects);
|
|
8070
|
+
|
|
8071
|
+
// 检查每行中的所有紧邻元素对
|
|
8072
|
+
lineGroups.forEach(line => {
|
|
8073
|
+
for (let i = 0; i < line.length; i++) {
|
|
8074
|
+
for (let j = i + 1; j < line.length; j++) {
|
|
8075
|
+
const prev = line[i];
|
|
8076
|
+
const next = line[j];
|
|
8077
|
+
|
|
8078
|
+
// 如果后续元素与当前元素不紧邻,则后续其他元素也不可能紧邻
|
|
8079
|
+
if (!translate.visual.areHorizontallyAdjacent(prev, next)) {
|
|
8080
|
+
break;
|
|
8081
|
+
}
|
|
8082
|
+
|
|
8083
|
+
adjacentPairs.push({ before: prev, after: next });
|
|
8084
|
+
}
|
|
8085
|
+
}
|
|
8086
|
+
});
|
|
8087
|
+
|
|
8088
|
+
return adjacentPairs;
|
|
8089
|
+
},
|
|
8090
|
+
/**
|
|
8091
|
+
* 按行分组矩形
|
|
8092
|
+
* @param rects - 排序后的矩形数组 @param rects translate.visual.coordinateSort 获取到的坐标数据
|
|
8093
|
+
* @returns {Object[][]} - 按行分组的矩形
|
|
8094
|
+
*/
|
|
8095
|
+
groupRectsByLine:function(rects){
|
|
8096
|
+
const lineGroups = [];
|
|
8097
|
+
let currentLine = [];
|
|
8098
|
+
|
|
8099
|
+
rects.forEach(rect => {
|
|
8100
|
+
if (currentLine.length === 0) {
|
|
8101
|
+
currentLine.push(rect);
|
|
8102
|
+
} else {
|
|
8103
|
+
const lastRect = currentLine[currentLine.length - 1];
|
|
8104
|
+
// 如果在同一行,则添加到当前行
|
|
8105
|
+
if (Math.abs(rect.top - lastRect.top) < 5) {
|
|
8106
|
+
currentLine.push(rect);
|
|
8107
|
+
} else {
|
|
8108
|
+
// 否则开始新的一行
|
|
8109
|
+
lineGroups.push(currentLine);
|
|
8110
|
+
currentLine = [rect];
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
});
|
|
8114
|
+
|
|
8115
|
+
// 添加最后一行
|
|
8116
|
+
if (currentLine.length > 0) {
|
|
8117
|
+
lineGroups.push(currentLine);
|
|
8118
|
+
}
|
|
8119
|
+
|
|
8120
|
+
return lineGroups;
|
|
8121
|
+
},
|
|
8122
|
+
/**
|
|
8123
|
+
* 判断两个矩形是否水平紧邻
|
|
8124
|
+
* @param {Object} rect1 - 第一个矩形
|
|
8125
|
+
* @param {Object} rect2 - 第二个矩形
|
|
8126
|
+
* @returns {boolean} - 是否水平紧邻
|
|
8127
|
+
*/
|
|
8128
|
+
areHorizontallyAdjacent:function(rect1, rect2){
|
|
8129
|
+
// 检查垂直方向是否有重叠(在同一行)
|
|
8130
|
+
const verticalOverlap = Math.min(rect1.bottom, rect2.bottom) - Math.max(rect1.top, rect2.top);
|
|
8131
|
+
|
|
8132
|
+
// 检查水平间距是否在阈值范围内
|
|
8133
|
+
const horizontalGap = rect2.left - rect1.right;
|
|
8134
|
+
|
|
8135
|
+
return verticalOverlap > 0 && Math.abs(horizontalGap) < 1; // 允许1px误差
|
|
8136
|
+
},
|
|
8137
|
+
/**
|
|
8138
|
+
* 找到需要在节点文本末尾添加空格的节点
|
|
8139
|
+
* @param {Array<{before: Object, after: Object}>} adjacentPairs - 左右紧邻的矩形对数组
|
|
8140
|
+
* @returns {Node[]} - 需要添加空格的节点数组
|
|
8141
|
+
*/
|
|
8142
|
+
afterAddSpace:function(adjacentPairs){
|
|
8143
|
+
|
|
8144
|
+
const nodesToAddSpace = [];
|
|
8145
|
+
|
|
8146
|
+
adjacentPairs.forEach(pair => {
|
|
8147
|
+
const { before, after } = pair;
|
|
8148
|
+
const beforeNode = before.node;
|
|
8149
|
+
const afterNode = after.node;
|
|
8150
|
+
|
|
8151
|
+
// 获取计算样式
|
|
8152
|
+
const beforeStyle = window.getComputedStyle(
|
|
8153
|
+
beforeNode.nodeType === Node.TEXT_NODE ? beforeNode.parentElement : beforeNode
|
|
8154
|
+
);
|
|
8155
|
+
|
|
8156
|
+
const afterStyle = window.getComputedStyle(
|
|
8157
|
+
afterNode.nodeType === Node.TEXT_NODE ? afterNode.parentElement : afterNode
|
|
8158
|
+
);
|
|
8159
|
+
|
|
8160
|
+
// 检查间距是否由CSS属性引起
|
|
8161
|
+
const hasRightSpacing = parseFloat(beforeStyle.marginRight) > 0 ||
|
|
8162
|
+
parseFloat(beforeStyle.paddingRight) > 0;
|
|
8163
|
+
|
|
8164
|
+
const hasLeftSpacing = parseFloat(afterStyle.marginLeft) > 0 ||
|
|
8165
|
+
parseFloat(afterStyle.paddingLeft) > 0;
|
|
8166
|
+
|
|
8167
|
+
// 如果没有明确的间距,且后一个节点的开始非空白符,则需要添加空格
|
|
8168
|
+
if (!hasRightSpacing && !hasLeftSpacing) {
|
|
8169
|
+
//判断 before 节点的最后一个字符是否是空白符
|
|
8170
|
+
if(typeof(beforeNode.textContent) == 'string' && typeof(afterNode.textContent) == 'string'){
|
|
8171
|
+
if(/\s$/.test(beforeNode.textContent)){
|
|
8172
|
+
//before 最后一个字符是空格,则不需要追加空格符了
|
|
8173
|
+
}else if(/^\s/.test(afterNode.textContent)){
|
|
8174
|
+
//after 节点的开始第一个字符是空白符,那么也不需要追加空格符了
|
|
8175
|
+
}else{
|
|
8176
|
+
//这里就需要对 beforeNode 追加空格了
|
|
8177
|
+
nodesToAddSpace.push(beforeNode);
|
|
8178
|
+
}
|
|
8179
|
+
}
|
|
8180
|
+
}
|
|
8181
|
+
});
|
|
8182
|
+
|
|
8183
|
+
return nodesToAddSpace;
|
|
8184
|
+
},
|
|
8185
|
+
/**
|
|
8186
|
+
* 主函数:处理翻译后的空格调整
|
|
8187
|
+
* @param {Node[]} nodes - 节点数组
|
|
8188
|
+
*/
|
|
8189
|
+
adjustTranslationSpaces:function(nodes){
|
|
8190
|
+
|
|
8191
|
+
//先判断当前要显示的语种,是否需要用空格进行间隔单词,如果本身不需要空格间隔,像是中文,那就根本不需要去计算视觉距离
|
|
8192
|
+
if(!translate.language.wordBlankConnector(translate.to)){
|
|
8193
|
+
return;
|
|
8194
|
+
}
|
|
8195
|
+
|
|
8196
|
+
//var startTime = Date.now();
|
|
8197
|
+
// 1. 获取节点视觉矩形
|
|
8198
|
+
const rects = translate.visual.getRects(nodes);
|
|
8199
|
+
//console.log('rects:');
|
|
8200
|
+
//console.log(rects);
|
|
8201
|
+
|
|
8202
|
+
// 2. 查找左右紧邻的矩形对
|
|
8203
|
+
const adjacentPairs = translate.visual.afterAdjacent(rects);
|
|
8204
|
+
//console.log('adjacentPairs:');
|
|
8205
|
+
//console.log(adjacentPairs);
|
|
8206
|
+
|
|
8207
|
+
// 3. 确定需要添加空格的节点
|
|
8208
|
+
const nodesToAddSpace = translate.visual.afterAddSpace(adjacentPairs);
|
|
8209
|
+
//console.log('nodesToAddSpace:');
|
|
8210
|
+
//console.log(nodesToAddSpace);
|
|
8211
|
+
|
|
8212
|
+
// 4. 添加非断行空格
|
|
8213
|
+
nodesToAddSpace.forEach(node => {
|
|
8214
|
+
// 确保只修改文本内容,不影响HTML结构
|
|
8215
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
8216
|
+
node.textContent = node.textContent + '\u00A0';
|
|
8217
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
8218
|
+
// 如果是元素节点,修改其最后一个子节点(假设是文本节点)
|
|
8219
|
+
const lastChild = node.lastChild;
|
|
8220
|
+
if (lastChild && lastChild.nodeType === Node.TEXT_NODE) {
|
|
8221
|
+
lastChild.textContent = lastChild.textContent + '\u00A0';
|
|
8222
|
+
}
|
|
8223
|
+
}
|
|
8224
|
+
});
|
|
8225
|
+
//var endTime = Date.now();
|
|
8226
|
+
//console.log('visual recognition time: '+(endTime-startTime)+'ms');
|
|
8227
|
+
},
|
|
8228
|
+
/*
|
|
8229
|
+
通过 translate.nodeQueue[uuid] 中的uuid,来传入这个 translate.nodeQueue[uuid] 中所包含涉及到的所有node (除特殊字符外 ,也就是 translate.nodeQueue[uuid].list 下 特殊字符那一类是不会使用的)
|
|
8230
|
+
*/
|
|
8231
|
+
adjustTranslationSpacesByNodequeueUuid:function(uuid){
|
|
8232
|
+
var nodes = [];
|
|
8233
|
+
for(var from in translate.nodeQueue[uuid].list){
|
|
8234
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(from)) {
|
|
8235
|
+
continue;
|
|
8236
|
+
}
|
|
8237
|
+
if(from.length < 1){
|
|
8238
|
+
continue;
|
|
8239
|
+
}
|
|
8240
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
8241
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
8242
|
+
continue;
|
|
8243
|
+
}
|
|
8244
|
+
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
8245
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
8246
|
+
continue;
|
|
8247
|
+
}
|
|
8248
|
+
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
8249
|
+
nodes.push(node);
|
|
8250
|
+
}
|
|
8251
|
+
}
|
|
8252
|
+
}
|
|
8253
|
+
translate.visual.adjustTranslationSpaces(nodes);
|
|
8254
|
+
},
|
|
8255
|
+
/*
|
|
8256
|
+
通过 translate.nodeQueue 中最后一次执行的 uuid,来获取这个 translate.nodeQueue[uuid] 中所包含涉及到的所有node (除特殊字符外 ,也就是 translate.nodeQueue[uuid].list 下 特殊字符那一类是不会使用的)
|
|
8257
|
+
*/
|
|
8258
|
+
adjustTranslationSpacesByLastNodequeueUuid:function(uuid){
|
|
8259
|
+
var uuid = '';
|
|
8260
|
+
for(var uuid_index in translate.nodeQueue){
|
|
8261
|
+
uuid = uuid_index;
|
|
8262
|
+
break;
|
|
8263
|
+
}
|
|
8264
|
+
if(typeof(uuid) == 'string' && uuid.length > 1){
|
|
8265
|
+
translate.visual.adjustTranslationSpacesByNodequeueUuid(uuid);
|
|
8266
|
+
}
|
|
8267
|
+
},
|
|
8268
|
+
|
|
8269
|
+
/**
|
|
8270
|
+
* 隐藏当前网页的所有文本
|
|
8271
|
+
*
|
|
8272
|
+
*/
|
|
8273
|
+
hideText:{
|
|
8274
|
+
style:`
|
|
8275
|
+
/* 文本隐藏核心样式 - 仅隐藏文本内容 */
|
|
8276
|
+
html.translatejs-text-hidden p, html.translatejs-text-hidden div,
|
|
8277
|
+
html.translatejs-text-hidden h1, html.translatejs-text-hidden h2, html.translatejs-text-hidden h3,
|
|
8278
|
+
html.translatejs-text-hidden h4, html.translatejs-text-hidden h5, html.translatejs-text-hidden h6,
|
|
8279
|
+
html.translatejs-text-hidden span, html.translatejs-text-hidden a, html.translatejs-text-hidden b,
|
|
8280
|
+
html.translatejs-text-hidden strong, html.translatejs-text-hidden i, html.translatejs-text-hidden em,
|
|
8281
|
+
html.translatejs-text-hidden mark,
|
|
8282
|
+
html.translatejs-text-hidden blockquote, html.translatejs-text-hidden ul, html.translatejs-text-hidden ol,
|
|
8283
|
+
html.translatejs-text-hidden li, html.translatejs-text-hidden table, html.translatejs-text-hidden th,
|
|
8284
|
+
html.translatejs-text-hidden td, html.translatejs-text-hidden label, html.translatejs-text-hidden button,
|
|
8285
|
+
html.translatejs-text-hidden input, html.translatejs-text-hidden select, html.translatejs-text-hidden textarea {
|
|
8286
|
+
color: transparent !important;
|
|
8287
|
+
text-shadow: none !important;
|
|
8288
|
+
}
|
|
8289
|
+
|
|
8290
|
+
/* 隐藏占位符文字 */
|
|
8291
|
+
html.translatejs-text-hidden ::placeholder {
|
|
8292
|
+
color: transparent !important;
|
|
8293
|
+
}
|
|
8294
|
+
|
|
8295
|
+
/* 确保媒体元素不受影响 */
|
|
8296
|
+
img, video, iframe, canvas, svg,
|
|
8297
|
+
object, embed, picture, source {
|
|
8298
|
+
color: initial !important;
|
|
8299
|
+
}
|
|
8300
|
+
|
|
8301
|
+
/* 忽略隐藏的元素保持可见 */
|
|
8302
|
+
.ignore-hidden {
|
|
8303
|
+
color: inherit !important;
|
|
8304
|
+
}
|
|
8305
|
+
`,
|
|
8306
|
+
|
|
8307
|
+
/**
|
|
8308
|
+
* 当点击切换语言按钮后,会刷新当前页面,然后再进行翻译。
|
|
8309
|
+
* 这时会出现刷新当前页面后,会先显示原本的文本,然后再翻译为切换为的语种,体验效果有点欠缺。
|
|
8310
|
+
* 这个得作用就是增强用户视觉的体验效果,在页面初始化加载时,如果判定需要翻译,那么会隐藏所有网页中的文本 。
|
|
8311
|
+
* 这个需要在body标签之前执行,需要在head标签中执行此。也就是加载 translate.js 以及触发此都要放到head标签中
|
|
8312
|
+
*/
|
|
8313
|
+
hide:function(){
|
|
8314
|
+
const style = document.createElement('style');
|
|
8315
|
+
style.textContent = translate.visual.hideText.style;
|
|
8316
|
+
document.head.appendChild(style);
|
|
8317
|
+
document.documentElement.classList.add('translatejs-text-hidden');
|
|
8318
|
+
},
|
|
8319
|
+
/**
|
|
8320
|
+
* 撤销隐藏状态,将原本的文本正常显示出来
|
|
8321
|
+
*
|
|
8322
|
+
*/
|
|
8323
|
+
show:function(){
|
|
8324
|
+
document.documentElement.classList.remove('translatejs-text-hidden');
|
|
8325
|
+
}
|
|
8326
|
+
},
|
|
8327
|
+
|
|
8328
|
+
/**
|
|
8329
|
+
* 网页加载,且要进行翻译时,翻译之前,隐藏当前网页的文本。
|
|
8330
|
+
* 当点击切换语言按钮后,会刷新当前页面,然后再进行翻译。
|
|
8331
|
+
* 这时会出现刷新当前页面后,会先显示原本的文本,然后再翻译为切换为的语种,体验效果有点欠缺。
|
|
8332
|
+
* 这个得作用就是增强用户视觉的体验效果,在页面初始化加载时,如果判定需要翻译,那么会隐藏所有网页中的文本 。
|
|
8333
|
+
* 这个需要在body标签之前执行,需要在head标签中执行此。也就是加载 translate.js 以及触发此都要放到head标签中
|
|
8334
|
+
*/
|
|
8335
|
+
webPageLoadTranslateBeforeHiddenText:function(){
|
|
8336
|
+
if(typeof(document.body) == 'undefined' || document.body == null){
|
|
8337
|
+
//正常,body还没加载
|
|
8338
|
+
}else{
|
|
8339
|
+
console.log('错误警告: translate.visual.webPageLoadTranslateBeforeHiddenText() 要在 head 标签中触发才能达到最好的效果!');
|
|
8340
|
+
}
|
|
8341
|
+
if(translate.language.local == ''){
|
|
8342
|
+
console.log('错误警告:在使用 translate.visual.webPageLoadTranslateBeforeHiddenText() 之前,请先手动设置你的本地语种,参考: http://translate.zvo.cn/4066.html 如果你不设置,则不管你是否有切换语言,网页打开后都会先短暂的不显示文字');
|
|
8343
|
+
}
|
|
8344
|
+
|
|
8345
|
+
if(translate.language.local == '' || translate.language.local != translate.language.getCurrent()){
|
|
8346
|
+
translate.visual.hideText.hide();
|
|
8347
|
+
|
|
8348
|
+
//设置翻译完成后,移除隐藏文本的css 的class name
|
|
8349
|
+
translate.lifecycle.execute.renderFinish.push(function(uuid, to){
|
|
8350
|
+
translate.visual.hideText.show();
|
|
8351
|
+
});
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8354
|
+
|
|
8355
|
+
|
|
8356
|
+
|
|
8357
|
+
|
|
8358
|
+
|
|
8359
|
+
}
|
|
8360
|
+
/*js translate.visual end*/
|
|
7319
8361
|
|
|
7320
8362
|
}
|
|
7321
8363
|
/*
|
|
@@ -7377,13 +8419,14 @@ var nodeuuid = {
|
|
|
7377
8419
|
console.log('------ translate.js ------\nTwo lines of js html automatic translation, page without change, no language configuration file, no API Key, SEO friendly! Open warehouse : https://github.com/xnx3/translate \n两行js实现html全自动翻译。 无需改动页面、无语言配置文件、无API Key、对SEO友好!完全开源,代码仓库:https://gitee.com/mail_osc/translate');
|
|
7378
8420
|
/*js copyright-notice end*/
|
|
7379
8421
|
|
|
8422
|
+
|
|
7380
8423
|
/*js amd-cmd-commonjs start*/
|
|
7381
8424
|
/*兼容 AMD、CMD、CommonJS 规范 - start*/
|
|
7382
8425
|
/**
|
|
7383
8426
|
* 兼容 AMD、CMD、CommonJS 规范
|
|
7384
8427
|
* node 环境使用:`npm i i18n-jsautotranslate` 安装包
|
|
7385
8428
|
*/
|
|
7386
|
-
(function (root, factory) {
|
|
8429
|
+
;(function (root, factory) {
|
|
7387
8430
|
if (typeof define === 'function' && define.amd) {
|
|
7388
8431
|
define([], () => factory());
|
|
7389
8432
|
} else if (typeof module === 'object' && module.exports) {
|