i18n-jsautotranslate 3.16.0 → 3.17.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 +13 -9
- package/index.js +735 -108
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* **[翻译时忽略指定的id](http://translate.zvo.cn/4062.html)**,翻译时追加上自己想忽略不进行翻译的id的值,凡是在这里面的,都不进行翻译,也就是当前元素以及其子元素都不会被翻译。
|
|
50
50
|
* **[翻译时忽略指定的class属性](http://translate.zvo.cn/4061.html)**,翻译时追加上自己想忽略不进行翻译的class标签,凡是在这里面的,都不进行翻译,也就是当前元素以及其子元素都不会被翻译。
|
|
51
51
|
* **[翻译时忽略指定的tag标签](http://translate.zvo.cn/4060.html)**,翻译时追加上自己想忽略不进行翻译的tag标签,凡是在这里面的,都不进行翻译,也就是当前元素以及其子元素都不会被翻译。
|
|
52
|
-
* **[翻译时忽略指定的文字不翻译](http://translate.zvo.cn/283381.html)
|
|
52
|
+
* **[翻译时忽略指定的文字不翻译](http://translate.zvo.cn/283381.html)**,翻译时追加上自己想忽略不进行翻译的文字(支持配置字符串和正则表达式),凡是在这里面的,都不进行翻译。
|
|
53
53
|
* **[对网页中图片进行翻译](http://translate.zvo.cn/4055.html)**,在进行翻译时,对其中的图片也会一起进行翻译。
|
|
54
54
|
* **[鼠标划词翻译](http://translate.zvo.cn/4072.html)**,鼠标在网页中选中一段文字,会自动出现对应翻译后的文本
|
|
55
55
|
* **[获取当前显示的是什么语种](http://translate.zvo.cn/4074.html)**,如果用户切换为英语进行浏览,那么这个方法将返回翻译的目标语种。
|
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
* **[本地语种也进行强制翻译](http://translate.zvo.cn/289574.html)**,切换为中文时,即使本地语种设置的是中文,网页中只要不是中文的元素,都会被翻译为要显示的语种
|
|
70
70
|
* **[自定义通过翻译API进行时的监听事件](http://translate.zvo.cn/379207.html)**,当通过翻译API进行文本翻译时的整个过程进行监听,做一些自定义处理,比如翻译API请求前要做些什么、请求翻译API完成并在DOM渲染完毕后触发些什么。
|
|
71
71
|
* **[启用翻译中的遮罩层](http://translate.zvo.cn/407105.html)**,在进行通过翻译API进行翻译时,相关元素上面显示一层加载中的动画效果,让用户知道这段文本正在进行处理中
|
|
72
|
+
* **[对JS对象及代码进行翻译](http://translate.zvo.cn/452991.html)**,可对JavaScript 对象、以及 JavaScript 代码进行翻译。
|
|
73
|
+
* **[网络请求自定义附加参数](http://translate.zvo.cn/471711.html)**,追加上一些自定义的参数传递到后端翻译服务。主要用于定制扩展使用。
|
|
74
|
+
* **[网络请求数据拦截并翻译](http://translate.zvo.cn/479724.html)**,当用户触发网络请求时,它可以针对ajax、fetch请求中的某个参数,进行拦截,并进行翻译,将翻译后的文本赋予这个参数,然后再放开请求。
|
|
75
|
+
* **[翻译排队执行](http://translate.zvo.cn/479742.html)**,避免接入时的异常设置,导致非常频繁的去执行扫描及翻译的情况。
|
|
72
76
|
|
|
73
77
|
# 在线体验
|
|
74
78
|
http://res.zvo.cn/translate/demo.html
|
|
@@ -89,11 +93,11 @@ http://res.zvo.cn/translate/demo.html
|
|
|
89
93
|
在网页最末尾, ````</html>```` 之前,加入以下代码,一般在页面的最底部就出现了选择语言的 select 切换标签。 其实就这么简单:
|
|
90
94
|
|
|
91
95
|
````
|
|
92
|
-
<script src="https://cdn.staticfile.net/translate.js/3.
|
|
96
|
+
<script src="https://cdn.staticfile.net/translate.js/3.16.0/translate.js"></script>
|
|
93
97
|
<script>
|
|
94
|
-
translate.language.setLocal('chinese_simplified'); //设置本地语种(当前网页的语种)。如果不设置,默认自动识别当前网页显示文字的语种。 可填写如 'english'、'chinese_simplified'
|
|
95
|
-
translate.service.use('client.edge');
|
|
96
|
-
translate.execute()
|
|
98
|
+
translate.language.setLocal('chinese_simplified'); //设置本地语种(当前网页的语种)。如果不设置,默认自动识别当前网页显示文字的语种。 可填写如 'english'、'chinese_simplified' 等
|
|
99
|
+
translate.service.use('client.edge'); //设置机器翻译服务通道,相关说明参考 http://translate.zvo.cn/43086.html
|
|
100
|
+
translate.execute();//完成翻译初始化,进行翻译
|
|
97
101
|
</script>
|
|
98
102
|
````
|
|
99
103
|
|
|
@@ -105,7 +109,7 @@ translate.execute();//进行翻译
|
|
|
105
109
|
|
|
106
110
|
**普通网站中点击某个语言进行切换**
|
|
107
111
|
如下图所示,网站中的某个位置要有几种语言切换
|
|
108
|
-

|
|
109
113
|
直接在其html代码末尾的位置加入以下代码:
|
|
110
114
|
|
|
111
115
|
````
|
|
@@ -115,12 +119,12 @@ translate.execute();//进行翻译
|
|
|
115
119
|
<li><a href="javascript:translate.changeLanguage('chinese_simplified');">简体中文</a></li>|
|
|
116
120
|
<li><a href="javascript:translate.changeLanguage('chinese_traditional');">繁體中文</a></li>
|
|
117
121
|
</ul>
|
|
118
|
-
|
|
122
|
+
|
|
119
123
|
<!-- 引入多语言切换的js -->
|
|
120
|
-
<script src="https://cdn.staticfile.net/translate.js/3.
|
|
124
|
+
<script src="https://cdn.staticfile.net/translate.js/3.16.0/translate.js"></script>
|
|
121
125
|
<script>
|
|
122
126
|
translate.selectLanguageTag.show = false; //不出现的select的选择语言
|
|
123
|
-
translate.service.use('client.edge');
|
|
127
|
+
translate.service.use('client.edge'); //设置翻译服务通道
|
|
124
128
|
translate.execute();
|
|
125
129
|
</script>
|
|
126
130
|
````
|
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.17.0.20250703',
|
|
18
18
|
// AUTO_VERSION_END
|
|
19
19
|
/*
|
|
20
20
|
当前使用的版本,默认使用v2. 可使用 setUseVersion2();
|
|
@@ -177,20 +177,17 @@ var translate = {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
//从服务器加载支持的语言库
|
|
180
|
-
translate.request.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}catch(e){ console.log(e);}
|
|
192
|
-
*/
|
|
193
|
-
}, null);
|
|
180
|
+
if(typeof(translate.request.api.language) == 'string' && translate.request.api.language.length > 0){
|
|
181
|
+
translate.request.post(translate.request.api.language, {}, function(data){
|
|
182
|
+
if(data.result == 0){
|
|
183
|
+
console.log('load language list error : '+data.info);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
translate.selectLanguageTag.customUI(data.list);
|
|
188
|
+
}, null);
|
|
189
|
+
}
|
|
190
|
+
|
|
194
191
|
|
|
195
192
|
|
|
196
193
|
}
|
|
@@ -536,8 +533,24 @@ var translate = {
|
|
|
536
533
|
* 这个其实是借用了 自定义术语 的能力,设置了自定义术语的原字符等于翻译后的字符, 于是这个字符就不会被翻译了
|
|
537
534
|
* 这里可以是多个,数组,如 ['你好','世界']
|
|
538
535
|
*/
|
|
539
|
-
text:[]
|
|
540
|
-
|
|
536
|
+
text:[],
|
|
537
|
+
/*
|
|
538
|
+
下面的 textRegex 、 setTextRegexs 正则方式设置忽略不翻译text的能力,有 https://github.com/wangliangyu 提交贡献, 弥补 translate.ignore.text 固定设置的不足
|
|
539
|
+
*/
|
|
540
|
+
textRegex:[],
|
|
541
|
+
/*
|
|
542
|
+
使用方式如:
|
|
543
|
+
translate.ignore.setTextRegexs([/请求/g, /[\u4a01-\u4a05]+/g]);
|
|
544
|
+
*/
|
|
545
|
+
setTextRegexs: function(arr) {
|
|
546
|
+
if (!Array.isArray(arr)) throw new Error('参数必须为数组');
|
|
547
|
+
for (let i = 0; i < arr.length; i++) {
|
|
548
|
+
if (!(arr[i] instanceof RegExp)) {
|
|
549
|
+
throw new Error('第' + i + '项不是RegExp对象');
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
this.textRegex = [...this.textRegex, ...arr];
|
|
553
|
+
},
|
|
541
554
|
},
|
|
542
555
|
//刷新页面,你可以自定义刷新页面的方式,比如在 uniapp 打包生成 apk 时,apk中的刷新页面就不是h5的这个刷新,而是app的刷新方式,就需要自己进行重写这个刷新页面的方法了
|
|
543
556
|
refreshCurrentPage:function(){
|
|
@@ -654,6 +667,10 @@ var translate = {
|
|
|
654
667
|
}
|
|
655
668
|
//console.log(str)
|
|
656
669
|
for(var originalText in translate.nomenclature.data[translate.language.getLocal()][translate.to]){
|
|
670
|
+
if (!translate.nomenclature.data[translate.language.getLocal()][translate.to].hasOwnProperty(originalText)) {
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
|
|
657
674
|
var translateText = translate.nomenclature.data[translate.language.getLocal()][translate.to][originalText];
|
|
658
675
|
if(typeof(translateText) == 'function'){
|
|
659
676
|
//进行异常的预处理调出
|
|
@@ -753,8 +770,15 @@ var translate = {
|
|
|
753
770
|
|
|
754
771
|
var text = '';
|
|
755
772
|
for(var uuid in translate.nodeQueue){
|
|
773
|
+
if (!translate.nodeQueue.hasOwnProperty(uuid)) {
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
|
|
756
777
|
var queueValue = translate.nodeQueue[uuid];
|
|
757
778
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
779
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
758
782
|
//console.log('------'+lang)
|
|
759
783
|
if(typeof(lang) != 'string' || lang.length < 1){
|
|
760
784
|
continue;
|
|
@@ -762,6 +786,9 @@ var translate = {
|
|
|
762
786
|
//if(translate.language.getLocal() == lang){
|
|
763
787
|
//console.log(translate.nodeQueue[uuid].list[lang]);
|
|
764
788
|
for(var hash in translate.nodeQueue[uuid].list[lang]){
|
|
789
|
+
if (!translate.nodeQueue[uuid].list[lang].hasOwnProperty(hash)) {
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
765
792
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
766
793
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
767
794
|
text = text + '\n' + translate.nodeQueue[uuid].list[lang][hash].original + '='+translate.storage.get('hash_'+translate.language.getCurrent()+'_'+hash);
|
|
@@ -903,6 +930,9 @@ var translate = {
|
|
|
903
930
|
|
|
904
931
|
var data = await translate.storage.IndexedDB.list('hash_*');
|
|
905
932
|
for(var i in data){
|
|
933
|
+
if (!data.hasOwnProperty(i)) {
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
906
936
|
var originalText = data[i].value.originalText.replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
907
937
|
text = text + '\n' + originalText + '='+data[i].value.english.replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
908
938
|
}
|
|
@@ -1246,7 +1276,7 @@ var translate = {
|
|
|
1246
1276
|
//console.log(translate.nodeQueue[uuid]);
|
|
1247
1277
|
for(var i = 0; i < translate.listener.execute.renderFinishByApi.length; i++){
|
|
1248
1278
|
try{
|
|
1249
|
-
|
|
1279
|
+
translate.listener.execute.renderFinishByApi[i](uuid, from, to);
|
|
1250
1280
|
}catch(e){
|
|
1251
1281
|
console.log(e);
|
|
1252
1282
|
}
|
|
@@ -1336,6 +1366,10 @@ var translate = {
|
|
|
1336
1366
|
execute(){
|
|
1337
1367
|
//先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到
|
|
1338
1368
|
for(var hash in this.taskQueue){
|
|
1369
|
+
if (!this.taskQueue.hasOwnProperty(hash)) {
|
|
1370
|
+
continue;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1339
1373
|
var tasks = this.taskQueue[hash];
|
|
1340
1374
|
if(typeof(tasks) == 'function'){
|
|
1341
1375
|
//进行异常的预处理调出
|
|
@@ -1358,6 +1392,10 @@ var translate = {
|
|
|
1358
1392
|
|
|
1359
1393
|
//对nodeQueue进行翻译
|
|
1360
1394
|
for(var hash in this.nodes){
|
|
1395
|
+
if (!this.nodes.hasOwnProperty(hash)) {
|
|
1396
|
+
continue;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1361
1399
|
var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务
|
|
1362
1400
|
//var tagName = this.nodes[hash][0].nodeName; //以下节点的tag name
|
|
1363
1401
|
//console.log(tasks);
|
|
@@ -1438,8 +1476,16 @@ var translate = {
|
|
|
1438
1476
|
/** 执行完成后,保存翻译的历史node **/
|
|
1439
1477
|
//将当前翻译完成的node进行缓存记录,以node唯一标识为key, node、以及node当前翻译之后的内容为值进行缓存。方便下一次执行 translate.execute() 时,若值未变化则不进行翻译
|
|
1440
1478
|
for(var hash in renderTask.nodes){
|
|
1479
|
+
if (!renderTask.nodes.hasOwnProperty(hash)) {
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1441
1483
|
//console.log(translate.nodeQueue[uuid].list[lang][hash])
|
|
1442
1484
|
for(var nodeindex in renderTask.nodes[hash]){
|
|
1485
|
+
if (!renderTask.nodes[hash].hasOwnProperty(nodeindex)) {
|
|
1486
|
+
continue;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1443
1489
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].original);
|
|
1444
1490
|
//var nodename = translate.element.getNodeName(translate.nodeQueue[uuid].list[lang][hash].nodes[0].node);
|
|
1445
1491
|
//console.log("nodename:"+nodename);
|
|
@@ -1566,8 +1612,13 @@ var translate = {
|
|
|
1566
1612
|
@param to 翻译为的语种
|
|
1567
1613
|
*/
|
|
1568
1614
|
isAllExecuteFinish:function(uuid, from, to){
|
|
1615
|
+
translate.listener.execute.renderFinishByApiRun(uuid, from, to);
|
|
1616
|
+
|
|
1569
1617
|
//console.log('uuid:'+uuid+', from:'+from+', to:'+to);
|
|
1570
1618
|
for(var lang in translate.translateRequest[uuid]){
|
|
1619
|
+
if (!translate.translateRequest[uuid].hasOwnProperty(lang)) {
|
|
1620
|
+
continue;
|
|
1621
|
+
}
|
|
1571
1622
|
//console.log(translate.translateRequest[uuid])
|
|
1572
1623
|
for(var i = 0; i<translate.translateRequest[uuid][lang].length; i++){
|
|
1573
1624
|
if(translate.translateRequest[uuid][lang][i].executeFinish == 0){
|
|
@@ -1581,11 +1632,12 @@ var translate = {
|
|
|
1581
1632
|
}
|
|
1582
1633
|
}
|
|
1583
1634
|
|
|
1635
|
+
//生命周期触发事件
|
|
1636
|
+
translate.lifecycle.execute.renderFinish_Trigger(uuid, to);
|
|
1637
|
+
|
|
1584
1638
|
//都执行完了,那么设置完毕
|
|
1585
1639
|
translate.state = 0;
|
|
1586
1640
|
translate.executeNumber++;
|
|
1587
|
-
|
|
1588
|
-
translate.listener.execute.renderFinishByApiRun(uuid, from, to);
|
|
1589
1641
|
}
|
|
1590
1642
|
|
|
1591
1643
|
},
|
|
@@ -1593,6 +1645,75 @@ var translate = {
|
|
|
1593
1645
|
//execute() 方法已经被执行过多少次了, 只有execute() 完全执行完,也就是界面渲染完毕后,它才会+1
|
|
1594
1646
|
executeNumber:0,
|
|
1595
1647
|
|
|
1648
|
+
lifecycle:{
|
|
1649
|
+
execute:{
|
|
1650
|
+
/*
|
|
1651
|
+
每当触发执行 translate.execute() 时,当缓存中未发现,需要请求翻译API进行翻译时,在发送API请求前,触发此
|
|
1652
|
+
|
|
1653
|
+
@param uuid:translate.nodeQueue[uuid] 这里的
|
|
1654
|
+
@param from 来源语种,翻译前的语种
|
|
1655
|
+
@param to 翻译为的语种
|
|
1656
|
+
*/
|
|
1657
|
+
start : [],
|
|
1658
|
+
startRun:function(uuid, from, to){
|
|
1659
|
+
//console.log(translate.nodeQueue[uuid]);
|
|
1660
|
+
for(var i = 0; i < translate.listener.execute.renderStartByApi.length; i++){
|
|
1661
|
+
try{
|
|
1662
|
+
translate.listener.execute.renderStartByApi[i](uuid, from, to);
|
|
1663
|
+
}catch(e){
|
|
1664
|
+
console.log(e);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
},
|
|
1668
|
+
|
|
1669
|
+
/*
|
|
1670
|
+
当扫描整个节点完成,进行翻译(1. 命中本地缓存、 2.进行网络翻译请求)之前,触发
|
|
1671
|
+
*/
|
|
1672
|
+
scanNodesFinsh: [],
|
|
1673
|
+
|
|
1674
|
+
/*
|
|
1675
|
+
当进行触发网络翻译请求之前,触发此
|
|
1676
|
+
*/
|
|
1677
|
+
translateNetworkBefore:[],
|
|
1678
|
+
|
|
1679
|
+
/*
|
|
1680
|
+
当 translate.execute() 触发网络翻译请求完毕(不管成功还是失败),并将翻译结果渲染到页面完毕后,触发此。
|
|
1681
|
+
@param uuid translate.nodeQueue 的uuid
|
|
1682
|
+
@param to 当前是执行的翻译为什么语种
|
|
1683
|
+
*/
|
|
1684
|
+
translateNetworkFinish:[],
|
|
1685
|
+
translateNetworkAfter_Trigger:function(uuid, to){
|
|
1686
|
+
for(var i = 0; i < translate.lifecycle.execute.translateNetworkAfter.length; i++){
|
|
1687
|
+
try{
|
|
1688
|
+
translate.lifecycle.execute.translateNetworkAfter[i](uuid, to);
|
|
1689
|
+
}catch(e){
|
|
1690
|
+
console.log(e);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
},
|
|
1694
|
+
|
|
1695
|
+
/*
|
|
1696
|
+
translate.execute() 的翻译渲染完毕触发
|
|
1697
|
+
这个完毕是指它当触发 translate.execute() 进行翻译后,无论是全部命中了本地缓存,还是有部分要通过翻译接口发起多个网络请求,当拿到结果(缓存中的翻译结果或多个不同的有xx语种翻译的网络请求全部完成,这个完成是包含所有成功跟失败的响应),并完成将翻译结果渲染到页面中进行显示后,触发此
|
|
1698
|
+
它跟 translateNetworkFinish 的区别是, translateNetworkFinish 仅仅针对有网络请求的才会触发,而 renderFinish 是如果全部命中了浏览器本地缓存,无需发起任何网络翻译请求这种情况时,也会触发。
|
|
1699
|
+
@param uuid translate.nodeQueue 的uuid
|
|
1700
|
+
@param to 当前是执行的翻译为什么语种
|
|
1701
|
+
*/
|
|
1702
|
+
renderFinish:[function(uuid, to){ //这里默认带着一个触发翻译为英文后,自动对英文进行元素视觉处理,追加空格的
|
|
1703
|
+
translate.visual.adjustTranslationSpacesByNodequeueUuid(uuid);
|
|
1704
|
+
}],
|
|
1705
|
+
renderFinish_Trigger:function(uuid, to){
|
|
1706
|
+
for(var i = 0; i < translate.lifecycle.execute.renderFinish.length; i++){
|
|
1707
|
+
try{
|
|
1708
|
+
translate.lifecycle.execute.renderFinish[i](uuid, to);
|
|
1709
|
+
}catch(e){
|
|
1710
|
+
console.log(e);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
},
|
|
1716
|
+
|
|
1596
1717
|
/*translate.execute() start */
|
|
1597
1718
|
/*
|
|
1598
1719
|
执行翻译操作。翻译的是 nodeQueue 中的
|
|
@@ -1742,6 +1863,9 @@ var translate = {
|
|
|
1742
1863
|
if(translate.language.translateLanguagesRange.length > 0){
|
|
1743
1864
|
//如果大于0,则是有设置,那么只翻译有设置的语种,不在设置中的语种不会参与翻译
|
|
1744
1865
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
1866
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
1867
|
+
continue;
|
|
1868
|
+
}
|
|
1745
1869
|
if(translate.language.translateLanguagesRange.indexOf(lang) < 0){
|
|
1746
1870
|
//删除这个语种
|
|
1747
1871
|
delete translate.nodeQueue[uuid].list[lang];
|
|
@@ -1759,13 +1883,23 @@ var translate = {
|
|
|
1759
1883
|
console.log('您使用translate.js时可能放的位置不对,不要吧 translate.js 放在网页最顶部,这样当 translate.js 进行执行,也就是 translate.execute() 执行时,因为网页是从上往下加载,它放在网页最顶部,那么它执行时网页后面的内容都还没加载出来,这个是不会获取到网页任何内容的,也就是它是不起任何作用的');
|
|
1760
1884
|
}
|
|
1761
1885
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
1886
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(lang)) {
|
|
1887
|
+
continue;
|
|
1888
|
+
}
|
|
1762
1889
|
//console.log('lang:'+lang)
|
|
1763
1890
|
for(var hash in translate.nodeQueue[uuid].list[lang]){
|
|
1891
|
+
if (!translate.nodeQueue[uuid].list[lang].hasOwnProperty(hash)) {
|
|
1892
|
+
continue;
|
|
1893
|
+
}
|
|
1764
1894
|
//console.log(hash)
|
|
1765
1895
|
if(typeof(translate.nodeQueue[uuid].list[lang][hash]) == 'function'){
|
|
1766
1896
|
//v2.10增加,避免hash冒出个 Contains 出来导致for中的.length 出错
|
|
1767
1897
|
continue;
|
|
1768
1898
|
}
|
|
1899
|
+
if(typeof(translate.nodeQueue[uuid].list[lang][hash].nodes) == 'undefined' || typeof(translate.nodeQueue[uuid].list[lang][hash].nodes.length) == 'undefined'){
|
|
1900
|
+
//v3.16.2 增加,针对深圳北理莫斯科学校龙老师提出的这里 .length 遇到了 undefined 的情况
|
|
1901
|
+
continue;
|
|
1902
|
+
}
|
|
1769
1903
|
for(var nodeindex = translate.nodeQueue[uuid].list[lang][hash].nodes.length-1; nodeindex > -1; nodeindex--){
|
|
1770
1904
|
//console.log(translate.nodeQueue[uuid].list[lang][hash].nodes);
|
|
1771
1905
|
var analyse = translate.element.nodeAnalyse.get(translate.nodeQueue[uuid].list[lang][hash].nodes[nodeindex].node);
|
|
@@ -1832,6 +1966,9 @@ var translate = {
|
|
|
1832
1966
|
var twoScanNodes = {};
|
|
1833
1967
|
var cacheScanNodes = []; //同上面的 twoScanNodes,只不过 twoScanNodes 是按照lang存的,而这个不再有lang区分
|
|
1834
1968
|
for(var lang in translate.nodeQueue[uuid]['list']){ //二维数组中,取语言
|
|
1969
|
+
if (!translate.nodeQueue[uuid]['list'].hasOwnProperty(lang)) {
|
|
1970
|
+
continue;
|
|
1971
|
+
}
|
|
1835
1972
|
//console.log('lang:'+lang); //lang为english这种语言标识
|
|
1836
1973
|
if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){
|
|
1837
1974
|
//console.log('lang is null : '+lang);
|
|
@@ -1847,6 +1984,9 @@ var translate = {
|
|
|
1847
1984
|
twoScanNodes[lang] = [];
|
|
1848
1985
|
//二维数组,取hash、value
|
|
1849
1986
|
for(var hash in translate.nodeQueue[uuid]['list'][lang]){
|
|
1987
|
+
if (!translate.nodeQueue[uuid]['list'][lang].hasOwnProperty(hash)) {
|
|
1988
|
+
continue;
|
|
1989
|
+
}
|
|
1850
1990
|
if(typeof(translate.nodeQueue[uuid]['list'][lang][hash]) == 'function'){
|
|
1851
1991
|
//跳出,增加容错。 正常情况下应该不会这样
|
|
1852
1992
|
continue;
|
|
@@ -1996,6 +2136,10 @@ var translate = {
|
|
|
1996
2136
|
|
|
1997
2137
|
/******* 进行第二次扫描、追加入翻译队列。目的是防止缓存打散扫描的待翻译文本 ********/
|
|
1998
2138
|
for(var lang in twoScanNodes){
|
|
2139
|
+
if (!twoScanNodes.hasOwnProperty(lang)) {
|
|
2140
|
+
continue;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
1999
2143
|
//记录第一次扫描的数据,以便跟第二次扫描后的进行对比
|
|
2000
2144
|
var firstScan = Object.keys(translate.nodeQueue[uuid]['list'][lang]);
|
|
2001
2145
|
var firstScan_lang_langth = firstScan.length; //第一次扫描后的数组长度
|
|
@@ -2077,6 +2221,10 @@ var translate = {
|
|
|
2077
2221
|
var fanyiLangs = [];
|
|
2078
2222
|
//console.log(translateTextArray)
|
|
2079
2223
|
for(var lang in translate.nodeQueue[uuid]['list']){ //二维数组中取语言
|
|
2224
|
+
if (!translate.nodeQueue[uuid]['list'].hasOwnProperty(lang)) {
|
|
2225
|
+
continue;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2080
2228
|
if(typeof(translateTextArray[lang]) == 'undefined'){
|
|
2081
2229
|
continue;
|
|
2082
2230
|
}
|
|
@@ -2112,6 +2260,10 @@ var translate = {
|
|
|
2112
2260
|
//console.log(translate.nodeQueue[uuid]['list'])
|
|
2113
2261
|
if(fanyiLangs.length == 0){
|
|
2114
2262
|
//没有需要翻译的,直接退出
|
|
2263
|
+
|
|
2264
|
+
//生命周期触发事件
|
|
2265
|
+
translate.lifecycle.execute.renderFinish_Trigger(uuid, translate.to);
|
|
2266
|
+
|
|
2115
2267
|
translate.state = 0;
|
|
2116
2268
|
translate.executeNumber++;
|
|
2117
2269
|
return;
|
|
@@ -2119,6 +2271,9 @@ var translate = {
|
|
|
2119
2271
|
|
|
2120
2272
|
//加入 translate.inProgressNodes -- start
|
|
2121
2273
|
for(var lang in translateHashArray){
|
|
2274
|
+
if (!translateHashArray.hasOwnProperty(lang)) {
|
|
2275
|
+
continue;
|
|
2276
|
+
}
|
|
2122
2277
|
if(typeof(translateHashArray[lang]) == 'undefined'){
|
|
2123
2278
|
continue;
|
|
2124
2279
|
}
|
|
@@ -2132,6 +2287,11 @@ var translate = {
|
|
|
2132
2287
|
//console.log('translate.nodeQueue[\''+uuid+'\'][\'list\'][\'chinese_simplified\'][\''+thhash+'\']');
|
|
2133
2288
|
//console.log(lang);
|
|
2134
2289
|
//console.log(translate.nodeQueue[uuid]['list'][lang][thhash].nodes);
|
|
2290
|
+
if(typeof(translate.nodeQueue[uuid]['list'][lang][thhash].nodes) == 'undefined' || typeof(translate.nodeQueue[uuid]['list'][lang][thhash].nodes.length) == 'undefined'){
|
|
2291
|
+
console.log('translate.nodeQueue[\''+uuid+'\'][\'list\'][\''+lang+'\'][\''+thhash+'\'].nodes.length is null ,理论上不应该存在,进行异常报出,但不影响使用,已容错。');
|
|
2292
|
+
continue;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2135
2295
|
for(var ipni = 0; ipni < translate.nodeQueue[uuid]['list'][lang][thhash].nodes.length; ipni++){
|
|
2136
2296
|
//取得这个翻译的node
|
|
2137
2297
|
var ipnode = translate.nodeQueue[uuid]['list'][lang][thhash].nodes[ipni].node;
|
|
@@ -2163,14 +2323,21 @@ var translate = {
|
|
|
2163
2323
|
//状态
|
|
2164
2324
|
translate.state = 20;
|
|
2165
2325
|
|
|
2166
|
-
|
|
2167
2326
|
//进行掉接口翻译
|
|
2168
2327
|
for(var lang_index in fanyiLangs){ //一维数组,取语言
|
|
2328
|
+
if (!fanyiLangs.hasOwnProperty(lang_index)) {
|
|
2329
|
+
continue;
|
|
2330
|
+
}
|
|
2169
2331
|
var lang = fanyiLangs[lang_index];
|
|
2170
|
-
|
|
2332
|
+
if(typeof(lang) != 'string'){
|
|
2333
|
+
continue;
|
|
2334
|
+
}
|
|
2171
2335
|
|
|
2172
2336
|
if(typeof(translateTextArray[lang]) == 'undefined' || translateTextArray[lang].length < 1){
|
|
2173
|
-
console.log('
|
|
2337
|
+
console.log('异常,理论上不应该存在, lang:'+lang+', translateTextArray:');
|
|
2338
|
+
console.log(translateTextArray);
|
|
2339
|
+
console.log('你无需担心,这个只是个提示,它并不影响你翻译的正常进行,只是个异常提示而已,它会自动容错处理的,不会影响翻译的使用。');
|
|
2340
|
+
|
|
2174
2341
|
translate.state = 0;
|
|
2175
2342
|
translate.executeNumber++;
|
|
2176
2343
|
return;
|
|
@@ -2313,10 +2480,10 @@ var translate = {
|
|
|
2313
2480
|
translate.waitingExecute.isAllExecuteFinish(uuid, data.from, data.to);
|
|
2314
2481
|
},10);
|
|
2315
2482
|
}, function(xhr){
|
|
2316
|
-
translate.translateRequest[uuid][
|
|
2317
|
-
translate.translateRequest[uuid][
|
|
2318
|
-
translate.translateRequest[uuid][
|
|
2319
|
-
translate.waitingExecute.isAllExecuteFinish(uuid,
|
|
2483
|
+
translate.translateRequest[uuid][xhr.data.from].executeFinish = 1; //1是执行完毕
|
|
2484
|
+
translate.translateRequest[uuid][xhr.data.from].stoptime = Math.floor(Date.now() / 1000);
|
|
2485
|
+
translate.translateRequest[uuid][xhr.data.from].result = 3;
|
|
2486
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, xhr.data.from, translate.to);
|
|
2320
2487
|
});
|
|
2321
2488
|
/*** 翻译end ***/
|
|
2322
2489
|
}
|
|
@@ -2602,7 +2769,9 @@ var translate = {
|
|
|
2602
2769
|
}else{
|
|
2603
2770
|
//替换渲染
|
|
2604
2771
|
if(typeof(originalText) != 'undefined' && originalText != null && originalText.length > 0){
|
|
2772
|
+
//console.log(originalText+'|');
|
|
2605
2773
|
var resultShowText = translate.util.textReplace(node.nodeValue, originalText, resultText, translate.to);
|
|
2774
|
+
//console.log(resultShowText+'|');
|
|
2606
2775
|
node.nodeValue = resultShowText; //2025.4.26 变更为此方式
|
|
2607
2776
|
if(resultShowText.indexOf(resultText) > -1){
|
|
2608
2777
|
result['resultText'] = resultShowText;
|
|
@@ -2675,6 +2844,9 @@ var translate = {
|
|
|
2675
2844
|
//console.log(translate.element.tagAttribute[nodeNameLowerCase]);
|
|
2676
2845
|
|
|
2677
2846
|
for(var attributeName_index in translate.element.tagAttribute[nodeNameLowerCase]){
|
|
2847
|
+
if (!translate.element.tagAttribute[nodeNameLowerCase].hasOwnProperty(attributeName_index)) {
|
|
2848
|
+
continue;
|
|
2849
|
+
}
|
|
2678
2850
|
|
|
2679
2851
|
var attributeName = translate.element.tagAttribute[nodeNameLowerCase][attributeName_index];
|
|
2680
2852
|
//console.log(attributeName);
|
|
@@ -2912,6 +3084,16 @@ var translate = {
|
|
|
2912
3084
|
textArray.push(text); //先将主 text 赋予 ,后面如果对主text进行加工分割,分割后会将主text给删除掉
|
|
2913
3085
|
//console.log(textArray);
|
|
2914
3086
|
|
|
3087
|
+
// 处理 ignore.regex
|
|
3088
|
+
for (var ri = 0; ri < translate.ignore.textRegex.length; ri++) {
|
|
3089
|
+
var regex = translate.ignore.textRegex[ri];
|
|
3090
|
+
for (var tai = 0; tai < textArray.length; tai++) {
|
|
3091
|
+
var text = textArray[tai];
|
|
3092
|
+
var ignoreTexts = text.match(regex) || []
|
|
3093
|
+
translate.ignore.text = translate.ignore.text.concat(ignoreTexts)
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
|
|
2915
3097
|
/**** v3.10.2.20241206 - 增加自定义忽略翻译的文本,忽略翻译的文本不会被翻译 - 当然这样会打乱翻译之后阅读的连贯性 ****/
|
|
2916
3098
|
for(var ti = 0; ti<translate.ignore.text.length; ti++){
|
|
2917
3099
|
if(translate.ignore.text[ti].trim().length == 0){
|
|
@@ -2924,7 +3106,6 @@ var translate = {
|
|
|
2924
3106
|
}
|
|
2925
3107
|
|
|
2926
3108
|
|
|
2927
|
-
|
|
2928
3109
|
/**** v3.10.2.20241206 - 自定义术语能力全面优化 - 当然这样会打乱翻译之后阅读的连贯性 ****/
|
|
2929
3110
|
//判断是否进行了翻译,也就是有设置目标语种,并且跟当前语种不一致
|
|
2930
3111
|
if(typeof(translate.temp_nomenclature) == 'undefined'){
|
|
@@ -2936,6 +3117,9 @@ var translate = {
|
|
|
2936
3117
|
if(typeof(translate.nomenclature.data[translate.language.getLocal()]) != 'undefined' && typeof(translate.nomenclature.data[translate.language.getLocal()][translate.to]) != 'undefined'){
|
|
2937
3118
|
var nomenclatureKeyArray;
|
|
2938
3119
|
for(var nomenclatureKey in translate.nomenclature.data[translate.language.getLocal()][translate.to]){
|
|
3120
|
+
if (!translate.nomenclature.data[translate.language.getLocal()][translate.to].hasOwnProperty(nomenclatureKey)) {
|
|
3121
|
+
continue;
|
|
3122
|
+
}
|
|
2939
3123
|
//nomenclatureKey 便是自定义术语的原始文本,值是要替换为的文本
|
|
2940
3124
|
//console.log(nomenclatureKey);
|
|
2941
3125
|
//自定义属于的指定的结果字符串
|
|
@@ -3147,6 +3331,9 @@ var translate = {
|
|
|
3147
3331
|
//console.log(langs);
|
|
3148
3332
|
|
|
3149
3333
|
for(var lang in langs) {
|
|
3334
|
+
if (!langs.hasOwnProperty(lang)) {
|
|
3335
|
+
continue;
|
|
3336
|
+
}
|
|
3150
3337
|
//创建二维数组, key为语种,如 english
|
|
3151
3338
|
/*
|
|
3152
3339
|
放到了 translate.addNodeQueueItem 进行判断
|
|
@@ -3512,21 +3699,32 @@ var translate = {
|
|
|
3512
3699
|
autoRecognitionLocalLanguage:function(){
|
|
3513
3700
|
if(translate.language.local != null && translate.language.local.length > 2){
|
|
3514
3701
|
//已设置过了,不需要再设置
|
|
3515
|
-
return;
|
|
3702
|
+
return translate.language.local;
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
//v3.16.1 优化,获取本地语种,针对开源中国只对 readme 部分进行翻译的场景,将针对设置的 translate.setDocument() 区域的元素的显示文本进行判定语种
|
|
3706
|
+
var translateAreaText = ''; //翻译区域内当前的文本
|
|
3707
|
+
var docs = translate.getDocuments();
|
|
3708
|
+
for(var docs_index = 0; docs_index < docs.length; docs_index++){
|
|
3709
|
+
var doc = docs[docs_index];
|
|
3710
|
+
if(typeof(doc) != 'undefined' && doc != null && typeof(doc.innerText) != 'undefined' && doc.innerText != null && doc.innerText.length > 0){
|
|
3711
|
+
translateAreaText = translateAreaText + doc.innerText;
|
|
3712
|
+
}
|
|
3516
3713
|
}
|
|
3517
3714
|
|
|
3518
|
-
|
|
3519
|
-
|
|
3715
|
+
|
|
3716
|
+
//var bodyText = document.body.outerText;
|
|
3717
|
+
if(translateAreaText == null || typeof(translateAreaText) == 'undefined' || translateAreaText.length < 1){
|
|
3520
3718
|
//未取到,默认赋予简体中文
|
|
3521
3719
|
translate.language.local = 'chinese_simplified';
|
|
3522
3720
|
return;
|
|
3523
3721
|
}
|
|
3524
3722
|
|
|
3525
|
-
|
|
3723
|
+
translateAreaText = translateAreaText.replace(/\n|\t|\r/g,''); //将回车换行等去掉
|
|
3526
3724
|
|
|
3527
3725
|
//默认赋予简体中文
|
|
3528
3726
|
translate.language.local = 'chinese_simplified';
|
|
3529
|
-
var recognition = translate.language.recognition(
|
|
3727
|
+
var recognition = translate.language.recognition(translateAreaText);
|
|
3530
3728
|
translate.language.local = recognition.languageName;
|
|
3531
3729
|
return translate.language.local;
|
|
3532
3730
|
/* v3.1优化
|
|
@@ -3712,6 +3910,9 @@ var translate = {
|
|
|
3712
3910
|
var langsNumberOriginal = []; //同上,只不过这个不会进行清空字符数
|
|
3713
3911
|
var allNumber = 0;//总字数
|
|
3714
3912
|
for(var key in langs){
|
|
3913
|
+
if (!langs.hasOwnProperty(key)) {
|
|
3914
|
+
continue;
|
|
3915
|
+
}
|
|
3715
3916
|
if(typeof(langs[key]) != 'object'){
|
|
3716
3917
|
continue;
|
|
3717
3918
|
}
|
|
@@ -3727,6 +3928,9 @@ var translate = {
|
|
|
3727
3928
|
//过滤 语种的字符数小于总字符数 百分之五的,低于这个数,将忽略
|
|
3728
3929
|
var langkeys = [];
|
|
3729
3930
|
for(var lang in langsNumber){
|
|
3931
|
+
if (!langsNumber.hasOwnProperty(lang)) {
|
|
3932
|
+
continue;
|
|
3933
|
+
}
|
|
3730
3934
|
if(langsNumber[lang]/allNumber > 0.01){
|
|
3731
3935
|
langkeys[langkeys.length] = lang+'';
|
|
3732
3936
|
}
|
|
@@ -3770,6 +3974,9 @@ var translate = {
|
|
|
3770
3974
|
var maxLang = ''; //字数最多的语种
|
|
3771
3975
|
var maxNumber = 0;
|
|
3772
3976
|
for(var lang in langsNumber){
|
|
3977
|
+
if (!langsNumber.hasOwnProperty(lang)) {
|
|
3978
|
+
continue;
|
|
3979
|
+
}
|
|
3773
3980
|
if(langsNumber[lang] > maxNumber){
|
|
3774
3981
|
maxLang = lang;
|
|
3775
3982
|
maxNumber = langsNumber[lang];
|
|
@@ -3779,6 +3986,9 @@ var translate = {
|
|
|
3779
3986
|
//重新组合返回值的 languageArray
|
|
3780
3987
|
var languageArray = {};
|
|
3781
3988
|
for(var lang in langs){
|
|
3989
|
+
if (!langs.hasOwnProperty(lang)) {
|
|
3990
|
+
continue;
|
|
3991
|
+
}
|
|
3782
3992
|
languageArray[lang] = {};
|
|
3783
3993
|
languageArray[lang].number = langsNumberOriginal[lang];
|
|
3784
3994
|
languageArray[lang].list = langs[lang];
|
|
@@ -4448,6 +4658,10 @@ var translate = {
|
|
|
4448
4658
|
return;
|
|
4449
4659
|
}
|
|
4450
4660
|
|
|
4661
|
+
if(typeof(translate.request.api.ip) != 'string' || translate.request.api.ip == null || translate.request.api.ip.length < 1){
|
|
4662
|
+
return;
|
|
4663
|
+
}
|
|
4664
|
+
|
|
4451
4665
|
//如果用户浏览器没读到默认语言,或者默认语言没有对应到translate.js支持的语种,那么在采用ip识别的方式
|
|
4452
4666
|
translate.request.post(translate.request.api.ip, {}, function(data){
|
|
4453
4667
|
//console.log(data);
|
|
@@ -4533,6 +4747,7 @@ var translate = {
|
|
|
4533
4747
|
}else{
|
|
4534
4748
|
//补充上一个空格,用于将两个单词隔开
|
|
4535
4749
|
replaceResultText = replaceResultText + ' ';
|
|
4750
|
+
//console.log('after add space : '+replaceResultText);
|
|
4536
4751
|
}
|
|
4537
4752
|
|
|
4538
4753
|
}
|
|
@@ -4557,6 +4772,7 @@ var translate = {
|
|
|
4557
4772
|
//补充上一个空格,用于将两个单词隔开
|
|
4558
4773
|
//text = text.replace(translateOriginal, ' '+translateResult);
|
|
4559
4774
|
replaceResultText = ' '+replaceResultText;
|
|
4775
|
+
//console.log('before add space : '+replaceResultText);
|
|
4560
4776
|
}
|
|
4561
4777
|
}
|
|
4562
4778
|
}else{
|
|
@@ -4658,6 +4874,9 @@ var translate = {
|
|
|
4658
4874
|
}
|
|
4659
4875
|
|
|
4660
4876
|
for(var item in numbers){
|
|
4877
|
+
if (!numbers.hasOwnProperty(item)) {
|
|
4878
|
+
continue;
|
|
4879
|
+
}
|
|
4661
4880
|
if(numbers[item]===maxNum){
|
|
4662
4881
|
maxStr.push(item)
|
|
4663
4882
|
}
|
|
@@ -5198,7 +5417,43 @@ var translate = {
|
|
|
5198
5417
|
}
|
|
5199
5418
|
|
|
5200
5419
|
return result;
|
|
5420
|
+
},
|
|
5421
|
+
|
|
5422
|
+
/*js translate.util.getElementPosition start*/
|
|
5423
|
+
/*
|
|
5424
|
+
计算一个元素在浏览器中的坐标系,其绝对定位、以及实际显示出来所占用的区域,宽、高
|
|
5425
|
+
*/
|
|
5426
|
+
getElementPosition:function (node) {
|
|
5427
|
+
// 获取元素的边界矩形信息(相对于视口)
|
|
5428
|
+
const rect = node.getBoundingClientRect();
|
|
5429
|
+
|
|
5430
|
+
// 获取当前页面的滚动位置(兼容不同浏览器)
|
|
5431
|
+
const scrollX = window.scrollX || document.documentElement.scrollLeft;
|
|
5432
|
+
const scrollY = window.scrollY || document.documentElement.scrollTop;
|
|
5433
|
+
|
|
5434
|
+
// 计算元素在文档中的起始坐标
|
|
5435
|
+
const startX = rect.left + scrollX;
|
|
5436
|
+
const startY = rect.top + scrollY;
|
|
5437
|
+
|
|
5438
|
+
// 计算元素的宽度和高度
|
|
5439
|
+
const width = rect.right - rect.left;
|
|
5440
|
+
const height = rect.bottom - rect.top;
|
|
5441
|
+
|
|
5442
|
+
// 计算元素在文档中的结束坐标
|
|
5443
|
+
const endX = startX + width;
|
|
5444
|
+
const endY = startY + height;
|
|
5445
|
+
|
|
5446
|
+
// 返回包含所有信息的对象
|
|
5447
|
+
return {
|
|
5448
|
+
startX,
|
|
5449
|
+
startY,
|
|
5450
|
+
endX,
|
|
5451
|
+
endY,
|
|
5452
|
+
width,
|
|
5453
|
+
height
|
|
5454
|
+
};
|
|
5201
5455
|
}
|
|
5456
|
+
/*js translate.util.getElementPosition end*/
|
|
5202
5457
|
},
|
|
5203
5458
|
//机器翻译采用哪种翻译服务
|
|
5204
5459
|
service:{
|
|
@@ -5570,6 +5825,10 @@ var translate = {
|
|
|
5570
5825
|
'content-type':'application/x-www-form-urlencoded',
|
|
5571
5826
|
};
|
|
5572
5827
|
|
|
5828
|
+
if(typeof(translate.request.api.connectTest) != 'string' || translate.request.api.connectTest == null || translate.request.api.connectTest.length < 1){
|
|
5829
|
+
return;
|
|
5830
|
+
}
|
|
5831
|
+
|
|
5573
5832
|
|
|
5574
5833
|
translate.request.speedDetectionControl.checkHostQueue = []; //用于实际存储
|
|
5575
5834
|
translate.request.speedDetectionControl.checkHostQueueMap = []; //只是map,通过key取值,无其他作用
|
|
@@ -5623,7 +5882,7 @@ var translate = {
|
|
|
5623
5882
|
headers,
|
|
5624
5883
|
function(data){
|
|
5625
5884
|
//translate.request.speedDetectionControl.checkResponseSpeed_Storage(host, time);
|
|
5626
|
-
var hostUrl = data.requestURL.replace(
|
|
5885
|
+
var hostUrl = data.requestURL.replace(translate.request.api.connectTest,'');
|
|
5627
5886
|
translate.request.speedDetectionControl.checkResponseSpeed_Storage(hostUrl, translate.request.speedDetectionControl.disableTime);
|
|
5628
5887
|
},
|
|
5629
5888
|
false
|
|
@@ -5758,6 +6017,9 @@ var translate = {
|
|
|
5758
6017
|
|
|
5759
6018
|
//追加附加参数
|
|
5760
6019
|
for(var apindex in translate.request.appendParams){
|
|
6020
|
+
if (!translate.request.appendParams.hasOwnProperty(apindex)) {
|
|
6021
|
+
continue;
|
|
6022
|
+
}
|
|
5761
6023
|
data[apindex] = translate.request.appendParams[apindex];
|
|
5762
6024
|
}
|
|
5763
6025
|
|
|
@@ -5770,6 +6032,9 @@ var translate = {
|
|
|
5770
6032
|
|
|
5771
6033
|
//组合参数
|
|
5772
6034
|
for(var index in data){
|
|
6035
|
+
if (!data.hasOwnProperty(index)) {
|
|
6036
|
+
continue;
|
|
6037
|
+
}
|
|
5773
6038
|
if(params.length > 0){
|
|
5774
6039
|
params = params + '&';
|
|
5775
6040
|
}
|
|
@@ -5790,17 +6055,24 @@ var translate = {
|
|
|
5790
6055
|
}catch(e){
|
|
5791
6056
|
xhr=new ActiveXObject("Microsoft.XMLHTTP");
|
|
5792
6057
|
}
|
|
6058
|
+
xhr.data=data;
|
|
5793
6059
|
//2.调用open方法(true----异步)
|
|
5794
6060
|
xhr.open(method,url,isAsynchronize);
|
|
5795
6061
|
//设置headers
|
|
5796
6062
|
if(headers != null){
|
|
5797
6063
|
for(var index in headers){
|
|
6064
|
+
if (!headers.hasOwnProperty(index)) {
|
|
6065
|
+
continue;
|
|
6066
|
+
}
|
|
5798
6067
|
xhr.setRequestHeader(index,headers[index]);
|
|
5799
6068
|
}
|
|
5800
6069
|
}
|
|
5801
6070
|
|
|
5802
6071
|
//追加附加参数
|
|
5803
6072
|
for(var ahindex in translate.request.appendHeaders){
|
|
6073
|
+
if (!translate.request.appendHeaders.hasOwnProperty(ahindex)) {
|
|
6074
|
+
continue;
|
|
6075
|
+
}
|
|
5804
6076
|
xhr.setRequestHeader(ahindex,translate.request.appendHeaders[ahindex]);
|
|
5805
6077
|
}
|
|
5806
6078
|
|
|
@@ -6293,6 +6565,9 @@ var translate = {
|
|
|
6293
6565
|
}
|
|
6294
6566
|
*/
|
|
6295
6567
|
for(var key in queueArray){
|
|
6568
|
+
if (!queueArray.hasOwnProperty(key)) {
|
|
6569
|
+
continue;
|
|
6570
|
+
}
|
|
6296
6571
|
translate.images.queues[key] = queueArray[key];
|
|
6297
6572
|
}
|
|
6298
6573
|
},
|
|
@@ -6387,50 +6662,81 @@ var translate = {
|
|
|
6387
6662
|
//对翻译结果进行复原。比如当前网页是简体中文的,被翻译为了英文,执行此方法即可复原为网页本身简体中文的状态,而无需在通过刷新页面来实现
|
|
6388
6663
|
reset:function(){
|
|
6389
6664
|
var currentLanguage = translate.language.getCurrent(); //获取当前翻译至的语种
|
|
6665
|
+
|
|
6666
|
+
var lastUuid = ''; //最后一次的uuid
|
|
6390
6667
|
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
|
-
|
|
6668
|
+
if (!translate.nodeQueue.hasOwnProperty(queue)) {
|
|
6669
|
+
continue;
|
|
6670
|
+
}
|
|
6671
|
+
lastUuid = queue;
|
|
6672
|
+
}
|
|
6673
|
+
//console.log(queue);
|
|
6674
|
+
|
|
6675
|
+
if(lastUuid == ''){
|
|
6676
|
+
console.log('提示,你当前还未执行过翻译,所以你无需执行 translate.reset(); 进行还原。');
|
|
6677
|
+
return;
|
|
6678
|
+
}
|
|
6679
|
+
|
|
6680
|
+
for(var lang in translate.nodeQueue[lastUuid].list){
|
|
6681
|
+
if (!translate.nodeQueue[lastUuid].list.hasOwnProperty(lang)) {
|
|
6682
|
+
continue;
|
|
6683
|
+
}
|
|
6684
|
+
//console.log(lang);
|
|
6685
|
+
|
|
6686
|
+
for(var hash in translate.nodeQueue[lastUuid].list[lang]){
|
|
6687
|
+
if (!translate.nodeQueue[lastUuid].list[lang].hasOwnProperty(hash)) {
|
|
6688
|
+
continue;
|
|
6689
|
+
}
|
|
6690
|
+
var item = translate.nodeQueue[lastUuid].list[lang][hash];
|
|
6691
|
+
//console.log(item);
|
|
6692
|
+
for(var index in item.nodes){
|
|
6693
|
+
if (!item.nodes.hasOwnProperty(index)) {
|
|
6694
|
+
continue;
|
|
6695
|
+
}
|
|
6696
|
+
//console.log(item.nodes[index]);
|
|
6697
|
+
//item.nodes[index].node.nodeValue = item.original;
|
|
6698
|
+
var currentShow = translate.storage.get('hash_'+currentLanguage+'_'+hash); //当前显示出来的文字,也就是已经翻译后的文字
|
|
6699
|
+
//console.log('hash_'+lang+'_'+hash+' -- '+currentShow);
|
|
6700
|
+
if(typeof(currentShow) == 'undefined'){
|
|
6701
|
+
continue;
|
|
6702
|
+
}
|
|
6703
|
+
if(currentShow == null){
|
|
6704
|
+
continue;
|
|
6705
|
+
}
|
|
6706
|
+
if(currentShow.length == 0){
|
|
6707
|
+
continue;
|
|
6708
|
+
}
|
|
6412
6709
|
/*
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6710
|
+
if(item.beforeText.length > 0 || item.afterText.length > 0){
|
|
6711
|
+
console.log('----'+currentShow);
|
|
6712
|
+
console.log(item);
|
|
6713
|
+
}
|
|
6714
|
+
|
|
6715
|
+
if(item.beforeText.length > 0){
|
|
6716
|
+
currentShow = currentShow.substring(currentShow.lastIndexOf(item.beforeText)+1, currentShow.length);
|
|
6717
|
+
}
|
|
6718
|
+
if(item.afterText.length > 0){
|
|
6719
|
+
currentShow = currentShow.substring(0, currentShow.lastIndexOf(item.afterText));
|
|
6720
|
+
}
|
|
6721
|
+
if(item.beforeText.length > 0 || item.afterText.length > 0){
|
|
6722
|
+
console.log(currentShow);
|
|
6723
|
+
}
|
|
6427
6724
|
*/
|
|
6428
|
-
|
|
6725
|
+
// v3.16.5 针对gitee 的 readme 接入优化
|
|
6726
|
+
if(typeof(item.nodes[index].node) == 'undefined'){
|
|
6727
|
+
continue;
|
|
6429
6728
|
}
|
|
6729
|
+
|
|
6730
|
+
var attribute = typeof(item.nodes[index].node.attribute) == 'undefined' ? null:item.nodes[index].node.attribute;
|
|
6731
|
+
var analyse = translate.element.nodeAnalyse.analyse(item.nodes[index].node, '', '', attribute);
|
|
6732
|
+
translate.element.nodeAnalyse.analyse(item.nodes[index].node, analyse.text, item.original, attribute);
|
|
6430
6733
|
}
|
|
6431
6734
|
}
|
|
6432
6735
|
}
|
|
6433
6736
|
|
|
6737
|
+
|
|
6738
|
+
|
|
6739
|
+
|
|
6434
6740
|
//清除设置storage中的翻译至的语种
|
|
6435
6741
|
translate.storage.set('to', '');
|
|
6436
6742
|
translate.to = null;
|
|
@@ -6554,6 +6860,10 @@ var translate = {
|
|
|
6554
6860
|
return;
|
|
6555
6861
|
}
|
|
6556
6862
|
translate.init_execute = '已进行';
|
|
6863
|
+
|
|
6864
|
+
if(typeof(translate.request.api.init) != 'string' || translate.request.api.init == null || translate.request.api.init.length < 1){
|
|
6865
|
+
return;
|
|
6866
|
+
}
|
|
6557
6867
|
try{
|
|
6558
6868
|
translate.request.send(
|
|
6559
6869
|
translate.request.api.init,
|
|
@@ -6654,6 +6964,35 @@ var translate = {
|
|
|
6654
6964
|
setUITip:function(tip){
|
|
6655
6965
|
translate.progress.api.isTip = tip;
|
|
6656
6966
|
},
|
|
6967
|
+
//移除子元素(无限级别)中的所有 class name 的loading 遮罩
|
|
6968
|
+
//level 层级,数字,比如第一次调用,传入1, 第一次里面产生的第二次调用,这里就是2
|
|
6969
|
+
removeChildClass:function(node, level){
|
|
6970
|
+
|
|
6971
|
+
//判断是否有子元素,判断其两级子元素,是否有加了loading遮罩了
|
|
6972
|
+
var childNodes = node.childNodes;
|
|
6973
|
+
if(childNodes == null || typeof(childNodes) == 'undefined'){
|
|
6974
|
+
|
|
6975
|
+
}else if(childNodes.length > 0){
|
|
6976
|
+
for(var i = 0; i<childNodes.length; i++){
|
|
6977
|
+
translate.progress.api.removeChildClass(childNodes[i], level+1);
|
|
6978
|
+
}
|
|
6979
|
+
}
|
|
6980
|
+
|
|
6981
|
+
if(level == 1){
|
|
6982
|
+
//第一次调用,是不删除本身的class name
|
|
6983
|
+
return;
|
|
6984
|
+
}
|
|
6985
|
+
if(typeof(node) == 'undefined'){
|
|
6986
|
+
return;
|
|
6987
|
+
}
|
|
6988
|
+
if(typeof(node.className) != 'string'){
|
|
6989
|
+
return;
|
|
6990
|
+
}
|
|
6991
|
+
if(node.className.indexOf('translate_api_in_progress') < -1){
|
|
6992
|
+
return;
|
|
6993
|
+
}
|
|
6994
|
+
node.className = node.className.replace(/translate_api_in_progress/g, '');
|
|
6995
|
+
},
|
|
6657
6996
|
startUITip:function(){
|
|
6658
6997
|
// 创建一个 style 元素
|
|
6659
6998
|
const style = document.createElement('style');
|
|
@@ -6665,49 +7004,67 @@ var translate = {
|
|
|
6665
7004
|
|
|
6666
7005
|
if(translate.progress.api.isTip){
|
|
6667
7006
|
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
|
-
nodeParent.className = ' translate_api_in_progress';
|
|
6693
|
-
}else{
|
|
6694
|
-
//这个元素本身有class了,那就追加
|
|
6695
|
-
if(nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
6696
|
-
continue;
|
|
6697
|
-
}
|
|
7007
|
+
|
|
7008
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
7009
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
7010
|
+
continue;
|
|
7011
|
+
}
|
|
7012
|
+
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
7013
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
7014
|
+
continue;
|
|
7015
|
+
}
|
|
7016
|
+
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
7017
|
+
|
|
7018
|
+
if(typeof(node) == 'undefined' || typeof(node.parentNode) == 'undefined'){
|
|
7019
|
+
continue;
|
|
7020
|
+
}
|
|
7021
|
+
var nodeParent = node.parentNode;
|
|
7022
|
+
if(nodeParent == null){
|
|
7023
|
+
continue;
|
|
7024
|
+
}
|
|
7025
|
+
/* 这里先不考虑多隐藏的问题,只要符合的都隐藏,宁愿吧一些不需要隐藏的也会跟着一起隐藏
|
|
7026
|
+
if(nodeParent.childNodes.length != 1){
|
|
7027
|
+
//这个文本节点所在的元素里,不止有这一个文本元素,还有别的文本元素
|
|
7028
|
+
continue;
|
|
7029
|
+
}
|
|
7030
|
+
*/
|
|
6698
7031
|
|
|
6699
|
-
|
|
7032
|
+
|
|
7033
|
+
//判断其在上一层的父级是否已经加了,如果父级加了,那作为子集就不需要在加了,免得出现两个重合的 loading 遮罩
|
|
7034
|
+
var nodeParentParent = node.parentNode;
|
|
7035
|
+
if(nodeParentParent != null && typeof(nodeParentParent.className) != 'undefined' && nodeParentParent.className != null && nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
7036
|
+
//父有了,那么子就不需要再加了
|
|
7037
|
+
continue;
|
|
7038
|
+
}
|
|
7039
|
+
//判断是否有子元素,判断其两级子元素,是否有加了loading遮罩了
|
|
7040
|
+
translate.progress.api.removeChildClass(nodeParent, 1);
|
|
7041
|
+
|
|
7042
|
+
|
|
7043
|
+
if(typeof(nodeParent.className) == 'undefined' || nodeParent.className == null || nodeParent.className == ''){
|
|
7044
|
+
nodeParent.className = ' translate_api_in_progress';
|
|
7045
|
+
}else{
|
|
7046
|
+
//这个元素本身有class了,那就追加
|
|
7047
|
+
if(nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
7048
|
+
continue;
|
|
6700
7049
|
}
|
|
7050
|
+
nodeParent.className = nodeParent.className+' translate_api_in_progress';
|
|
7051
|
+
}
|
|
6701
7052
|
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
7053
|
+
}
|
|
7054
|
+
}
|
|
7055
|
+
|
|
6705
7056
|
});
|
|
6706
7057
|
translate.listener.execute.renderFinishByApi.push(function(uuid, from, to){
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
7058
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
7059
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
7060
|
+
continue;
|
|
7061
|
+
}
|
|
7062
|
+
|
|
6710
7063
|
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
7064
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
7065
|
+
continue;
|
|
7066
|
+
}
|
|
7067
|
+
|
|
6711
7068
|
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
6712
7069
|
var nodeParent = node.parentNode;
|
|
6713
7070
|
if(nodeParent == null){
|
|
@@ -6729,6 +7086,7 @@ var translate = {
|
|
|
6729
7086
|
continue;
|
|
6730
7087
|
}
|
|
6731
7088
|
|
|
7089
|
+
|
|
6732
7090
|
nodeParent.className = parentClassName.replace(/translate_api_in_progress/g, '');
|
|
6733
7091
|
//nodeParent.className = parentClassName.replace(/loading/g, '');
|
|
6734
7092
|
}
|
|
@@ -7313,9 +7671,278 @@ var translate = {
|
|
|
7313
7671
|
_requestContext: null
|
|
7314
7672
|
|
|
7315
7673
|
}
|
|
7316
|
-
}
|
|
7674
|
+
},
|
|
7317
7675
|
|
|
7318
7676
|
/*js translate.network end*/
|
|
7677
|
+
|
|
7678
|
+
|
|
7679
|
+
/*js translate.visual start*/
|
|
7680
|
+
/*
|
|
7681
|
+
人眼所看到的纯视觉层的处理
|
|
7682
|
+
*/
|
|
7683
|
+
visual: {
|
|
7684
|
+
/**
|
|
7685
|
+
* 获取一组节点的视觉矩形信息
|
|
7686
|
+
* @param {Node[]} nodes - 节点数组,格式如
|
|
7687
|
+
* [node1,node2,node3]
|
|
7688
|
+
* @returns {Object[]} - 矩形信息数组,与输入节点一一对应
|
|
7689
|
+
*/
|
|
7690
|
+
getRects:function(nodes){
|
|
7691
|
+
return nodes.map(node => {
|
|
7692
|
+
if (!node) return null;
|
|
7693
|
+
|
|
7694
|
+
let rect;
|
|
7695
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
7696
|
+
const range = document.createRange();
|
|
7697
|
+
range.selectNodeContents(node);
|
|
7698
|
+
const rects = range.getClientRects();
|
|
7699
|
+
//console.log(rect);
|
|
7700
|
+
rect = rects.length > 0 ? rects[0] : null;
|
|
7701
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
7702
|
+
rect = node.getBoundingClientRect();
|
|
7703
|
+
}
|
|
7704
|
+
|
|
7705
|
+
return rect ? {
|
|
7706
|
+
node,
|
|
7707
|
+
left: rect.left,
|
|
7708
|
+
top: rect.top,
|
|
7709
|
+
right: rect.right,
|
|
7710
|
+
bottom: rect.bottom,
|
|
7711
|
+
width: rect.width,
|
|
7712
|
+
height: rect.height
|
|
7713
|
+
} : null;
|
|
7714
|
+
});
|
|
7715
|
+
},
|
|
7716
|
+
/*
|
|
7717
|
+
对一组坐标进行排序
|
|
7718
|
+
按开始坐标从左到右、从上到下排序
|
|
7719
|
+
@param rects translate.visual.getRects获取到的坐标数据
|
|
7720
|
+
*/
|
|
7721
|
+
coordinateSort:function(rects){
|
|
7722
|
+
// 按从左到右、从上到下排序
|
|
7723
|
+
const sortedRects = rects
|
|
7724
|
+
.filter(rect => rect !== null)
|
|
7725
|
+
.sort((a, b) => {
|
|
7726
|
+
if (Math.abs(a.top - b.top) < 5) { // 同一行
|
|
7727
|
+
return a.left - b.left;
|
|
7728
|
+
}
|
|
7729
|
+
return a.top - b.top;
|
|
7730
|
+
});
|
|
7731
|
+
return sortedRects;
|
|
7732
|
+
},
|
|
7733
|
+
/**
|
|
7734
|
+
* 查找左右紧邻的矩形对
|
|
7735
|
+
* @param rects translate.visual.getRects获取到的坐标数据
|
|
7736
|
+
* @returns {Array<{before: Object, after: Object}>} - 左右紧邻的矩形对数组
|
|
7737
|
+
*/
|
|
7738
|
+
afterAdjacent:function(rects){
|
|
7739
|
+
var sortedRects = translate.visual.coordinateSort(rects);
|
|
7740
|
+
|
|
7741
|
+
const adjacentPairs = [];
|
|
7742
|
+
const lineGroups = translate.visual.groupRectsByLine(sortedRects);
|
|
7743
|
+
|
|
7744
|
+
// 检查每行中的所有紧邻元素对
|
|
7745
|
+
lineGroups.forEach(line => {
|
|
7746
|
+
for (let i = 0; i < line.length; i++) {
|
|
7747
|
+
for (let j = i + 1; j < line.length; j++) {
|
|
7748
|
+
const prev = line[i];
|
|
7749
|
+
const next = line[j];
|
|
7750
|
+
|
|
7751
|
+
// 如果后续元素与当前元素不紧邻,则后续其他元素也不可能紧邻
|
|
7752
|
+
if (!translate.visual.areHorizontallyAdjacent(prev, next)) {
|
|
7753
|
+
break;
|
|
7754
|
+
}
|
|
7755
|
+
|
|
7756
|
+
adjacentPairs.push({ before: prev, after: next });
|
|
7757
|
+
}
|
|
7758
|
+
}
|
|
7759
|
+
});
|
|
7760
|
+
|
|
7761
|
+
return adjacentPairs;
|
|
7762
|
+
},
|
|
7763
|
+
/**
|
|
7764
|
+
* 按行分组矩形
|
|
7765
|
+
* @param rects - 排序后的矩形数组 @param rects translate.visual.coordinateSort 获取到的坐标数据
|
|
7766
|
+
* @returns {Object[][]} - 按行分组的矩形
|
|
7767
|
+
*/
|
|
7768
|
+
groupRectsByLine:function(rects){
|
|
7769
|
+
const lineGroups = [];
|
|
7770
|
+
let currentLine = [];
|
|
7771
|
+
|
|
7772
|
+
rects.forEach(rect => {
|
|
7773
|
+
if (currentLine.length === 0) {
|
|
7774
|
+
currentLine.push(rect);
|
|
7775
|
+
} else {
|
|
7776
|
+
const lastRect = currentLine[currentLine.length - 1];
|
|
7777
|
+
// 如果在同一行,则添加到当前行
|
|
7778
|
+
if (Math.abs(rect.top - lastRect.top) < 5) {
|
|
7779
|
+
currentLine.push(rect);
|
|
7780
|
+
} else {
|
|
7781
|
+
// 否则开始新的一行
|
|
7782
|
+
lineGroups.push(currentLine);
|
|
7783
|
+
currentLine = [rect];
|
|
7784
|
+
}
|
|
7785
|
+
}
|
|
7786
|
+
});
|
|
7787
|
+
|
|
7788
|
+
// 添加最后一行
|
|
7789
|
+
if (currentLine.length > 0) {
|
|
7790
|
+
lineGroups.push(currentLine);
|
|
7791
|
+
}
|
|
7792
|
+
|
|
7793
|
+
return lineGroups;
|
|
7794
|
+
},
|
|
7795
|
+
/**
|
|
7796
|
+
* 判断两个矩形是否水平紧邻
|
|
7797
|
+
* @param {Object} rect1 - 第一个矩形
|
|
7798
|
+
* @param {Object} rect2 - 第二个矩形
|
|
7799
|
+
* @returns {boolean} - 是否水平紧邻
|
|
7800
|
+
*/
|
|
7801
|
+
areHorizontallyAdjacent:function(rect1, rect2){
|
|
7802
|
+
// 检查垂直方向是否有重叠(在同一行)
|
|
7803
|
+
const verticalOverlap = Math.min(rect1.bottom, rect2.bottom) - Math.max(rect1.top, rect2.top);
|
|
7804
|
+
|
|
7805
|
+
// 检查水平间距是否在阈值范围内
|
|
7806
|
+
const horizontalGap = rect2.left - rect1.right;
|
|
7807
|
+
|
|
7808
|
+
return verticalOverlap > 0 && Math.abs(horizontalGap) < 1; // 允许1px误差
|
|
7809
|
+
},
|
|
7810
|
+
/**
|
|
7811
|
+
* 找到需要在节点文本末尾添加空格的节点
|
|
7812
|
+
* @param {Array<{before: Object, after: Object}>} adjacentPairs - 左右紧邻的矩形对数组
|
|
7813
|
+
* @returns {Node[]} - 需要添加空格的节点数组
|
|
7814
|
+
*/
|
|
7815
|
+
afterAddSpace:function(adjacentPairs){
|
|
7816
|
+
|
|
7817
|
+
const nodesToAddSpace = [];
|
|
7818
|
+
|
|
7819
|
+
adjacentPairs.forEach(pair => {
|
|
7820
|
+
const { before, after } = pair;
|
|
7821
|
+
const beforeNode = before.node;
|
|
7822
|
+
const afterNode = after.node;
|
|
7823
|
+
|
|
7824
|
+
// 获取计算样式
|
|
7825
|
+
const beforeStyle = window.getComputedStyle(
|
|
7826
|
+
beforeNode.nodeType === Node.TEXT_NODE ? beforeNode.parentElement : beforeNode
|
|
7827
|
+
);
|
|
7828
|
+
|
|
7829
|
+
const afterStyle = window.getComputedStyle(
|
|
7830
|
+
afterNode.nodeType === Node.TEXT_NODE ? afterNode.parentElement : afterNode
|
|
7831
|
+
);
|
|
7832
|
+
|
|
7833
|
+
// 检查间距是否由CSS属性引起
|
|
7834
|
+
const hasRightSpacing = parseFloat(beforeStyle.marginRight) > 0 ||
|
|
7835
|
+
parseFloat(beforeStyle.paddingRight) > 0;
|
|
7836
|
+
|
|
7837
|
+
const hasLeftSpacing = parseFloat(afterStyle.marginLeft) > 0 ||
|
|
7838
|
+
parseFloat(afterStyle.paddingLeft) > 0;
|
|
7839
|
+
|
|
7840
|
+
// 如果没有明确的间距,且后一个节点的开始非空白符,则需要添加空格
|
|
7841
|
+
if (!hasRightSpacing && !hasLeftSpacing) {
|
|
7842
|
+
//判断 before 节点的最后一个字符是否是空白符
|
|
7843
|
+
if(typeof(beforeNode.textContent) == 'string' && typeof(afterNode.textContent) == 'string'){
|
|
7844
|
+
if(/\s$/.test(beforeNode.textContent)){
|
|
7845
|
+
//before 最后一个字符是空格,则不需要追加空格符了
|
|
7846
|
+
}else if(/^\s/.test(afterNode.textContent)){
|
|
7847
|
+
//after 节点的开始第一个字符是空白符,那么也不需要追加空格符了
|
|
7848
|
+
}else{
|
|
7849
|
+
//这里就需要对 beforeNode 追加空格了
|
|
7850
|
+
nodesToAddSpace.push(beforeNode);
|
|
7851
|
+
}
|
|
7852
|
+
}
|
|
7853
|
+
}
|
|
7854
|
+
});
|
|
7855
|
+
|
|
7856
|
+
return nodesToAddSpace;
|
|
7857
|
+
},
|
|
7858
|
+
/**
|
|
7859
|
+
* 主函数:处理翻译后的空格调整
|
|
7860
|
+
* @param {Node[]} nodes - 节点数组
|
|
7861
|
+
*/
|
|
7862
|
+
adjustTranslationSpaces:function(nodes){
|
|
7863
|
+
|
|
7864
|
+
//先判断当前要显示的语种,是否需要用空格进行间隔单词,如果本身不需要空格间隔,像是中文,那就根本不需要去计算视觉距离
|
|
7865
|
+
if(!translate.language.wordBlankConnector(translate.to)){
|
|
7866
|
+
return;
|
|
7867
|
+
}
|
|
7868
|
+
|
|
7869
|
+
//var startTime = Date.now();
|
|
7870
|
+
// 1. 获取节点视觉矩形
|
|
7871
|
+
const rects = translate.visual.getRects(nodes);
|
|
7872
|
+
//console.log('rects:');
|
|
7873
|
+
//console.log(rects);
|
|
7874
|
+
|
|
7875
|
+
// 2. 查找左右紧邻的矩形对
|
|
7876
|
+
const adjacentPairs = translate.visual.afterAdjacent(rects);
|
|
7877
|
+
//console.log('adjacentPairs:');
|
|
7878
|
+
//console.log(adjacentPairs);
|
|
7879
|
+
|
|
7880
|
+
// 3. 确定需要添加空格的节点
|
|
7881
|
+
const nodesToAddSpace = translate.visual.afterAddSpace(adjacentPairs);
|
|
7882
|
+
//console.log('nodesToAddSpace:');
|
|
7883
|
+
//console.log(nodesToAddSpace);
|
|
7884
|
+
|
|
7885
|
+
// 4. 添加非断行空格
|
|
7886
|
+
nodesToAddSpace.forEach(node => {
|
|
7887
|
+
// 确保只修改文本内容,不影响HTML结构
|
|
7888
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
7889
|
+
node.textContent = node.textContent + '\u00A0';
|
|
7890
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
7891
|
+
// 如果是元素节点,修改其最后一个子节点(假设是文本节点)
|
|
7892
|
+
const lastChild = node.lastChild;
|
|
7893
|
+
if (lastChild && lastChild.nodeType === Node.TEXT_NODE) {
|
|
7894
|
+
lastChild.textContent = lastChild.textContent + '\u00A0';
|
|
7895
|
+
}
|
|
7896
|
+
}
|
|
7897
|
+
});
|
|
7898
|
+
//var endTime = Date.now();
|
|
7899
|
+
//console.log('visual recognition time: '+(endTime-startTime)+'ms');
|
|
7900
|
+
},
|
|
7901
|
+
/*
|
|
7902
|
+
通过 translate.nodeQueue[uuid] 中的uuid,来传入这个 translate.nodeQueue[uuid] 中所包含涉及到的所有node (除特殊字符外 ,也就是 translate.nodeQueue[uuid].list 下 特殊字符那一类是不会使用的)
|
|
7903
|
+
*/
|
|
7904
|
+
adjustTranslationSpacesByNodequeueUuid:function(uuid){
|
|
7905
|
+
var nodes = [];
|
|
7906
|
+
for(var from in translate.nodeQueue[uuid].list){
|
|
7907
|
+
if (!translate.nodeQueue[uuid].list.hasOwnProperty(from)) {
|
|
7908
|
+
continue;
|
|
7909
|
+
}
|
|
7910
|
+
if(from.length < 1){
|
|
7911
|
+
continue;
|
|
7912
|
+
}
|
|
7913
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
7914
|
+
if (!translate.nodeQueue[uuid].list[from].hasOwnProperty(hash)) {
|
|
7915
|
+
continue;
|
|
7916
|
+
}
|
|
7917
|
+
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
7918
|
+
if (!translate.nodeQueue[uuid].list[from][hash].nodes.hasOwnProperty(nodeindex)) {
|
|
7919
|
+
continue;
|
|
7920
|
+
}
|
|
7921
|
+
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
7922
|
+
nodes.push(node);
|
|
7923
|
+
}
|
|
7924
|
+
}
|
|
7925
|
+
}
|
|
7926
|
+
translate.visual.adjustTranslationSpaces(nodes);
|
|
7927
|
+
},
|
|
7928
|
+
/*
|
|
7929
|
+
通过 translate.nodeQueue 中最后一次执行的 uuid,来获取这个 translate.nodeQueue[uuid] 中所包含涉及到的所有node (除特殊字符外 ,也就是 translate.nodeQueue[uuid].list 下 特殊字符那一类是不会使用的)
|
|
7930
|
+
*/
|
|
7931
|
+
adjustTranslationSpacesByLastNodequeueUuid:function(uuid){
|
|
7932
|
+
var uuid = '';
|
|
7933
|
+
for(var uuid_index in translate.nodeQueue){
|
|
7934
|
+
uuid = uuid_index;
|
|
7935
|
+
break;
|
|
7936
|
+
}
|
|
7937
|
+
if(typeof(uuid) == 'string' && uuid.length > 1){
|
|
7938
|
+
translate.visual.adjustTranslationSpacesByNodequeueUuid(uuid);
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
|
|
7942
|
+
|
|
7943
|
+
|
|
7944
|
+
}
|
|
7945
|
+
/*js translate.visual end*/
|
|
7319
7946
|
|
|
7320
7947
|
}
|
|
7321
7948
|
/*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18n-jsautotranslate",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "Two lines of js realize automatic html translation. No need to change the page, no language configuration file, no API key, SEO friendly!",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|