i18n-jsautotranslate 3.18.76 → 3.18.84

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 CHANGED
@@ -17,12 +17,10 @@
17
17
  </h4>
18
18
 
19
19
  # 特性说明
20
- * **使用极其简单。** 直接加入几行 JavaScript 代码即可让其拥有上百种语言切换能力。
21
- * **不增加工作量。** 无需改造页面本身植入大量垃圾代码变得臃肿,也不需要配置各种语种的语言文件,因为它会直接扫描你的DOM自动识别并翻译显示,它不需要你到某某网站登录去申请什么key,它是开源开放的,拿来就能用。
22
- * **极其灵活扩展。** 您可指定它[只翻译某些指定区域的元素](http://translate.zvo.cn/4063.html)、[自定义切换语言方式及美化](http://translate.zvo.cn/4056.html)、[某些id、class、tag不被翻译](https://translate.zvo.cn/4061.html)、[自定义翻译术语](https://translate.zvo.cn/4070.html) ...... 只要你想的,它都能做到。做不到的,你找我我来让它做到!
23
- * **自动切换语种。** [自动根据用户的语言喜好及所在的国家切换到这个语种进行浏览](http://translate.zvo.cn/4065.html)
24
- * **极速翻译能力。** [内置三层缓存、预加载机制,毫秒级瞬间翻译的能力。它并不是你理解的大模型蜗牛似的逐个字往外出的那样](http://translate.zvo.cn/4026.html)
25
- * **永久开源免费。** 采用MIT开源协议,您可永久免费使用。[另外你可以用它来做某些系统的三方插件直接售卖盈利](http://translate.zvo.cn/4036.html)
20
+ * **使用极其简单。** 直接加入几行 JavaScript 代码即可让其拥有上百种语言切换能力,不增加工作量,无需改造页面本身植入大量垃圾代码变得臃肿,也不需要配置各种语种的语言文件,因为它会直接扫描你的DOM自动识别并翻译显示,它不需要你到某某网站登录去申请什么key,它是开源开放的,拿来就能用。
21
+ * **极其灵活扩展。** 您可指定它[只翻译某些指定区域的元素](http://translate.zvo.cn/4063.html)、[自定义切换语言方式及美化](http://translate.zvo.cn/4056.html)、[某些id、class、tag不被翻译](https://translate.zvo.cn/4061.html)、[自定义翻译术语](https://translate.zvo.cn/4070.html)、[自动根据用户的语言喜好及所在的国家切换到这个语种进行浏览](http://translate.zvo.cn/4065.html)、 ...... 只要你想的,它都能做到。做不到的,你找我我来让它做到!
22
+ * **极速翻译能力。** [采用多线程加速,内置三层缓存、预加载机制、文本预处理清洗等,提供毫秒级瞬间翻译的能力。](http://translate.zvo.cn/4026.html)
23
+ * **永久开源免费。** 采用MIT开源协议,您可永久免费使用。[另外你可以用它来做某些系统的三方插件、浏览器插件...等等,进行售卖盈利](http://translate.zvo.cn/4036.html)
26
24
  * **搜索引擎友好。** 完全不影响你本身网站搜索引擎的收录。爬虫所爬取的网页源代码,它不会对其进行任何改动,你可完全放心。
27
25
  * **支持私有部署。** [在某些政府机关及大集团内部项目中,对数据隐私及安全保密有强要求场景、或者完全不通外网的场景,可以自行私有部署翻译API服务](http://translate.zvo.cn/391129.html)
28
26
  * **全球网络节点。** 美洲、亚洲、欧洲 ... 都有网络节点,它能自动适配最快节点,每间隔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.18.76.20251020',
17
+ version: '3.18.84.20251024',
18
18
  // AUTO_VERSION_END
19
19
  /*
20
20
  当前使用的版本,默认使用v2. 可使用 setUseVersion2();
@@ -234,14 +234,14 @@ var translate = {
234
234
  //从服务器加载支持的语言库
235
235
  if(typeof(translate.request.api.language) == 'string' && translate.request.api.language.length > 0){
236
236
  //从接口加载语种
237
- translate.request.post(translate.request.api.language, {}, function(data){
238
- if(data.result == 0){
239
- translate.log('load language list error : '+data.info);
237
+ translate.request.post(translate.request.api.language, {}, function(responseData, requestData){
238
+ if(responseData.result == 0){
239
+ translate.log('load language list error : '+responseData.info);
240
240
  return;
241
241
  }
242
242
  //console.log(data.list);
243
- translate.request.api.language = data.list; //进行缓存,下一次切换语言渲染的时候直接从缓存取,就不用在通过网络加载了
244
- translate.selectLanguageTag.customUI(translate.selectLanguageTag.customLanguagesHandle(data.list));
243
+ translate.request.api.language = responseData.list; //进行缓存,下一次切换语言渲染的时候直接从缓存取,就不用在通过网络加载了
244
+ translate.selectLanguageTag.customUI(translate.selectLanguageTag.customLanguagesHandle(responseData.list));
245
245
  }, null);
246
246
  }else if(typeof(translate.request.api.language) == 'object'){
247
247
  //无网络环境下,自定义显示语种
@@ -1478,6 +1478,7 @@ var translate = {
1478
1478
  }else{
1479
1479
  //判断是否是 translate.element.tagAttribute 自定义翻译属性的
1480
1480
  var divTagAttribute = translate.element.tagAttribute[mutation.target.nodeName.toLowerCase()];
1481
+ //console.log('divTagAttribute:'+divTagAttribute);
1481
1482
  if(typeof(divTagAttribute) !== 'undefined' && divTagAttribute.attribute.indexOf(mutation.attributeName) > -1 && divTagAttribute.condition(mutation.target)){
1482
1483
  //是自定义翻译这个属性的,以及判定是否达到翻译条件
1483
1484
  //条件满足,允许翻译
@@ -1651,12 +1652,15 @@ var translate = {
1651
1652
  constructor(){
1652
1653
  /*
1653
1654
  * 任务列表
1654
- * 一维数组 [hash] = tasks; tasks 是多个task的数组集合
1655
- * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换
1656
- * 三维数组 task['originalText'] task['resultText'] 存放要替换的字符串
1657
- task['attribute'] 存放要替换的属性,比如 a标签的title属性。 如果是直接替换node.nodeValue ,那这个没有
1655
+ * map
1656
+ * key: node
1657
+ * value: [task,task,...] 是多个task的数组集合,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换
1658
+ * 每个 task:
1659
+ task['originalText']
1660
+ task['resultText'] 存放要替换的字符串
1661
+ task['attribute'] 存放要替换的属性,比如 a标签的title属性。 如果是直接替换node.nodeValue ,那这个没有
1658
1662
  */
1659
- this.taskQueue = [];
1663
+ this.taskQueue = new Map();
1660
1664
 
1661
1665
  /*
1662
1666
  * 要进行翻译的node元素,
@@ -1674,13 +1678,14 @@ var translate = {
1674
1678
  * attribute: 要替换的是哪个属性,比如 a标签的title属性,这里便是传入title。如果不是替换属性,这里不用传入,或者传入null
1675
1679
  */
1676
1680
  add(node, originalText, resultText, attribute){
1681
+ //console.log('renderTask.add : originalText:'+originalText+', resultText:'+resultText+', attribute:'+attribute+', node:');
1682
+ //console.log(node);
1677
1683
  var nodeAnaly = translate.element.nodeAnalyse.get(node, attribute); //node解析
1678
1684
  //var hash = translate.util.hash(translate.element.getTextByNode(node)); //node中内容的hash
1679
1685
  var hash = translate.util.hash(nodeAnaly['text']);
1680
1686
  //console.log('--------------'+hash);
1681
1687
  //console.log(nodeAnaly);
1682
- //console.log(node);
1683
- //console.log('originalText:'+originalText+', resultText:'+resultText+', attribute:'+attribute);
1688
+
1684
1689
  /****** 加入翻译的元素队列 */
1685
1690
  if(typeof(this.nodes[hash]) == 'undefined'){
1686
1691
  this.nodes[hash] = new Array();
@@ -1689,7 +1694,8 @@ var translate = {
1689
1694
  //console.log(node)
1690
1695
 
1691
1696
  /****** 加入翻译的任务队列 */
1692
- var tasks = this.taskQueue[hash];
1697
+ //var tasks = this.taskQueue[hash];
1698
+ var tasks = this.taskQueue.get(node);
1693
1699
  if(tasks == null || typeof(tasks) == 'undefined'){
1694
1700
  //console.log(node.nodeValue);
1695
1701
  tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换
@@ -1720,18 +1726,19 @@ var translate = {
1720
1726
 
1721
1727
  //console.log(task);
1722
1728
  tasks.push(task);
1723
- this.taskQueue[hash] = tasks;
1729
+ //this.taskQueue[hash] = tasks;
1730
+ this.taskQueue.set(node, tasks);
1724
1731
  /****** 加入翻译的任务队列 end */
1725
1732
  }
1726
1733
  //进行替换渲染任务,对页面进行渲染替换翻译
1727
1734
  execute(){
1728
1735
  //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到
1729
- for(var hash in this.taskQueue){
1730
- if (!this.taskQueue.hasOwnProperty(hash)) {
1736
+ //for(var hash in this.taskQueue){
1737
+ for (let node of this.taskQueue.keys()) {
1738
+ var tasks = this.taskQueue.get(node);
1739
+ if (tasks == null) {
1731
1740
  continue;
1732
1741
  }
1733
-
1734
- var tasks = this.taskQueue[hash];
1735
1742
  if(typeof(tasks) == 'function'){
1736
1743
  //进行异常的预处理调出
1737
1744
  continue;
@@ -1740,7 +1747,8 @@ var translate = {
1740
1747
  //进行排序,将原字符串长的放前面,避免造成有部分不翻译的情况(bug是先翻译了短的,导致长的被打断而无法进行适配)
1741
1748
  tasks.sort((a, b) => b.originalText.length - a.originalText.length);
1742
1749
 
1743
- this.taskQueue[hash] = tasks;
1750
+ //this.taskQueue[hash] = tasks;
1751
+ this.taskQueue.set(node, tasks);
1744
1752
  }
1745
1753
 
1746
1754
  //console.log('===========task=========');
@@ -1757,10 +1765,21 @@ var translate = {
1757
1765
  continue;
1758
1766
  }
1759
1767
 
1760
- var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务
1768
+ //var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务
1761
1769
  //var tagName = this.nodes[hash][0].nodeName; //以下节点的tag name
1762
1770
  //console.log(tasks);
1763
1771
  for(var node_index = 0; node_index < this.nodes[hash].length; node_index++){
1772
+ //当前翻译的node
1773
+ var node = this.nodes[hash][node_index];
1774
+
1775
+ //取出当前node元素对应的替换任务
1776
+ var tasks = this.taskQueue.get(node);
1777
+ //console.log(tasks);
1778
+ if (tasks == null) {
1779
+ translate.log('WARNING : renderTask.execute 中,this.taskQueue.get(node) == null ,理论上要进行替换任务,就应该会有内容的,数据在理论上出现异常');
1780
+ continue;
1781
+ }
1782
+
1764
1783
  //对这个node元素进行替换翻译字符
1765
1784
  for(var task_index=0; task_index<tasks.length; task_index++){
1766
1785
  var task = tasks[task_index];
@@ -1795,13 +1814,22 @@ var translate = {
1795
1814
 
1796
1815
  // translate.node 记录
1797
1816
 
1798
- var translateNode; //当前操作的,要记录入 translate.node 中的,进行翻译的node
1817
+ var translateNode = null; //当前操作的,要记录入 translate.node 中的,进行翻译的node
1799
1818
  var translateNode_attribute = ''; //当前操作的是node中的哪个attribute,如果没有是node本身则是空字符串
1800
1819
  if(typeof(task['attribute']) === 'string' && task['attribute'].length > 0){
1801
1820
  //当前渲染任务是针对的元素的某个属性,这是要取出这个元素的具体属性,作为一个目的 node 来进行加入 translate.node
1802
- //是操作的元素的某个属性
1803
- translateNode = this.nodes[hash][node_index].getAttributeNode(task['attribute']);
1804
- translateNode_attribute = task['attribute'];
1821
+ //是操作的元素的某个属性,这时要判断 是否是 input、textarea 的value属性
1822
+ if(task['attribute'] === 'value'){
1823
+ var nodeNameLowerCase = translate.element.getNodeName(this.nodes[hash][node_index]).toLowerCase();
1824
+ if((nodeNameLowerCase === 'input' || nodeNameLowerCase === 'textarea')){
1825
+ translateNode = this.nodes[hash][node_index];
1826
+ translateNode_attribute = 'value';
1827
+ }
1828
+ }
1829
+ if(translateNode === null){
1830
+ translateNode = this.nodes[hash][node_index].getAttributeNode(task['attribute']);
1831
+ translateNode_attribute = task['attribute'];
1832
+ }
1805
1833
  }else{
1806
1834
  //操作的就是node本身
1807
1835
  translateNode = this.nodes[hash][node_index];
@@ -1817,8 +1845,9 @@ var translate = {
1817
1845
  }
1818
1846
 
1819
1847
  //渲染页面进行翻译显示
1820
- //console.log(task.originalText+' ('+task['attribute']+') --> ' + task.resultText);
1821
- var analyseSet = translate.element.nodeAnalyse.set(this.nodes[hash][task_index], task.originalText, task.resultText, task['attribute']);
1848
+ //console.log(task.originalText+' ('+task['attribute']+') --> ' + task.resultText+', node:');
1849
+ //console.log(node);
1850
+ var analyseSet = translate.element.nodeAnalyse.set(node, task.originalText, task.resultText, task['attribute']);
1822
1851
  //console.log(analyseSet);
1823
1852
 
1824
1853
  if(translate.node.data.get(translateNode) != null){
@@ -3127,38 +3156,38 @@ var translate = {
3127
3156
  //text:JSON.stringify(translateTextArray[lang])
3128
3157
  text:encodeURIComponent(JSON.stringify(translateTextArray[lang]))
3129
3158
  };
3130
- translate.request.post(url, data, function(data){
3159
+ translate.request.post(url, data, function(responseData, requestData){
3131
3160
  //console.log(data);
3132
3161
  //console.log(translateTextArray[data.from]);
3133
3162
 
3134
3163
  //针对 giteeai 增加了账户余额、账户是否激活的拍的判定,所以增加了 401 这个参数,凡是账户异常的,参数值是 401~499 之间。所以只要不是1都是失败
3135
- if(data.result != 1){
3136
- if(typeof(translate.translateRequest[uuid]) == 'object' && typeof(translate.translateRequest[uuid][data.from]) == 'object'){
3137
- translate.translateRequest[uuid][data.from]['result'] = 2;
3138
- translate.translateRequest[uuid][data.from].executeFinish = 1; //1是执行完毕
3139
- translate.translateRequest[uuid][data.from].stoptime = Math.floor(Date.now() / 1000);
3164
+ if(responseData.result != 1){
3165
+ if(typeof(translate.translateRequest[uuid]) == 'object' && typeof(translate.translateRequest[uuid][requestData.from]) == 'object'){
3166
+ translate.translateRequest[uuid][requestData.from]['result'] = 2;
3167
+ translate.translateRequest[uuid][requestData.from].executeFinish = 1; //1是执行完毕
3168
+ translate.translateRequest[uuid][requestData.from].stoptime = Math.floor(Date.now() / 1000);
3140
3169
  }else{
3141
- translate.log('WARINNG!!! translate.translateRequest[uuid][data.from] is not object');
3170
+ translate.log('WARINNG!!! translate.translateRequest[uuid][requestData.from] is not object');
3142
3171
  }
3143
3172
 
3144
3173
  //为了兼容 v3.14以前的translate.service 版本,做了判断
3145
3174
  var from = '';
3146
- if(typeof(data.from) != 'undefined' && data.from != null){
3147
- from = data.from;
3175
+ if(typeof(requestData.from) != 'undefined' && requestData.from != null){
3176
+ from = requestData.from;
3148
3177
  }
3149
3178
  var to = '';
3150
- if(typeof(data.to) != 'undefined' && data.to != null){
3151
- to = data.to;
3179
+ if(typeof(requestData.to) != 'undefined' && requestData.to != null){
3180
+ to = requestData.to;
3152
3181
  }else{
3153
3182
  to = translate.to;
3154
3183
  }
3155
- translate.waitingExecute.isAllExecuteFinish(uuid, from, to, 0, data.info);
3184
+ translate.waitingExecute.isAllExecuteFinish(uuid, from, to, 0, responseData.info);
3156
3185
 
3157
3186
 
3158
3187
  translate.log('=======ERROR START=======');
3159
- translate.log(translateTextArray[data.from]);
3188
+ translate.log(translateTextArray[requestData.from]);
3160
3189
  //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from])));
3161
- translate.log('response : '+data.info);
3190
+ translate.log('response : '+responseData.info);
3162
3191
  translate.log('=======ERROR END =======');
3163
3192
  //translate.temp_executeFinishNumber++; //记录执行完的次数
3164
3193
  return;
@@ -3175,11 +3204,11 @@ var translate = {
3175
3204
  //console.log('response:'+uuid);
3176
3205
  let task = new translate.renderTask();
3177
3206
  //遍历 translateHashArray
3178
- for(var i=0; i<translateHashArray[data.from].length; i++){
3207
+ for(var i=0; i<translateHashArray[responseData.from].length; i++){
3179
3208
  //翻译前的语种,如 english
3180
- var lang = data.from;
3209
+ var lang = responseData.from;
3181
3210
  //翻译后的内容
3182
- var text = data.text[i];
3211
+ var text = responseData.text[i];
3183
3212
  //如果text为null,那么这个可能是一次翻译字数太多,为了保持数组长度,拼上的null
3184
3213
  if(text == null){
3185
3214
  continue;
@@ -3187,14 +3216,14 @@ var translate = {
3187
3216
 
3188
3217
  // v3.0.3 添加,避免像是 JavaScript 被错误翻译为 “JavaScript的” ,然后出现了多个句子中都出现了Javascript时,会出现翻译后文本重复的问题
3189
3218
  // 这里就是验证一下,翻译后的文本,是否会完全包含翻以前的文本,如果包含了,那么强制将翻译后的文本赋予翻译前的原始文本(也就是不被翻译)
3190
- if(text.toLowerCase().indexOf(translateTextArray[data.from][i].toLowerCase()) > -1){
3219
+ if(text.toLowerCase().indexOf(translateTextArray[responseData.from][i].toLowerCase()) > -1){
3191
3220
  //发现了,那么强制赋予翻以前内容
3192
- text = translateTextArray[data.from][i];
3221
+ text = translateTextArray[responseData.from][i];
3193
3222
  }
3194
3223
 
3195
3224
 
3196
3225
  //翻译前的hash对应下标
3197
- var hash = translateHashArray[data.from][i];
3226
+ var hash = translateHashArray[responseData.from][i];
3198
3227
  var cacheHash = translate.nodeQueue[uuid]['list'][lang][hash]['cacheHash'];
3199
3228
 
3200
3229
 
@@ -3224,10 +3253,10 @@ var translate = {
3224
3253
  */
3225
3254
 
3226
3255
  //将翻译结果以 key:hash value翻译结果的形式缓存
3227
- translate.storage.set('hash_'+data.to+'_'+cacheHash,text);
3256
+ translate.storage.set('hash_'+responseData.to+'_'+cacheHash,text);
3228
3257
  //如果离线翻译启用了全部提取,那么还要存入离线翻译指定存储
3229
3258
  if(translate.offline.fullExtract.isUse){
3230
- translate.offline.fullExtract.set(hash, originalWord, data.to, text);
3259
+ translate.offline.fullExtract.set(hash, originalWord, responseData.to, text);
3231
3260
  }
3232
3261
  }
3233
3262
  task.execute(); //执行渲染任务
@@ -3237,7 +3266,7 @@ var translate = {
3237
3266
  translate.translateRequest[uuid][lang].executeFinish = 1; //1是执行完毕
3238
3267
  translate.translateRequest[uuid][lang].stoptime = Math.floor(Date.now() / 1000);
3239
3268
  setTimeout(function(){
3240
- translate.waitingExecute.isAllExecuteFinish(uuid, data.from, data.to, 1, '');
3269
+ translate.waitingExecute.isAllExecuteFinish(uuid, responseData.from, responseData.to, 1, '');
3241
3270
  },5);
3242
3271
  }, function(xhr){
3243
3272
  translate.translateRequest[uuid][xhr.data.from].executeFinish = 1; //1是执行完毕
@@ -3307,6 +3336,7 @@ var translate = {
3307
3336
  这是一个map,为了兼容es5,这里设置为null,在 translate.execute 中在进行初始化
3308
3337
 
3309
3338
  key: node ,进行翻译的文本的node, 如果是 div 的 title属性进行的翻译,那这个node是定位在 title 上的node,而不是 div 这个依附的元素
3339
+ 注意,如果是对 input、textarea 的value进行翻译,而 value是通过js赋予的,那么这个value属性的值并不是一个单独的node,所以是为空的,此时要记录的node便是 input、textarea 这个node本身。
3310
3340
  value: 这是一个对像
3311
3341
  其中,key的取值有这几种:
3312
3342
  translate_default_value: 如果当前翻译的是元素本身的值或node节点本身的值(nodeValue),那么这里的key就是固定的 translate_default_value
@@ -3628,6 +3658,7 @@ var translate = {
3628
3658
 
3629
3659
  参数:
3630
3660
  node 当前翻译的node元素
3661
+ 注意,如果是对 input、textarea 的value进行翻译,而 value是通过js赋予的,那么这个value属性的值并不是一个单独的node,所以是为空的,此时要记录的node便是 input、textarea 这个node本身。
3631
3662
  originalText 翻译之前的内容文本
3632
3663
  resultText 翻译之后的内容文本
3633
3664
  attribute 存放要替换的属性,比如 a标签的title属性。 如果是直接替换node.nodeValue ,那这个没有
@@ -3649,6 +3680,7 @@ var translate = {
3649
3680
  返回结果是一个数组。其中:
3650
3681
  ['text']:要进行翻译的text内容文本
3651
3682
  ['node']:要进行翻译的目标node
3683
+ 注意,如果是对 input、textarea 的value进行翻译,而 value是通过js赋予的,那么这个value属性的值并不是一个单独的node,所以是为空的,此时要记录的node便是 input、textarea 这个node本身。
3652
3684
  2. 传入 node、originalText、 resultText
3653
3685
  则是进行翻译之后的渲染显示
3654
3686
 
@@ -3657,7 +3689,8 @@ var translate = {
3657
3689
  返回结果是一个数组,其中:
3658
3690
  resultText: 翻译完成之后的text内容文本。 当使用 translate.element.nodeAnalyse.set 时才会有这个参数返回。 注意,如果返回的是空字符串,那么则是翻译结果进行替换时,并没有成功替换,应该是翻译的过程中,这个node的值被其他js又赋予其他内容了。
3659
3691
  text : 要进行翻译的text内容文本,当使用 translate.element.nodeAnalyse.get 时才会有这个参数的返回
3660
- node: 进行翻译的目标node
3692
+ node: 要进行翻译的目标node
3693
+ 注意,如果是对 input、textarea 的value进行翻译,而 value是通过js赋予的,那么这个value属性的值并不是一个单独的node,所以是为空的,此时要记录的node便是 input、textarea 这个node本身。
3661
3694
  */
3662
3695
  analyse:function(node, originalText, resultText, attribute){
3663
3696
  var result = new Array(); //返回的结果
@@ -3665,13 +3698,15 @@ var translate = {
3665
3698
  result['text'] = '';
3666
3699
 
3667
3700
  var nodename = translate.element.getNodeName(node);
3668
-
3701
+ //console.log('nodeAnalyse.analyse: NodeName:'+nodename+', originalText:'+originalText+', resultText:'+resultText+', attribute:'+attribute+', node:');
3702
+ //console.log(node)
3703
+
3669
3704
  if(attribute != null && typeof(attribute) == 'string' && attribute.length > 0){
3670
3705
  //这个node有属性,替换的是node的属性,而不是nodeValue
3671
3706
 
3672
3707
  var nodeAttributeValue; //这个 attribute 属性的值
3673
- if(nodename == 'INPUT' && attribute.toLowerCase() == 'value'){
3674
- //如果是input 的value属性,那么要直接获取,而非通过 attribute ,不然用户自己输入的通过 attribute 是获取不到的 -- catl 赵阳 提出
3708
+ if((nodename === 'INPUT' || nodename === 'TEXTAREA') && attribute.toLowerCase() == 'value'){
3709
+ //如果是input\textarea 的value属性,那么要直接获取,而非通过 attribute ,不然用户自己输入的通过 attribute 是获取不到的 -- catl 赵阳 提出
3675
3710
 
3676
3711
  nodeAttributeValue = node.value;
3677
3712
  }else{
@@ -3687,7 +3722,7 @@ var translate = {
3687
3722
  var resultShowText = translate.util.textReplace(nodeAttributeValue, originalText, resultText, translate.to);
3688
3723
  translate.element.nodeAnalyse.analyseReplaceBefore_DateToTranslateNode(node, attribute, resultShowText);
3689
3724
 
3690
- if(nodename == 'INPUT' && attribute.toLowerCase() == 'value'){
3725
+ if((nodename === 'INPUT' || nodename === 'TEXTAREA') && attribute.toLowerCase() == 'value'){
3691
3726
  //input 的value 对于用户输入的必须用 .value 操作
3692
3727
  node.value = resultShowText;
3693
3728
  }else{
@@ -3720,6 +3755,8 @@ var translate = {
3720
3755
  return result;
3721
3756
  }
3722
3757
 
3758
+
3759
+
3723
3760
  //正常的node ,typeof 都是 object
3724
3761
 
3725
3762
  /* 这里是通用方法,不应该有限制
@@ -3895,13 +3932,25 @@ var translate = {
3895
3932
  resultShowText: translate.element.nodeAnalyse.analyse 进行设置翻译后的文本渲染时,提前计算好这个node显示的所有文本,然后在赋予 dom,这里是计算好的node要整体显示的文本
3896
3933
  */
3897
3934
  analyseReplaceBefore_DateToTranslateNode:function(node, attribute, resultShowText){
3898
- var translateNode; //当前操作的,要记录入 translate.node 中的,进行翻译的node
3935
+ //console.log('analyseReplaceBefore_DateToTranslateNode: attribute:'+attribute+', resultShowText:'+resultShowText+', node:');
3936
+ //console.log(node);
3937
+
3938
+ var translateNode = null; //当前操作的,要记录入 translate.node 中的,进行翻译的node
3899
3939
  var translateNode_attribute = ''; //当前操作的是node中的哪个attribute,如果没有是node本身则是空字符串
3900
3940
 
3901
3941
  if(typeof(attribute) === 'string' && attribute.length > 0){
3902
- //是操作的元素的某个属性
3903
- translateNode = node.getAttributeNode(attribute);
3904
- translateNode_attribute = attribute;
3942
+ //是操作的元素的某个属性,这时要判断 是否是 input、textarea 的value属性
3943
+ if(attribute !== null && attribute === 'value'){
3944
+ var nodeNameLowerCase = translate.element.getNodeName(node).toLowerCase();
3945
+ if((nodeNameLowerCase === 'input' || nodeNameLowerCase === 'textarea')){
3946
+ translateNode = node;
3947
+ translateNode_attribute = 'value';
3948
+ }
3949
+ }
3950
+ if(translateNode === null){
3951
+ translateNode = node.getAttributeNode(attribute);
3952
+ translateNode_attribute = attribute;
3953
+ }
3905
3954
  }else{
3906
3955
  //操作的就是node本身
3907
3956
  translateNode = node;
@@ -3941,7 +3990,10 @@ var translate = {
3941
3990
  }
3942
3991
  }
3943
3992
  },
3944
- //向下遍历node
3993
+ /*
3994
+ 向下遍历node
3995
+ 其中如果使用了自定义 textarea 、input 的 value 属性,则认为是 node 本身进行挂钩,而非其 value 值(value值并不是个node)
3996
+ */
3945
3997
  whileNodes:function(uuid, node){
3946
3998
  if(node == null || typeof(node) == 'undefined'){
3947
3999
  return;
@@ -3977,6 +4029,7 @@ var translate = {
3977
4029
  if(typeof(translate.element.tagAttribute[nodeNameLowerCase]) != 'undefined'){
3978
4030
  //console.log('find:'+nodeNameLowerCase);
3979
4031
  //console.log(translate.element.tagAttribute[nodeNameLowerCase]);
4032
+ //console.log(translate.element.tagAttribute[nodeNameLowerCase].attribute);
3980
4033
 
3981
4034
  for(var attributeName_index in translate.element.tagAttribute[nodeNameLowerCase].attribute){
3982
4035
  if (!translate.element.tagAttribute[nodeNameLowerCase].attribute.hasOwnProperty(attributeName_index)) {
@@ -3990,11 +4043,13 @@ var translate = {
3990
4043
  //console.log(attributeName);
3991
4044
  //console.log(node.getAttribute(attributeName));
3992
4045
 
3993
-
3994
- if(nodeNameLowerCase == 'input' && attributeName.toLowerCase() == 'value'){
4046
+ //是否是 input、 textarea 的 value ,如果是 则是 true
4047
+ var isInputValue = false;
4048
+ if((nodeNameLowerCase === 'input' || nodeNameLowerCase === 'textarea') && attributeName.toLowerCase() == 'value'){
3995
4049
  //如果是input 的value属性,那么要直接获取,而非通过 attribute ,不然用户自己输入的通过 attribute 是获取不到的 - catl 赵阳 提出
3996
4050
  attributeValue = node.value;
3997
4051
  DOMPropOrHTMLAttr = 'DOMProperty';
4052
+ isInputValue = true;
3998
4053
  }else{
3999
4054
  /*
4000
4055
  * 默认是 HtmlAtrribute 也就是 HTML特性。取值有两个:
@@ -4019,10 +4074,10 @@ var translate = {
4019
4074
  // //这个tag标签没有这个 attribute,忽略
4020
4075
  // continue
4021
4076
  //}
4022
- //判断当前元素是否在ignore忽略的tag、id、class name中 v3.15.7 增加
4077
+ //判断当前元素是否在ignore忽略的tag、id、class name中 v3.15.7 增加
4023
4078
  if(!translate.ignore.isIgnore(node)){
4024
4079
  //加入翻译
4025
- translate.addNodeToQueue(uuid, node.getAttributeNode(attributeName), attributeValue, '');
4080
+ translate.addNodeToQueue(uuid, isInputValue? node:node.getAttributeNode(attributeName), attributeValue, isInputValue? 'value':'');
4026
4081
  }
4027
4082
  }
4028
4083
  }
@@ -4226,9 +4281,12 @@ var translate = {
4226
4281
  * text 当前要翻译的目标文本
4227
4282
  * attribute 是否是元素的某个属性。比如 a标签中的title属性, a.title 再以node参数传入时是string类型的,本身并不是node类型,所以就要传入这个 attribute=title 来代表这是a标签的title属性。同样第二个参数node传入的也不能是a.title,而是传入a这个node元素
4228
4283
  如果不穿或者传入 '' 空字符串,则代表不是 attribute 属性,而是nodeValue 本身
4284
+ 注意, textarea、input 标签的 value 属性的特殊性,如果 node 是textarea、input ,那么value时这个 attribute 要传递 'value' 进来的
4229
4285
  */
4230
4286
  addNodeToQueue:function(uuid, node, text, attribute){
4231
- //console.log(text)
4287
+ //console.log('addNodeToQueue - params: uuid:'+uuid+', text:'+text+', attribute:'+attribute+', node:');
4288
+ //console.log(node);
4289
+
4232
4290
  if(node == null || text == null || text.length == 0){
4233
4291
  return;
4234
4292
  }
@@ -4236,10 +4294,10 @@ var translate = {
4236
4294
 
4237
4295
  //console.log('find tag ignore : '+node.nodeValue+', '+node.nodeName+", "+node.nodeType+", "+node.tagName);
4238
4296
  //console.log('addNodeToQueue into -- node:'+node+', text:'+text+', attribute:'+attribute);
4239
- var nodename = translate.element.getNodeName(node);
4297
+ var nodename = translate.element.getNodeName(node).toLowerCase();
4240
4298
 
4241
4299
  //判断如果是被 <!-- --> 注释的区域,不进行翻译
4242
- if(nodename.toLowerCase() == '#comment'){
4300
+ if(nodename == '#comment'){
4243
4301
  return;
4244
4302
  }
4245
4303
  //console.log('\t\t'+text);
@@ -4281,9 +4339,14 @@ var translate = {
4281
4339
  var translateNode; //当前操作的,要记录入 translate.node 中的,进行翻译的node
4282
4340
  var translateNode_attribute = ''; //当前操作的是node中的哪个attribute,如果没有是node本身则是空字符串
4283
4341
  if(typeof(attribute) === 'string' && attribute.length > 0){
4284
- //是操作的元素的某个属性
4285
- translateNode = node.getAttributeNode(attribute);
4286
- translateNode_attribute = attribute;
4342
+ //是操作的元素的某个属性,这时要判断 是否是 input、textarea 的value属性
4343
+ if((nodename === 'input' || nodename === 'textarea') && attribute !== null && attribute === 'value'){
4344
+ translateNode = node;
4345
+ translateNode_attribute = 'value';
4346
+ }else{
4347
+ translateNode = node.getAttributeNode(attribute);
4348
+ translateNode_attribute = attribute;
4349
+ }
4287
4350
  }else{
4288
4351
  //操作的就是node本身
4289
4352
  translateNode = node;
@@ -4381,7 +4444,7 @@ var translate = {
4381
4444
  //console.log(textArray);
4382
4445
  textArray = translate.nomenclature.dispose(textArray, temporaryIgnoreTexts[ti], temporaryIgnoreTexts[ti], {
4383
4446
  node:translateNode,
4384
- attribute:''
4447
+ attribute:translateNode_attribute
4385
4448
  }).texts;
4386
4449
  //console.log(textArray);
4387
4450
  }
@@ -4410,7 +4473,7 @@ var translate = {
4410
4473
  //console.log(textArray);
4411
4474
  var nomenclatureDispose = translate.nomenclature.dispose(textArray, nomenclatureKey, nomenclatureValue, {
4412
4475
  node:translateNode,
4413
- attribute:''
4476
+ attribute:translateNode_attribute
4414
4477
  });
4415
4478
 
4416
4479
  textArray = nomenclatureDispose.texts;
@@ -6188,16 +6251,16 @@ var translate = {
6188
6251
  }
6189
6252
 
6190
6253
  //如果用户浏览器没读到默认语言,或者默认语言没有对应到translate.js支持的语种,那么在采用ip识别的方式
6191
- translate.request.post(translate.request.api.ip, {}, function(data){
6192
- //console.log(data);
6193
- if(data.result == 0){
6254
+ translate.request.post(translate.request.api.ip, {}, function(responseData, requestData){
6255
+ //console.log(responseData);
6256
+ if(responseData.result != 1){
6194
6257
  translate.log('==== ERROR 获取当前用户所在区域异常 ====');
6195
6258
  translate.log(data.info);
6196
6259
  translate.log('==== ERROR END ====');
6197
6260
  }else{
6198
- translate.storage.set('to',data.language); //设置目标翻译语言
6199
- translate.to = data.language; //设置目标语言
6200
- translate.selectLanguageTag
6261
+ translate.storage.set('to',responseData.language); //设置目标翻译语言
6262
+ translate.to = responseData.language; //设置目标语言
6263
+ //translate.selectLanguageTag
6201
6264
  translate.execute(); //执行翻译
6202
6265
  }
6203
6266
  }, null);
@@ -7276,7 +7339,7 @@ var translate = {
7276
7339
 
7277
7340
  if(serviceName.toLowerCase() == 'giteeai'){
7278
7341
  //设定翻译接口为GiteeAI的
7279
- translate.request.api.host=['https://giteeai.zvo.cn/','https://deutsch.enterprise.api.translate.zvo.cn:1000/','https://api.translate.zvo.cn:1000/'];
7342
+ translate.request.api.host=['https://giteeai.zvo.cn/','https://deutsch.enterprise.api.translate.zvo.cn:1000/','https://api.translate.zvo.cn:1000/', 'https://america.api.translate.zvo.cn:1000/'];
7280
7343
  return;
7281
7344
  }
7282
7345
  if(serviceName.toLowerCase() == 'siliconflow'){
@@ -7869,7 +7932,11 @@ var translate = {
7869
7932
  * to: "chinese_traditional
7870
7933
  * }
7871
7934
  *
7872
- * @param func 请求完成的回调,传入如 function(data){ console.log(data); }
7935
+ * @param func 请求完成的回调,也就是只要响应码是 200 ,则会触发这个方法。 传入如 function(responseData, requestData){ console.log(responseData); }
7936
+ * 其中的参数:
7937
+ * responseData 响应的数据
7938
+ * requestData post请求所携带的数据
7939
+ * 注意,是响应数据是第一个参数,请求数据是第二个参数。 以向前兼容
7873
7940
  * @param abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} 另外这里的 xhr 会额外有个参数 xhr.requestURL 返回当前请求失败的url
7874
7941
  */
7875
7942
  post:function(path, data, func, abnormalFunc){
@@ -7913,7 +7980,10 @@ var translate = {
7913
7980
  * url 请求的url或者path(path,传入的是translate.request.api.translate 这种的,需要使用 getUrl 来组合真正请求的url )
7914
7981
  * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'}
7915
7982
  * appendXhrData 附加到 xhr.data 中的对象数据,传入比如 {"from":"english","to":"japanese"} ,他会直接赋予 xhr.data
7916
- * func 请求完成的回调,传入如 function(data){}
7983
+ * func 请求完成的回调,也就是只要响应码是 200 ,则会触发这个方法。 传入如 function(requestData, responseData){ console.log(responseData); }
7984
+ * 其中的参数:
7985
+ * requestData post请求所携带的数据
7986
+ * responseData 响应的数据
7917
7987
  * method 请求方式,可传入 post、get
7918
7988
  * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求。 如果传入false,则本方法返回xhr
7919
7989
  * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'};
@@ -8022,10 +8092,10 @@ var translate = {
8022
8092
  }
8023
8093
  }
8024
8094
 
8025
- if(json == null){
8095
+ if(json === null){
8026
8096
  func(xhr.responseText);
8027
8097
  }else{
8028
- func(json);
8098
+ func(json, xhr.data);
8029
8099
  }
8030
8100
  }else{
8031
8101
  if(showErrorLog){
@@ -8178,34 +8248,34 @@ var translate = {
8178
8248
  text:encodeURIComponent(JSON.stringify(apiTranslateText))
8179
8249
  };
8180
8250
  //console.log(apiTranslateText);
8181
- translate.request.post(url, data, function(resultData){
8182
- //console.log(resultData);
8251
+ translate.request.post(url, data, function(responseData, requestData){
8252
+ //console.log(responseData);
8183
8253
  //console.log(data);
8184
- if(resultData.result == 0){
8254
+ if(responseData.result != 1){
8185
8255
  translate.log('=======ERROR START=======');
8186
- translate.log('from : '+resultData.from);
8187
- translate.log('to : '+resultData.to);
8256
+ translate.log('from : '+requestData.from);
8257
+ translate.log('to : '+requestData.to);
8188
8258
  translate.log('translate text array : '+texts);
8189
- translate.log('response : '+resultData.info);
8259
+ translate.log('response error info: '+responseData.info);
8190
8260
  translate.log('=======ERROR END =======');
8191
8261
  //return;
8192
8262
  }
8193
8263
 
8194
- for(var i = 0; i < resultData.text.length; i++){
8264
+ for(var i = 0; i < responseData.text.length; i++){
8195
8265
  //将翻译结果以 key:hash value翻译结果的形式缓存
8196
8266
  var hash = translate.util.hash(apiTranslateText[i]);
8197
- translate.storage.set('hash_'+to+'_'+hash, resultData.text[i]);
8267
+ translate.storage.set('hash_'+to+'_'+hash, responseData.text[i]);
8198
8268
  //如果离线翻译启用了全部提取,那么还要存入离线翻译指定存储
8199
8269
  if(translate.offline.fullExtract.isUse){
8200
- translate.offline.fullExtract.set(hash, apiTranslateText[i], data.to, resultData.text[i]);
8270
+ translate.offline.fullExtract.set(hash, apiTranslateText[i], data.to, responseData.text[i]);
8201
8271
  }
8202
8272
 
8203
8273
  //进行组合数据到 translateResultArray
8204
- translateResultArray[apiTranslateArray[hash]] = resultData.text[i];
8274
+ translateResultArray[apiTranslateArray[hash]] = responseData.text[i];
8205
8275
  }
8206
- resultData.text = translateResultArray;
8276
+ responseData.text = translateResultArray;
8207
8277
 
8208
- func(resultData);
8278
+ func(responseData);
8209
8279
  }, null);
8210
8280
  },
8211
8281
  listener:{
@@ -8734,7 +8804,20 @@ var translate = {
8734
8804
  //translate.element.nodeAnalyse.analyse(key, analyse.text, translate.node.get(key).originalText, translate.node.get(key).attribute);
8735
8805
 
8736
8806
  //标注此次改动是有 translate.js 导致的 -- 这里就不用标记了,因为先已经移除了 translate.listener.observer 监听,所以不会再监听到还原的操作了
8737
- key.nodeValue = translate.node.get(key).originalText;
8807
+
8808
+ //是否是 input、 textarea 的 value ,如果是 则是 true
8809
+ var isInputValue = false;
8810
+ if(typeof(translate.node.get(key).attribute) === 'string' && translate.node.get(key).attribute === 'value'){
8811
+ //可能是input\textarea 的value
8812
+ var nodename = translate.element.getNodeName(key).toLowerCase();
8813
+ if(nodename === 'input' || nodename === 'textarea'){
8814
+ key.value = translate.node.get(key).originalText;
8815
+ isInputValue = true;
8816
+ }
8817
+ }
8818
+ if(!isInputValue){
8819
+ key.nodeValue = translate.node.get(key).originalText;
8820
+ }
8738
8821
  //}
8739
8822
  }
8740
8823
 
@@ -8806,10 +8889,13 @@ var translate = {
8806
8889
  to:translate.to,
8807
8890
  text:encodeURIComponent(JSON.stringify([translateText]))
8808
8891
  };
8809
- translate.request.post(url, data, function(data) {
8810
- if (data.result == 0) return;
8892
+ translate.request.post(url, data, function(responseData, requestData) {
8893
+ if (responseData.result != 1){
8894
+ translate.log('translate.selectionTranslate network response error : '+responseData.info);
8895
+ return;
8896
+ };
8811
8897
  let curTooltipEle = document.querySelector('#translateTooltip')
8812
- curTooltipEle.innerText = data.text[0];
8898
+ curTooltipEle.innerText = responseData.text[0];
8813
8899
  curTooltipEle.style.top =selectionY+20+"px";
8814
8900
  curTooltipEle.style.left = selectionX+50+"px" ;
8815
8901
  curTooltipEle.style.display = "";
@@ -9014,6 +9100,8 @@ var translate = {
9014
9100
  if(translate.progress.api.isTip){
9015
9101
  //translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
9016
9102
  translate.lifecycle.execute.translateNetworkBefore.push(function(data){
9103
+ //var startTime = new Date().getTime();
9104
+
9017
9105
  //取出当前变动的node,对应的元素
9018
9106
  var elements = translate.element.nodeToElement(data.nodes);
9019
9107
  //console.log(elements)
@@ -9032,10 +9120,15 @@ var translate = {
9032
9120
  //console.log(sortRects);
9033
9121
 
9034
9122
  //去重
9035
- sortRects = translate.visual.filterNodeRepeat(sortRects);
9036
- //console.log(sortRects);
9123
+ var repeatRects = translate.visual.filterNodeRepeat(sortRects);
9124
+ //console.log(repeatRects);
9037
9125
 
9038
- var rectLineSplit = translate.visual.filterRectsByLineInterval(rectsOneArray, 2);
9126
+ //去除空间重叠
9127
+ var spaceEORects = translate.visual.rectsSpaceEliminateOverlap(repeatRects);
9128
+ //console.log(spaceEORects);
9129
+ //console.log('计算耗时:'+(new Date().getTime() - startTime));
9130
+
9131
+ var rectLineSplit = translate.visual.filterRectsByLineInterval(spaceEORects, 2);
9039
9132
  for(var r = 0; r<rectLineSplit.length; r++){
9040
9133
  if(typeof(rectLineSplit[r].node.className) === 'string' && rectLineSplit[r].node.className.indexOf('translate_api_in_progress') > -1){
9041
9134
  //已经存在了,就不继续加了
@@ -9043,6 +9136,7 @@ var translate = {
9043
9136
  rectLineSplit[r].node.className = rectLineSplit[r].node.className+' translate_api_in_progress';
9044
9137
  }
9045
9138
  }
9139
+ //console.log('计算+渲染耗时:'+(new Date().getTime() - startTime));
9046
9140
  });
9047
9141
 
9048
9142
  translate.lifecycle.execute.translateNetworkAfter.push(function(data){
@@ -10035,6 +10129,50 @@ var translate = {
10035
10129
 
10036
10130
  return filtered;
10037
10131
  },
10132
+ /*
10133
+ 对排重并按照top排序后的 rect 坐标进行空间的重叠处理(按高度进行判定,避免一行出现两个)
10134
+ 它可以紧紧挨着,但不允许出现重叠情况
10135
+
10136
+ @param rects 一维的矩形信息数组(包含node和坐标信息),也就是 translate.visual.filterNodeRepeat(sortRects); 去重后取得的信息。
10137
+ 注意,它必须要经过这几步处理才行:
10138
+ var sortRects = translate.visual.coordinateSort(rectsOneArray); //排序
10139
+ sortRects = translate.visual.filterNodeRepeat(sortRects); //去重
10140
+ @return 返回排除重叠的坐标数组。
10141
+
10142
+ */
10143
+ rectsSpaceEliminateOverlap: function(rects){
10144
+ for(var i = rects.length-1; i > -1; i--){
10145
+ //是第一个,那么就不需要再向上判定了
10146
+ if(i == 0){
10147
+ continue;
10148
+ }
10149
+
10150
+ //如果上一个坐标的底部大于当前坐标的顶部,那么高度就已经产生重叠了,将排除当前元素,移除当前元素
10151
+ if(rects[i-1].bottom > rects[i].top){
10152
+ //console.log('---移除第'+i);
10153
+ //console.log(rects[i]);
10154
+ rects.splice(i, 1);
10155
+ }
10156
+ }
10157
+
10158
+ /*
10159
+ //检查
10160
+ for(var i = rects.length-1; i > -1; i--){
10161
+ //是第一个,那么就不需要再向上判定了
10162
+ if(i == 0){
10163
+ continue;
10164
+ }
10165
+
10166
+ //如果上一个坐标的底部大于当前坐标的顶部,那么高度就已经产生重叠了,将排除当前元素,移除当前元素
10167
+ if(rects[i-1].bottom > rects[i].top){
10168
+ console.log('---发现漏掉的,第'+i);
10169
+ console.log(rects[i]);
10170
+ }
10171
+ }
10172
+ */
10173
+
10174
+ return rects;
10175
+ },
10038
10176
  /*
10039
10177
  对一组坐标进行排序
10040
10178
  按开始坐标从左到右、从上到下排序
@@ -10053,13 +10191,15 @@ var translate = {
10053
10191
  return sortedRects;
10054
10192
  },
10055
10193
  /*
10056
- 对一组坐标进行去重处理,同一个node,只会取从下标0开始往后的第一个
10194
+ 对一组坐标进行处理,过滤
10195
+ 1. 同一个node,只会取从下标0开始往后的第一个,对 node 进行排重
10196
+ 2. 对 rects 中的坐标进行计算大小,计算出当前的平均数(面积),然后移除小于平均数5倍的 rects 元素。 比如平均面积是 10, 则具体的rect面积小于 2 的则删掉
10197
+
10057
10198
  @param rects translate.visual.getRects 获取到的坐标数据,经过 translate.visual.rectsToOneArray(rects); 处理后得到的一维数组,可以直接传入,也可以进行 translate.visual.coordinateSort(rectsOneArray); 排序处理后传入
10058
10199
  */
10059
10200
  filterNodeRepeat:function(rects){
10060
10201
  var map = new Map(); //key是node,value随便
10061
- //console.log(rects);
10062
-
10202
+
10063
10203
  var deleteIndexArray = [];
10064
10204
  for(var i = 0; i < rects.length; i++){
10065
10205
  if(map.get(rects[i].node) != null){
@@ -10075,8 +10215,32 @@ var translate = {
10075
10215
  //console.log(deleteIndexArray[di]);
10076
10216
  rects.splice(deleteIndexArray[di], 1); // 从索引 deleteIndexArray[di] 开始,删除1个元素
10077
10217
  }
10078
-
10079
10218
  map = undefined;
10219
+
10220
+
10221
+ // 计算面积
10222
+ var areaSizeArray = []; //其中下标跟 rects 一一对应,这里存的是面积大小
10223
+ for(var i = 0; i < rects.length; i++){
10224
+ areaSizeArray[i] = rects[i].height * rects[i].width;
10225
+ }
10226
+ // 1. 计算面积总和
10227
+ const sum = areaSizeArray.reduce((acc, val) => acc + val, 0);
10228
+ // 2. 计算平均值
10229
+ const avg = sum / areaSizeArray.length;
10230
+ // 3. 计算阈值(平均值的20%)
10231
+ const threshold = avg * 0.2;
10232
+ // 4. 收集需要删除的下标
10233
+ const indicesToRemove = [];
10234
+ for (let i = 0; i < areaSizeArray.length; i++) {
10235
+ if (areaSizeArray[i] < threshold) {
10236
+ indicesToRemove.push(i);
10237
+ }
10238
+ }
10239
+ //5. 移除面积极小的rects元素
10240
+ for(var di = indicesToRemove.length-1; di > -1; di--){
10241
+ rects.splice(indicesToRemove[di], 1);
10242
+ }
10243
+
10080
10244
  return rects;
10081
10245
  },
10082
10246
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18n-jsautotranslate",
3
- "version": "3.18.76",
3
+ "version": "3.18.84",
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": {
@@ -15,7 +15,9 @@
15
15
  "files": [
16
16
  "index.js",
17
17
  "ArcoDesign/Vue3/LanguageSelect.vue",
18
- "vue/**",
18
+ "vue/vue3/LanguageSelect.vue",
19
+ "vue/vue3/translateVue3TS.ts",
20
+ "vue/vue3/translate.ts",
19
21
  "naiveUI/LanguageSelect.vue"
20
22
  ],
21
23
  "homepage": "https://github.com/xnx3/translate#readme",
@@ -1,18 +1,19 @@
1
1
  VUE3 中 使用 translate.js
2
2
 
3
- ## [修改] package.json 文件
3
+ ## 第一步:修改 package.json 文件
4
4
  dependencies 中增加
5
5
  ````
6
- "i18n-jsautotranslate": "^3.18.76",
6
+ "i18n-jsautotranslate": "^3.18.77",
7
7
  ````
8
+ 然后执行 ````npm install```` (或 ````yarn install```` 或 ````pnpm install```` 等等)
8
9
 
9
- ## [新增] translate.js (或ts) 文件
10
+ ## 第二步:增加 translate.js (或ts) 文件
10
11
  比如,在你项目的 utils 目录(或其他什么目录都行)下,新增 translate.js (或.ts 只是后缀自己改一下就行) 文件。
11
- 此文件源码: [Github](https://raw.githubusercontent.com/xnx3/translate/refs/heads/master/extend/vue/vue3/translate.ts) | [Gitee](https://gitee.com/mail_osc/translate/blob/master/extend/vue/vue3/translate.ts)
12
+ [此文件源码点此查看](./translate.ts)
12
13
  这个文件也是你当前项目对翻译进行各种自定义微调所在。
13
14
  有什么要设置的,比如设置使用你私有部署的翻译服务器提供翻译服务、设置哪些文字不进行翻译、设置自定义术语 ……等等
14
15
 
15
- ## [修改] main.js (或ts) 文件
16
+ ## 第三步:修改 main.js (或ts) 文件
16
17
  首先导入 上一步新建的文件,也就是新增一行 import :
17
18
  ````
18
19
  import {translateJsVueUseModel} from './utils/translate' // 多语言切换, 导入translate插件
@@ -33,17 +34,19 @@ app.use(translateJsVueUseModel); //注释掉,即可停用多语言切换能
33
34
  app.mount('#app');
34
35
  ````
35
36
 
36
- ## 页面上出现语言切换的Select下拉切换菜单
37
+ ## 第四步:在页面上出现Select下拉切换语言菜单
37
38
 
38
- 文档参见: [Github文档](https://github.com/xnx3/translate/tree/master/extend/vue/vue3/LanguageSelect.md) | [Gitee文档](https://gitee.com/mail_osc/translate/tree/master/extend/vue/vue3/LanguageSelect.md)
39
+ 文档参见: [./LanguageSelect.md](./LanguageSelect.md)
39
40
 
40
41
 
41
42
  另外,我们针对部分UI框架,进行了适配,你可以直接快速使用
42
- * ArcoDesign - [Github](https://github.com/xnx3/translate/tree/master/extend/ArcoDesign/Vue3) | [Gitee](https://gitee.com/mail_osc/translate/tree/master/extend/ArcoDesign/Vue3)
43
- * naiveUI - [Github](https://github.com/xnx3/translate/tree/master/extend/naiveUI) | [Gitee](https://gitee.com/mail_osc/translate/tree/master/extend/naiveUI)
43
+ * [ArcoDesign](../../ArcoDesign/Vue3/README.md)
44
+ * [naiveUI](../../naiveUI/README.md)
44
45
 
45
46
  如果你使用的别的UI框架,可以 [联系我](http://translate.zvo.cn/4030.html) 沟通,目前正在增加其他主流UI框架的,没准你要的就恰好有了,或者直接针对你当前使用的进行新适配。
46
47
 
48
+ ## 第五步:DEMO参考示例
49
+ 参见: [demo/README.md](./demo/README.md)
47
50
 
48
51
  ## 注意
49
- 比如你vue页面中有个按钮,点击后触发切换为某种语言,正常使用是 `translate.changeLanguage('english');` 而在vue代码中如果提示 `translate 不存在` ,那么你触发时前面额外加个windows.即可 : `window.translate.changeLanguage('english');`
52
+ 比如你vue页面中有个按钮,点击后触发切换为某种语言,正常使用是 `translate.changeLanguage('english');` 而在vue代码中如果提示 `translate not find` ,那么你触发时前面额外加个windows.即可 : `window.translate.changeLanguage('english');`
@@ -1,4 +1,5 @@
1
- import {translateJsVueUseModel, translate} from './translateVue3TS' // 导入 translate 的 VUE3 的 ts 插件
1
+ import {translateJsVueUseModel, translate} from 'i18n-jsautotranslate/vue/vue3/translateVue3TS.ts'; // 导入 translate 的 VUE3 的 ts 插件
2
+
2
3
 
3
4
  /*
4
5
 
@@ -15,14 +16,6 @@ translate.vue3.config = function(app){
15
16
  //translate.time.use = true;
16
17
  //window.translate.time.printTime = 100;
17
18
 
18
- var originalTrasnalteLog = translate.log;
19
- translate.log = function(obj){
20
- if(typeof(obj) === 'string' && obj.indexOf('- translate.js -') !== -1){
21
- //不显示 translate.js 的说明
22
- }else{
23
- originalTrasnalteLog(obj);
24
- }
25
- }
26
19
 
27
20
  // 针对翻译动作的性能监控 https://translate.zvo.cn/549733.html
28
21
  translate.time.execute.start();
@@ -1,6 +1,16 @@
1
1
  import { nextTick } from 'vue';
2
2
  import translate from 'i18n-jsautotranslate'
3
3
 
4
+ /* 这里不打印 translate.js 的声明 */
5
+ var originalTrasnalteLog = translate.log;
6
+ translate.log = function(obj){
7
+ if(typeof(obj) === 'string' && obj.indexOf('- translate.js -') !== -1){
8
+ //不显示 translate.js 的说明
9
+ }else{
10
+ originalTrasnalteLog(obj);
11
+ }
12
+ }
13
+
4
14
  //vue3框架的一些单独设置
5
15
  translate.vue3 = {
6
16
  /*
@@ -1,132 +0,0 @@
1
- # VUE3
2
-
3
- ## 接入 vue3 方式使用 translate.js
4
- http://translate.zvo.cn/4041.html
5
-
6
- ## 页面上出现语言切换的Select下拉切换菜单
7
-
8
- ### 效果
9
- 见下图右上角的多语言切换
10
- ![](./resource/preview.png)
11
- 这个多语言切换的 Select 很原始,你可以对它使用CSS进行美化、或自定义其html显示方式。具体可参考以下文档。
12
- 另外如果你用其他UI框架,也可以直接进行使用:
13
- * ArcoDesign - [Github](https://github.com/xnx3/translate/tree/master/extend/ArcoDesign/Vue3) | [Gitee](https://gitee.com/mail_osc/translate/tree/master/extend/ArcoDesign/Vue3)
14
- * naiveUI - [Github](https://github.com/xnx3/translate/tree/master/extend/naiveUI) | [Gitee](https://gitee.com/mail_osc/translate/tree/master/extend/naiveUI)
15
-
16
- ### 代码
17
-
18
- 比如要在 index.vue 页面上显示切换语言的 select 下拉菜单,那么 index.vue 页面中,要进行的操作:
19
- 先在 index.vue 中,加入一行,导入此UI框架的多语言切换Select
20
- ````import LanguageSelect from 'i18n-jsautotranslate/vue/vue3/LanguageSelect.vue';````
21
- 然后在要显示select菜单的位置,直接加入
22
- ````<LanguageSelect/>````
23
- 即可。
24
- 最后,可以使用css样式来进行自定义美化,比如要将这个语言切换放到页面的右上角:
25
- ````
26
- /* 多语言切换Select */
27
- .LanguageSelect {
28
- position: fixed;
29
- top: 20px;
30
- right: 80px;
31
- }
32
- ````
33
- 注意,这个多语言切换的 select ,它的class 名字为 LanguageSelect
34
-
35
- 完整的示例代码如下:
36
- ````
37
- <template>
38
- <div class="login">
39
- <h3 class="login-logo">
40
- Logo
41
- </h3>
42
-
43
- <!-- 多语言切换的 Select 下拉选择 -->
44
- <LanguageSelect/>
45
- </div>
46
- </template>
47
-
48
- <script setup>
49
- import { computed, ref } from 'vue'
50
- import LanguageSelect from 'i18n-jsautotranslate/vue/vue3/LanguageSelect.vue';
51
- </script>
52
-
53
- <style scoped>
54
- .LanguageSelect {
55
- position: fixed;
56
- top: 20px;
57
- right: 80px;
58
- }
59
- </style>
60
- ````
61
-
62
- ### 自定义切换语言的html代码
63
- 修改
64
- ````
65
- <LanguageSelect/>
66
- ````
67
- 为:
68
- ````
69
- <script setup>
70
- //获取该用户之前是否有切换过语言,获取其最后一次切换的是什么语种,详细参考: http://translate.zvo.cn/4074.html
71
- const language = window.translate.language.getCurrent();
72
- </script>
73
- <LanguageSelect>
74
- <!-- 使用作用域插槽,直接使用子组件传递过来的数据和方法 -->
75
- <template #default="{ LanguageSelectLanguageList, LanguageSelectOnChange }">
76
- <select
77
- v-model="language"
78
- @change="LanguageSelectOnChange"
79
- class="ignore LanguageSelect"
80
- >
81
- <option value="" disabled>Please select language</option>
82
- <option v-for="option in LanguageSelectLanguageList" :key="option.id" :value="option.id">
83
- {{ option.name }}
84
- </option>
85
- </select>
86
- </template>
87
- </LanguageSelect>
88
- ````
89
-
90
- 完整的示例代码如下:
91
- ````
92
- <template>
93
- <div class="login">
94
- <h3 class="login-logo">
95
- Logo
96
- </h3>
97
-
98
- <!-- 多语言切换的 Select 下拉选择 -->
99
- <LanguageSelect>
100
- <!-- 使用作用域插槽,直接使用子组件传递过来的数据和方法 -->
101
- <template #default="{ LanguageSelectLanguageList, LanguageSelectOnChange }">
102
- <select
103
- v-model="language"
104
- @change="LanguageSelectOnChange"
105
- class="ignore LanguageSelect"
106
- >
107
- <option value="" disabled>Please select language</option>
108
- <option v-for="option in LanguageSelectLanguageList" :key="option.id" :value="option.id">
109
- {{ option.name }}
110
- </option>
111
- </select>
112
- </template>
113
- </LanguageSelect>
114
- </div>
115
- </template>
116
-
117
- <script setup>
118
- import { computed, ref } from 'vue'
119
- import LanguageSelect from 'i18n-jsautotranslate/vue/vue3/LanguageSelect.vue';
120
-
121
- //获取该用户之前是否有切换过语言,获取其最后一次切换的是什么语种,详细参考: http://translate.zvo.cn/4074.html
122
- const language = window.translate.language.getCurrent();
123
- </script>
124
-
125
- <style scoped>
126
- .LanguageSelect {
127
- position: fixed;
128
- top: 20px;
129
- right: 80px;
130
- }
131
- </style>
132
- ````
Binary file