i18n-jsautotranslate 3.18.77 → 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 +4 -6
- package/index.js +270 -106
- package/package.json +4 -2
- package/vue/vue3/README.md +13 -10
- package/vue/vue3/translate.ts +2 -1
- package/vue/vue3/LanguageSelect.md +0 -132
- package/vue/vue3/resource/preview.png +0 -0
package/README.md
CHANGED
|
@@ -17,12 +17,10 @@
|
|
|
17
17
|
</h4>
|
|
18
18
|
|
|
19
19
|
# 特性说明
|
|
20
|
-
* **使用极其简单。** 直接加入几行 JavaScript
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
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.
|
|
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(
|
|
238
|
-
if(
|
|
239
|
-
translate.log('load language list error : '+
|
|
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 =
|
|
244
|
-
translate.selectLanguageTag.customUI(translate.selectLanguageTag.customLanguagesHandle(
|
|
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
|
-
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1804
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
3136
|
-
if(typeof(translate.translateRequest[uuid]) == 'object' && typeof(translate.translateRequest[uuid][
|
|
3137
|
-
translate.translateRequest[uuid][
|
|
3138
|
-
translate.translateRequest[uuid][
|
|
3139
|
-
translate.translateRequest[uuid][
|
|
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][
|
|
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(
|
|
3147
|
-
from =
|
|
3175
|
+
if(typeof(requestData.from) != 'undefined' && requestData.from != null){
|
|
3176
|
+
from = requestData.from;
|
|
3148
3177
|
}
|
|
3149
3178
|
var to = '';
|
|
3150
|
-
if(typeof(
|
|
3151
|
-
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,
|
|
3184
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, from, to, 0, responseData.info);
|
|
3156
3185
|
|
|
3157
3186
|
|
|
3158
3187
|
translate.log('=======ERROR START=======');
|
|
3159
|
-
translate.log(translateTextArray[
|
|
3188
|
+
translate.log(translateTextArray[requestData.from]);
|
|
3160
3189
|
//console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from])));
|
|
3161
|
-
translate.log('response : '+
|
|
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[
|
|
3207
|
+
for(var i=0; i<translateHashArray[responseData.from].length; i++){
|
|
3179
3208
|
//翻译前的语种,如 english
|
|
3180
|
-
var lang =
|
|
3209
|
+
var lang = responseData.from;
|
|
3181
3210
|
//翻译后的内容
|
|
3182
|
-
var text =
|
|
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[
|
|
3219
|
+
if(text.toLowerCase().indexOf(translateTextArray[responseData.from][i].toLowerCase()) > -1){
|
|
3191
3220
|
//发现了,那么强制赋予翻以前内容
|
|
3192
|
-
text = translateTextArray[
|
|
3221
|
+
text = translateTextArray[responseData.from][i];
|
|
3193
3222
|
}
|
|
3194
3223
|
|
|
3195
3224
|
|
|
3196
3225
|
//翻译前的hash对应下标
|
|
3197
|
-
var hash = translateHashArray[
|
|
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_'+
|
|
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,
|
|
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,
|
|
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:
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
3904
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
4286
|
-
|
|
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(
|
|
6192
|
-
//console.log(
|
|
6193
|
-
if(
|
|
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',
|
|
6199
|
-
translate.to =
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
8182
|
-
//console.log(
|
|
8251
|
+
translate.request.post(url, data, function(responseData, requestData){
|
|
8252
|
+
//console.log(responseData);
|
|
8183
8253
|
//console.log(data);
|
|
8184
|
-
if(
|
|
8254
|
+
if(responseData.result != 1){
|
|
8185
8255
|
translate.log('=======ERROR START=======');
|
|
8186
|
-
translate.log('from : '+
|
|
8187
|
-
translate.log('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 : '+
|
|
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 <
|
|
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,
|
|
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,
|
|
8270
|
+
translate.offline.fullExtract.set(hash, apiTranslateText[i], data.to, responseData.text[i]);
|
|
8201
8271
|
}
|
|
8202
8272
|
|
|
8203
8273
|
//进行组合数据到 translateResultArray
|
|
8204
|
-
translateResultArray[apiTranslateArray[hash]] =
|
|
8274
|
+
translateResultArray[apiTranslateArray[hash]] = responseData.text[i];
|
|
8205
8275
|
}
|
|
8206
|
-
|
|
8276
|
+
responseData.text = translateResultArray;
|
|
8207
8277
|
|
|
8208
|
-
func(
|
|
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
|
-
|
|
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(
|
|
8810
|
-
if (
|
|
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 =
|
|
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
|
-
|
|
9036
|
-
//console.log(
|
|
9123
|
+
var repeatRects = translate.visual.filterNodeRepeat(sortRects);
|
|
9124
|
+
//console.log(repeatRects);
|
|
9037
9125
|
|
|
9038
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|
package/vue/vue3/README.md
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
VUE3 中 使用 translate.js
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 第一步:修改 package.json 文件
|
|
4
4
|
dependencies 中增加
|
|
5
5
|
````
|
|
6
|
-
"i18n-jsautotranslate": "^3.18.
|
|
6
|
+
"i18n-jsautotranslate": "^3.18.77",
|
|
7
7
|
````
|
|
8
|
+
然后执行 ````npm install```` (或 ````yarn install```` 或 ````pnpm install```` 等等)
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## 第二步:增加 translate.js (或ts) 文件
|
|
10
11
|
比如,在你项目的 utils 目录(或其他什么目录都行)下,新增 translate.js (或.ts 只是后缀自己改一下就行) 文件。
|
|
11
|
-
|
|
12
|
+
[此文件源码点此查看](./translate.ts)
|
|
12
13
|
这个文件也是你当前项目对翻译进行各种自定义微调所在。
|
|
13
14
|
有什么要设置的,比如设置使用你私有部署的翻译服务器提供翻译服务、设置哪些文字不进行翻译、设置自定义术语 ……等等
|
|
14
15
|
|
|
15
|
-
##
|
|
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
|
-
##
|
|
37
|
+
## 第四步:在页面上出现Select下拉切换语言菜单
|
|
37
38
|
|
|
38
|
-
文档参见: [
|
|
39
|
+
文档参见: [./LanguageSelect.md](./LanguageSelect.md)
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
另外,我们针对部分UI框架,进行了适配,你可以直接快速使用
|
|
42
|
-
*
|
|
43
|
-
*
|
|
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
|
|
52
|
+
比如你vue页面中有个按钮,点击后触发切换为某种语言,正常使用是 `translate.changeLanguage('english');` 而在vue代码中如果提示 `translate not find` ,那么你触发时前面额外加个windows.即可 : `window.translate.changeLanguage('english');`
|
package/vue/vue3/translate.ts
CHANGED
|
@@ -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
|
-

|
|
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
|