i18n-jsautotranslate 3.14.0 → 3.15.1
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/LICENSE +21 -201
- package/README.md +7 -5
- package/index.js +499 -326
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var translate = {
|
|
|
14
14
|
* 格式:major.minor.patch.date
|
|
15
15
|
*/
|
|
16
16
|
// AUTO_VERSION_START
|
|
17
|
-
version: '3.
|
|
17
|
+
version: '3.15.1.20250506',
|
|
18
18
|
// AUTO_VERSION_END
|
|
19
19
|
/*
|
|
20
20
|
当前使用的版本,默认使用v2. 可使用 setUseVersion2();
|
|
@@ -1083,13 +1083,17 @@ var translate = {
|
|
|
1083
1083
|
|
|
1084
1084
|
/*
|
|
1085
1085
|
每当触发执行 translate.execute() 时,当缓存中未发现,需要请求翻译API进行翻译时,在发送API请求前,触发此
|
|
1086
|
+
|
|
1087
|
+
@param uuid:translate.nodeQueue[uuid] 这里的
|
|
1088
|
+
@param from 来源语种,翻译前的语种
|
|
1089
|
+
@param to 翻译为的语种
|
|
1086
1090
|
*/
|
|
1087
1091
|
renderStartByApi : [],
|
|
1088
|
-
renderStartByApiRun:function(uuid){
|
|
1092
|
+
renderStartByApiRun:function(uuid, from, to){
|
|
1089
1093
|
//console.log(translate.nodeQueue[uuid]);
|
|
1090
1094
|
for(var i = 0; i < translate.listener.execute.renderStartByApi.length; i++){
|
|
1091
1095
|
try{
|
|
1092
|
-
translate.listener.execute.renderStartByApi[i](uuid);
|
|
1096
|
+
translate.listener.execute.renderStartByApi[i](uuid, from, to);
|
|
1093
1097
|
}catch(e){
|
|
1094
1098
|
console.log(e);
|
|
1095
1099
|
}
|
|
@@ -1098,14 +1102,17 @@ var translate = {
|
|
|
1098
1102
|
|
|
1099
1103
|
/*
|
|
1100
1104
|
每当 translate.execute() 执行完毕(前提是采用API翻译的,API将翻译结果返回,并且界面上的翻译结果也已经渲染完毕)后,触发此方法。
|
|
1101
|
-
|
|
1105
|
+
|
|
1106
|
+
@param uuid:translate.nodeQueue[uuid] 这里的
|
|
1107
|
+
@param from 来源语种,翻译前的语种
|
|
1108
|
+
@param to 翻译为的语种
|
|
1102
1109
|
*/
|
|
1103
1110
|
renderFinishByApi : [],
|
|
1104
|
-
renderFinishByApiRun:function(uuid){
|
|
1111
|
+
renderFinishByApiRun:function(uuid, from, to){
|
|
1105
1112
|
//console.log(translate.nodeQueue[uuid]);
|
|
1106
1113
|
for(var i = 0; i < translate.listener.execute.renderFinishByApi.length; i++){
|
|
1107
1114
|
try{
|
|
1108
|
-
translate.listener.execute.renderFinishByApi[i](uuid);
|
|
1115
|
+
translate.listener.execute.renderFinishByApi[i](uuid, from, to);
|
|
1109
1116
|
}catch(e){
|
|
1110
1117
|
console.log(e);
|
|
1111
1118
|
}
|
|
@@ -1402,9 +1409,25 @@ var translate = {
|
|
|
1402
1409
|
return null;
|
|
1403
1410
|
}
|
|
1404
1411
|
},
|
|
1405
|
-
|
|
1406
|
-
|
|
1412
|
+
/*
|
|
1413
|
+
当前 translate.translateRequest[uuid] 的是否已经全部执行完毕
|
|
1414
|
+
这里单纯只是对 translate.translateRequest[uuid] 的进行判断
|
|
1415
|
+
这里要在 translate.json 接口触发完并渲染完毕后触发,当然接口失败时也要触发。
|
|
1416
|
+
|
|
1417
|
+
正常情况下,是根据本地语言不同,进行分别请求翻译的,比如本地中包含中文、英文、俄语三种语种,要翻译为韩语,那么
|
|
1418
|
+
* 中文->韩语会请求一次api
|
|
1419
|
+
* 英文->韩语会请求一次APi
|
|
1420
|
+
* 俄语->韩语会请求一次APi
|
|
1421
|
+
也就会触发三次
|
|
1422
|
+
|
|
1423
|
+
@param uuid translate.translateRequest[uuid]中的uuid,也是 translate.nodeQueue 中的uuid
|
|
1424
|
+
@param from 来源语种,翻译前的语种
|
|
1425
|
+
@param to 翻译为的语种
|
|
1426
|
+
*/
|
|
1427
|
+
isAllExecuteFinish:function(uuid, from, to){
|
|
1428
|
+
//console.log('uuid:'+uuid+', from:'+from+', to:'+to);
|
|
1407
1429
|
for(var lang in translate.translateRequest[uuid]){
|
|
1430
|
+
//console.log(translate.translateRequest[uuid])
|
|
1408
1431
|
for(var i = 0; i<translate.translateRequest[uuid][lang].length; i++){
|
|
1409
1432
|
if(translate.translateRequest[uuid][lang][i].executeFinish == 0){
|
|
1410
1433
|
//这个还没执行完,那么直接退出,不在向后执行了
|
|
@@ -1421,7 +1444,7 @@ var translate = {
|
|
|
1421
1444
|
translate.state = 0;
|
|
1422
1445
|
translate.executeNumber++;
|
|
1423
1446
|
|
|
1424
|
-
translate.listener.execute.renderFinishByApiRun(uuid);
|
|
1447
|
+
translate.listener.execute.renderFinishByApiRun(uuid, from, to);
|
|
1425
1448
|
}
|
|
1426
1449
|
|
|
1427
1450
|
},
|
|
@@ -1996,9 +2019,7 @@ var translate = {
|
|
|
1996
2019
|
//状态
|
|
1997
2020
|
translate.state = 20;
|
|
1998
2021
|
|
|
1999
|
-
|
|
2000
|
-
translate.listener.execute.renderStartByApiRun(uuid);
|
|
2001
|
-
|
|
2022
|
+
|
|
2002
2023
|
//进行掉接口翻译
|
|
2003
2024
|
for(var lang_index in fanyiLangs){ //一维数组,取语言
|
|
2004
2025
|
var lang = fanyiLangs[lang_index];
|
|
@@ -2026,6 +2047,9 @@ var translate = {
|
|
|
2026
2047
|
translate.translateRequest[uuid][lang].addtime = Math.floor(Date.now() / 1000);
|
|
2027
2048
|
|
|
2028
2049
|
|
|
2050
|
+
//listener
|
|
2051
|
+
translate.listener.execute.renderStartByApiRun(uuid, lang, translate.to);
|
|
2052
|
+
|
|
2029
2053
|
/*** 翻译开始 ***/
|
|
2030
2054
|
var url = translate.request.api.translate;
|
|
2031
2055
|
var data = {
|
|
@@ -2035,7 +2059,6 @@ var translate = {
|
|
|
2035
2059
|
//text:JSON.stringify(translateTextArray[lang])
|
|
2036
2060
|
text:encodeURIComponent(JSON.stringify(translateTextArray[lang]))
|
|
2037
2061
|
};
|
|
2038
|
-
//console.log(data);
|
|
2039
2062
|
translate.request.post(url, data, function(data){
|
|
2040
2063
|
//console.log(data);
|
|
2041
2064
|
//console.log(translateTextArray[data.from]);
|
|
@@ -2047,8 +2070,20 @@ var translate = {
|
|
|
2047
2070
|
}else{
|
|
2048
2071
|
console.log('WARINNG!!! translate.translateRequest[uuid][data.from] is not object');
|
|
2049
2072
|
}
|
|
2050
|
-
|
|
2051
|
-
translate.
|
|
2073
|
+
|
|
2074
|
+
//为了兼容 v3.14以前的translate.service 版本,做了判断
|
|
2075
|
+
var from = '';
|
|
2076
|
+
if(typeof(data.from) != 'undefined' && data.from != null){
|
|
2077
|
+
from = data.from;
|
|
2078
|
+
}
|
|
2079
|
+
var to = '';
|
|
2080
|
+
if(typeof(data.to) != 'undefined' && data.to != null){
|
|
2081
|
+
to = data.to;
|
|
2082
|
+
}else{
|
|
2083
|
+
to = translate.to;
|
|
2084
|
+
}
|
|
2085
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, from, to);
|
|
2086
|
+
|
|
2052
2087
|
console.log('=======ERROR START=======');
|
|
2053
2088
|
console.log(translateTextArray[data.from]);
|
|
2054
2089
|
//console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from])));
|
|
@@ -2127,13 +2162,13 @@ var translate = {
|
|
|
2127
2162
|
translate.translateRequest[uuid][lang].executeFinish = 1; //1是执行完毕
|
|
2128
2163
|
translate.translateRequest[uuid][lang].stoptime = Math.floor(Date.now() / 1000);
|
|
2129
2164
|
setTimeout(function(){
|
|
2130
|
-
translate.waitingExecute.isAllExecuteFinish(uuid);
|
|
2165
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, data.from, data.to);
|
|
2131
2166
|
},10);
|
|
2132
2167
|
}, function(xhr){
|
|
2133
2168
|
translate.translateRequest[uuid][lang].executeFinish = 1; //1是执行完毕
|
|
2134
2169
|
translate.translateRequest[uuid][lang].stoptime = Math.floor(Date.now() / 1000);
|
|
2135
2170
|
translate.translateRequest[uuid][lang].result = 3;
|
|
2136
|
-
translate.waitingExecute.isAllExecuteFinish(uuid);
|
|
2171
|
+
translate.waitingExecute.isAllExecuteFinish(uuid, lang, translate.to);
|
|
2137
2172
|
});
|
|
2138
2173
|
/*** 翻译end ***/
|
|
2139
2174
|
}
|
|
@@ -2246,14 +2281,16 @@ var translate = {
|
|
|
2246
2281
|
if(typeof(originalText) != 'undefined' && originalText.length > 0){
|
|
2247
2282
|
if(typeof(node[attribute]) != 'undefined'){
|
|
2248
2283
|
//这种是主流框架,像是vue、element、react 都是用这种 DOM Property 的方式,更快
|
|
2249
|
-
node[attribute] = node[attribute]
|
|
2284
|
+
node[attribute] = translate.util.textReplace(node[attribute], originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2285
|
+
//node[attribute] = node[attribute].replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2250
2286
|
}
|
|
2251
2287
|
|
|
2252
2288
|
//这种 Html Attribute 方式 是 v3.12 版本之前一直使用的方式,速度上要慢于 上面的,为了向前兼容不至于升级出问题,后面可能会优化掉
|
|
2253
2289
|
var htmlAttributeValue = node.getAttribute(attribute);
|
|
2254
2290
|
if(htmlAttributeValue != null && typeof(htmlAttributeValue) != 'undefined'){
|
|
2255
2291
|
//这个才是在v3.9.2 后要用的,上面的留着只是为了适配以前的
|
|
2256
|
-
node.setAttribute(attribute,
|
|
2292
|
+
node.setAttribute(attribute, translate.util.textReplace(htmlAttributeValue, originalText, resultText, translate.to)); //2025.4.26 变更为此方式
|
|
2293
|
+
//node.setAttribute(attribute, htmlAttributeValue.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText)));
|
|
2257
2294
|
}
|
|
2258
2295
|
}
|
|
2259
2296
|
return result;
|
|
@@ -2301,7 +2338,8 @@ var translate = {
|
|
|
2301
2338
|
//替换渲染
|
|
2302
2339
|
if(typeof(originalText) != 'undefined' && originalText.length > 0){
|
|
2303
2340
|
//this.nodes[hash][task_index].nodeValue = this.nodes[hash][task_index].nodeValue.replace(new RegExp(translate.util.regExp.pattern(task.originalText),'g'), translate.util.regExp.resultText(task.resultText));
|
|
2304
|
-
input_value_node.nodeValue =
|
|
2341
|
+
input_value_node.nodeValue = translate.util.textReplace(input_value_node.nodeValue, originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2342
|
+
//input_value_node.nodeValue = input_value_node.nodeValue.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2305
2343
|
}
|
|
2306
2344
|
|
|
2307
2345
|
result['text'] = input_value_node.nodeValue;
|
|
@@ -2318,7 +2356,8 @@ var translate = {
|
|
|
2318
2356
|
//替换渲染
|
|
2319
2357
|
if(typeof(originalText) != 'undefined' && originalText.length > 0){
|
|
2320
2358
|
//this.nodes[hash][task_index].nodeValue = this.nodes[hash][task_index].nodeValue.replace(new RegExp(translate.util.regExp.pattern(task.originalText),'g'), translate.util.regExp.resultText(task.resultText));
|
|
2321
|
-
node.attributes['placeholder'].nodeValue = node.attributes['placeholder'].nodeValue
|
|
2359
|
+
node.attributes['placeholder'].nodeValue = translate.util.textReplace(node.attributes['placeholder'].nodeValue, originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2360
|
+
//node.attributes['placeholder'].nodeValue = node.attributes['placeholder'].nodeValue.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2322
2361
|
}
|
|
2323
2362
|
|
|
2324
2363
|
result['text'] = node.attributes['placeholder'].nodeValue;
|
|
@@ -2343,7 +2382,8 @@ var translate = {
|
|
|
2343
2382
|
//替换渲染
|
|
2344
2383
|
if(typeof(originalText) != 'undefined' && originalText != null && originalText.length > 0){
|
|
2345
2384
|
//this.nodes[hash][task_index].nodeValue = this.nodes[hash][task_index].nodeValue.replace(new RegExp(translate.util.regExp.pattern(task.originalText),'g'), translate.util.regExp.resultText(task.resultText));
|
|
2346
|
-
node.content =
|
|
2385
|
+
node.content = translate.util.textReplace(node.content, originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2386
|
+
//node.content = node.content.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2347
2387
|
}
|
|
2348
2388
|
|
|
2349
2389
|
result['text'] = node.content;
|
|
@@ -2363,7 +2403,8 @@ var translate = {
|
|
|
2363
2403
|
//替换渲染
|
|
2364
2404
|
if(typeof(originalText) != 'undefined' && originalText.length > 0){
|
|
2365
2405
|
//this.nodes[hash][task_index].nodeValue = this.nodes[hash][task_index].nodeValue.replace(new RegExp(translate.util.regExp.pattern(task.originalText),'g'), translate.util.regExp.resultText(task.resultText));
|
|
2366
|
-
node.alt =
|
|
2406
|
+
node.alt = translate.util.textReplace(node.alt, originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2407
|
+
//node.alt = node.alt.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2367
2408
|
}
|
|
2368
2409
|
result['text'] = node.alt;
|
|
2369
2410
|
return result;
|
|
@@ -2380,7 +2421,8 @@ var translate = {
|
|
|
2380
2421
|
//替换渲染
|
|
2381
2422
|
if(typeof(originalText) != 'undefined' && originalText != null && originalText.length > 0){
|
|
2382
2423
|
//this.nodes[hash][task_index].nodeValue = this.nodes[hash][task_index].nodeValue.replace(new RegExp(translate.util.regExp.pattern(task.originalText),'g'), translate.util.regExp.resultText(task.resultText));
|
|
2383
|
-
node.nodeValue =
|
|
2424
|
+
node.nodeValue = translate.util.textReplace(node.nodeValue, originalText, resultText, translate.to); //2025.4.26 变更为此方式
|
|
2425
|
+
//node.nodeValue = node.nodeValue.replace(new RegExp(translate.util.regExp.pattern(originalText),'g'), translate.util.regExp.resultText(resultText));
|
|
2384
2426
|
}
|
|
2385
2427
|
result['text'] = node.nodeValue;
|
|
2386
2428
|
}
|
|
@@ -2792,28 +2834,29 @@ var translate = {
|
|
|
2792
2834
|
}
|
|
2793
2835
|
}
|
|
2794
2836
|
|
|
2795
|
-
|
|
2796
|
-
//判断当前是否是英语及变种,也就是单词之间需要有空格的,如果前后没有空格,要补充上空格
|
|
2797
|
-
if(translate.language.wordBlankConnector(translate.to)){
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
}
|
|
2837
|
+
// 2025.4.26 优化,将不再在此处进行处理,交有 translate.util.textReplace 在页面最终渲染前处理
|
|
2838
|
+
// //判断当前是否是英语及变种,也就是单词之间需要有空格的,如果前后没有空格,要补充上空格
|
|
2839
|
+
// if(translate.language.wordBlankConnector(translate.to)){
|
|
2840
|
+
// if(wordKeyIndex > 0){
|
|
2841
|
+
// //它前面还有文本,判断它前面的文本是否是空格,如果不是,那么要补充上空格
|
|
2842
|
+
// var before = text.charAt(wordKeyIndex-1);
|
|
2843
|
+
// //console.log(before);
|
|
2844
|
+
// if(!(/\s/.test(before))){
|
|
2845
|
+
// //不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
2846
|
+
// nomenclatureValue = ' '+nomenclatureValue
|
|
2847
|
+
// }
|
|
2848
|
+
// }
|
|
2849
|
+
// if(wordKeyIndex + nomenclatureKey.length < text.length){
|
|
2850
|
+
// //它后面还有文本,判断它前面的文本是否是空格,如果不是,那么要补充上空格
|
|
2851
|
+
// var after = text.charAt(wordKeyIndex + nomenclatureKey.length);
|
|
2852
|
+
// //console.log(after);
|
|
2853
|
+
// // 2025.4.23 woodsway提出bug修复 https://gitee.com/mail_osc/translate/issues/IC34VN
|
|
2854
|
+
// if(!(/\s/.test(after))){
|
|
2855
|
+
// //不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
2856
|
+
// nomenclatureValue = nomenclatureValue+' ';
|
|
2857
|
+
// }
|
|
2858
|
+
// }
|
|
2859
|
+
// }
|
|
2817
2860
|
|
|
2818
2861
|
//如果是自定义术语的key等于value,则是属于指定的某些文本不进行翻译的情况,所以这里要单独判断一下
|
|
2819
2862
|
//console.log(nomenclatureKey+':'+nomenclatureValue);
|
|
@@ -2859,6 +2902,7 @@ var translate = {
|
|
|
2859
2902
|
}
|
|
2860
2903
|
}
|
|
2861
2904
|
|
|
2905
|
+
//console.log(textArray);
|
|
2862
2906
|
return textArray;
|
|
2863
2907
|
},
|
|
2864
2908
|
|
|
@@ -3455,7 +3499,8 @@ var translate = {
|
|
|
3455
3499
|
languageName 是当前字符串最终判定结果是什么语种。它的识别有以下特点:
|
|
3456
3500
|
1. 如果出现英语跟中文、罗曼语族、德语等混合的情况,也就是不纯粹英语的情况,那么会以其他语种为准,而不是识别为英语。不论英语字符出现的比例占多少。
|
|
3457
3501
|
2. 如果出现简体中文跟繁体中文混合的情况,那么识别为繁体中文。不论简体中文字符出现的比例占多少。
|
|
3458
|
-
|
|
3502
|
+
3. 如果出现简体中文、繁体中文、日语混合的情况,那么识别为日语。不论简体中文、繁体中文出现的比例占多少。 2025.4.19 增加
|
|
3503
|
+
4. 除了以上两种规则外,如果出现了多个语种,那么会识别为出现字符数量最多的语种当做当前句子的语种。(注意是字符数,而不是语种的数组数)
|
|
3459
3504
|
languageArray 对传入字符串进行分析,识别出都有哪些语种,每个语种的字符是什么
|
|
3460
3505
|
*
|
|
3461
3506
|
*/
|
|
@@ -3506,13 +3551,21 @@ var translate = {
|
|
|
3506
3551
|
}
|
|
3507
3552
|
}
|
|
3508
3553
|
|
|
3554
|
+
//如果简体中文跟繁体中文一起出现,那么会判断当前句子为繁体中文,将简体中文字符数置0
|
|
3509
3555
|
if(langkeys.indexOf('chinese_simplified') > -1 && langkeys.indexOf('chinese_traditional') > -1){
|
|
3510
|
-
//如果简体中文跟繁体中文一起出现,那么会判断当前句子为繁体中文。
|
|
3511
3556
|
//langkeys.splice(langkeys.indexOf('chinese_simplified'), 1);
|
|
3512
3557
|
langsNumber['chinese_simplified'] = 0;
|
|
3513
3558
|
}
|
|
3514
3559
|
|
|
3515
3560
|
|
|
3561
|
+
//如果发现日语字符,那么将发现的简体中文、繁体中文字符数量置零
|
|
3562
|
+
if(langkeys.length > 1 && langkeys.indexOf('japanese') > -1){
|
|
3563
|
+
langsNumber['chinese_simplified'] = 0;
|
|
3564
|
+
langsNumber['chinese_traditional'] = 0;
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
|
|
3568
|
+
|
|
3516
3569
|
//从 langsNumber 中找出字数最多的来
|
|
3517
3570
|
var maxLang = ''; //字数最多的语种
|
|
3518
3571
|
var maxNumber = 0;
|
|
@@ -3561,6 +3614,9 @@ var translate = {
|
|
|
3561
3614
|
japanese 日语
|
|
3562
3615
|
korean 韩语
|
|
3563
3616
|
greek 希腊语
|
|
3617
|
+
thai 泰语
|
|
3618
|
+
arabic 阿拉伯语
|
|
3619
|
+
romanian 罗马尼亚语
|
|
3564
3620
|
*/
|
|
3565
3621
|
getCharLanguage:function(charstr){
|
|
3566
3622
|
if(charstr == null || typeof(charstr) == 'undefined'){
|
|
@@ -3600,7 +3656,15 @@ var translate = {
|
|
|
3600
3656
|
if(this.greek(charstr)){
|
|
3601
3657
|
return 'greek';
|
|
3602
3658
|
}
|
|
3603
|
-
|
|
3659
|
+
if(this.thai(charstr)){
|
|
3660
|
+
return 'thai';
|
|
3661
|
+
}
|
|
3662
|
+
if(this.arabic(charstr)){
|
|
3663
|
+
return 'arabic';
|
|
3664
|
+
}
|
|
3665
|
+
if(this.romanian(charstr)){
|
|
3666
|
+
return 'romanian';
|
|
3667
|
+
}
|
|
3604
3668
|
//未识别是什么语种
|
|
3605
3669
|
//console.log('not find is language , char : '+charstr+', unicode: '+charstr.charCodeAt(0).toString(16));
|
|
3606
3670
|
return '';
|
|
@@ -3867,6 +3931,7 @@ var translate = {
|
|
|
3867
3931
|
return false;
|
|
3868
3932
|
},
|
|
3869
3933
|
//语种的单词连接符是否需要空格,比如中文简体、繁体、韩文、日语都不需要空格,则返回false, 但是像是英文的单词间需要空格进行隔开,则返回true
|
|
3934
|
+
//另外这也是区分是否使用标点符号 ,。还是 ,. 的
|
|
3870
3935
|
//如果未匹配到,默认返回true
|
|
3871
3936
|
//language:语种,传入如 english
|
|
3872
3937
|
wordBlankConnector:function(language){
|
|
@@ -3924,13 +3989,39 @@ var translate = {
|
|
|
3924
3989
|
},
|
|
3925
3990
|
//是否包含俄语
|
|
3926
3991
|
russian:function(str){
|
|
3927
|
-
|
|
3928
|
-
|
|
3992
|
+
// 正则表达式匹配俄语大小写字母(包含 Ё/ё,排除其他语言特有的西里尔字符)
|
|
3993
|
+
//АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЮюЯя
|
|
3994
|
+
if(/^[А-Яа-яЁё]$/.test(str)){
|
|
3929
3995
|
return true
|
|
3930
3996
|
} else {
|
|
3931
3997
|
return false;
|
|
3932
3998
|
}
|
|
3933
3999
|
},
|
|
4000
|
+
//是否包含泰语
|
|
4001
|
+
thai:function(str){
|
|
4002
|
+
if(/^[\u0E01-\u0E59]$/.test(str)){
|
|
4003
|
+
return true
|
|
4004
|
+
} else {
|
|
4005
|
+
return false;
|
|
4006
|
+
}
|
|
4007
|
+
},
|
|
4008
|
+
//是否包含阿拉伯语
|
|
4009
|
+
arabic:function(str){
|
|
4010
|
+
/*
|
|
4011
|
+
阿拉伯语基本区块(U+0600–U+06FF)
|
|
4012
|
+
阿拉伯语补充区块(U+0750–U+077F)
|
|
4013
|
+
*/
|
|
4014
|
+
return /^[\u0600-\u06FF\u0750-\u077F]$/.test(str);
|
|
4015
|
+
},
|
|
4016
|
+
//是否包含 罗马尼亚语
|
|
4017
|
+
romanian:function(str) {
|
|
4018
|
+
/*
|
|
4019
|
+
U+00C0–U+00FF:Latin-1 Supplement (包含带变音符号的字母,如 Ă/ă 的部分形式)
|
|
4020
|
+
U+0100–U+017F:Latin Extended-A (包含罗马尼亚语特有字母 Ă/ă、Â/â、Î/î 等);
|
|
4021
|
+
U+0218–U+021B:Latin Extended-B (包含 Ș/ș 和 Ț/ț,这是罗马尼亚语标志性字母)
|
|
4022
|
+
*/
|
|
4023
|
+
return /^[\u00C0-\u00FF\u0100-\u017F\u0218-\u021B]$/.test(str);
|
|
4024
|
+
},
|
|
3934
4025
|
//是否包含希腊语
|
|
3935
4026
|
greek:function(str){
|
|
3936
4027
|
const greekRegex = /^[\u0391-\u03A9\u03B1-\u03C9]$/;
|
|
@@ -4048,12 +4139,7 @@ var translate = {
|
|
|
4048
4139
|
return true;
|
|
4049
4140
|
}
|
|
4050
4141
|
|
|
4051
|
-
|
|
4052
|
-
//阿拉伯数字 0-9
|
|
4053
|
-
if(/.*[\u0030-\u0039]+.*$/.test(str)){
|
|
4054
|
-
return true;
|
|
4055
|
-
}
|
|
4056
|
-
*/
|
|
4142
|
+
|
|
4057
4143
|
|
|
4058
4144
|
/*
|
|
4059
4145
|
U+0020 空格
|
|
@@ -4108,132 +4194,11 @@ var translate = {
|
|
|
4108
4194
|
}
|
|
4109
4195
|
|
|
4110
4196
|
/*
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
U+00A3 £ (货币)英镑
|
|
4116
|
-
U+00A4 ¤ (货币)当货币未有符号时以此替代
|
|
4117
|
-
U+00A5 ¥ (货币)日元
|
|
4118
|
-
U+00A6 ¦ 两条断开的直线
|
|
4119
|
-
U+00A7 § 文件分不同部分
|
|
4120
|
-
U+00A8 ¨ (语言)分音
|
|
4121
|
-
U+00A9 © 版权符
|
|
4122
|
-
U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数
|
|
4123
|
-
U+00AB « 双重角形引号
|
|
4124
|
-
U+00AC ¬ 逻辑非
|
|
4125
|
-
U+00AE ® 商标
|
|
4126
|
-
U+00AF ¯ 长音
|
|
4127
|
-
U+00B0 ° 角度
|
|
4128
|
-
U+00B1 ± 正负号
|
|
4129
|
-
U+00B2 ² 二次方
|
|
4130
|
-
U+00B3 ³ 三次方
|
|
4131
|
-
U+00B4 ´ 锐音符
|
|
4132
|
-
U+00B5 µ 百万分之一,10?6
|
|
4133
|
-
U+00B6 ¶ 文章分段
|
|
4134
|
-
U+00B7 · 间隔号
|
|
4135
|
-
U+00B8 ¸ 软音符
|
|
4136
|
-
U+00B9 ¹ 一次方
|
|
4137
|
-
U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数
|
|
4138
|
-
U+00BB » 指向右的双箭头
|
|
4139
|
-
U+00BC ¼ 四分之一
|
|
4140
|
-
U+00BD ½ 二分之一
|
|
4141
|
-
U+00BE ¾ 四分之三
|
|
4142
|
-
U+00BF ¿ 倒转的问号
|
|
4143
|
-
U+00C1 Á 在拉丁字母 A 上加锐音符
|
|
4144
|
-
U+00C2 Â 在拉丁字母 A 上加抑扬符“^”
|
|
4145
|
-
U+00C3 Ã 在拉丁字母 A 上加“~”
|
|
4146
|
-
U+00C4 Ä 在拉丁字母 A 上加分音符“..”
|
|
4147
|
-
U+00C5 Å 在拉丁字母 A 上加角度符“°”
|
|
4148
|
-
U+00C6 Æ 拉丁字母 A、E 的混合
|
|
4149
|
-
U+00C7 Ç 在拉丁字母 C 下加软音符
|
|
4150
|
-
U+00C8 È 在拉丁字母 E 上加重音符
|
|
4151
|
-
U+00C9 É 在拉丁字母 E 上加锐音符
|
|
4152
|
-
U+00CA Ê 在拉丁字母 E 上加抑扬符
|
|
4153
|
-
U+00CB Ë 在拉丁字母 E 上加分音符
|
|
4154
|
-
U+00CC Ì 在拉丁字母 I 上加重音符
|
|
4155
|
-
U+00CD Í 在拉丁字母 I 上加锐音符
|
|
4156
|
-
U+00CE Î 在拉丁字母 I 上加抑扬符
|
|
4157
|
-
U+00CF Ï 在拉丁字母 I 上加分音符
|
|
4158
|
-
U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用
|
|
4159
|
-
U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~”
|
|
4160
|
-
U+00D2 Ò 在拉丁字母 O 上加重音符
|
|
4161
|
-
U+00D3 Ó 在拉丁字母 O 上加锐音符
|
|
4162
|
-
U+00D4 Ô 在拉丁字母 O 上加抑扬符
|
|
4163
|
-
U+00D5 Õ 在拉丁字母 O 上加波浪纹“~”
|
|
4164
|
-
U+00D6 Ö 在拉丁字母 O 上加分音符
|
|
4165
|
-
U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键
|
|
4166
|
-
U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/”
|
|
4167
|
-
U+00D9 Ù 在拉丁字母 U 上加重音符
|
|
4168
|
-
U+00DA Ú 在拉丁字母 U 上加锐音符
|
|
4169
|
-
U+00DB Û 在拉丁字母 U 上加抑扬符
|
|
4170
|
-
U+00DC Ü 在拉丁字母 U 上加分音符
|
|
4171
|
-
U+00DD Ý 在拉丁字母 Y 上加锐音符
|
|
4172
|
-
U+00DE Þ 古拉丁字母,现已被“Th”取替
|
|
4173
|
-
U+00DF ß 德文字母
|
|
4174
|
-
U+00E0 à 在拉丁字母 a 上加重音符
|
|
4175
|
-
U+00E1 á 在拉丁字母 a 上加锐音符
|
|
4176
|
-
U+00E2 â 在拉丁字母 a 上加抑扬符
|
|
4177
|
-
U+00E3 ã 在拉丁字母 a 上加波浪纹“~”
|
|
4178
|
-
U+00E4 ä 在拉丁字母 a 上加分音符
|
|
4179
|
-
U+00E5 å 在拉丁字母 a 上加角度符“°”
|
|
4180
|
-
U+00E6 æ 拉丁字母 a、e 的混合
|
|
4181
|
-
U+00E7 ç 在拉丁字母 c 下加软音符
|
|
4182
|
-
U+00E8 è 在拉丁字母 e 上加锐音符
|
|
4183
|
-
U+00E9 é 在拉丁字母 e 上加重音符
|
|
4184
|
-
U+00EA ê 在拉丁字母 e 上加抑扬符
|
|
4185
|
-
U+00EB ë 在拉丁字母 e 上加分音符
|
|
4186
|
-
U+00EC ì 在拉丁字母 i 上加重音符
|
|
4187
|
-
U+00ED í 在拉丁字母 i 上加锐音符
|
|
4188
|
-
U+00EE î 在拉丁字母 i 上加抑扬符
|
|
4189
|
-
U+00EF ï 在拉丁字母 i 上加分音符
|
|
4190
|
-
U+00F0 ð 古拉丁字母
|
|
4191
|
-
U+00F1 ñ 在拉丁字母 n 上加波浪纹“~”
|
|
4192
|
-
U+00F2 ò 在拉丁字母 o 上加重音符
|
|
4193
|
-
U+00F3 ó 在拉丁字母 o 上加锐音符
|
|
4194
|
-
U+00F4 ô 在拉丁字母 o 上加抑扬符
|
|
4195
|
-
U+00F5 õ 在拉丁字母 o 上加波浪纹“~”
|
|
4196
|
-
U+00F6 ö 在拉丁字母 o 上加分音符
|
|
4197
|
-
U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键
|
|
4198
|
-
U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/”
|
|
4199
|
-
U+00F9 ù 在拉丁字母 u 上加重音符
|
|
4200
|
-
U+00FA ú 在拉丁字母 u 上加锐音符
|
|
4201
|
-
U+00FB ? 在拉丁字母 u 上加抑扬符
|
|
4202
|
-
U+00FC ü 在拉丁字母 u 上加分音符
|
|
4203
|
-
U+00FD ý 在拉丁字母 y 上加锐音符
|
|
4204
|
-
U+00FE þ 古拉丁字母,现已被“th”取替
|
|
4205
|
-
U+00FF ü 在拉丁字母 u 上加分音符
|
|
4206
|
-
拉丁字母(扩展 A)
|
|
4207
|
-
代码 显示 描述
|
|
4208
|
-
U+0100 Ā 在拉丁字母 A 上加长音符
|
|
4209
|
-
U+0101 ā 在拉丁字母 a 上加长音符
|
|
4210
|
-
U+0102 Ă 在拉丁字母 A 上加短音符
|
|
4211
|
-
U+0103 ă 在拉丁字母 a 上加短音符
|
|
4212
|
-
U+0104 Ą 在拉丁字母 A 上加反尾形符
|
|
4213
|
-
U+0105 ą 在拉丁字母 a 上加反尾形符
|
|
4214
|
-
拉丁字母(扩展 C)
|
|
4215
|
-
代码 显示 描述
|
|
4216
|
-
U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=”
|
|
4217
|
-
U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=”
|
|
4218
|
-
U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~”
|
|
4219
|
-
U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-”
|
|
4220
|
-
U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴
|
|
4221
|
-
U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/”
|
|
4222
|
-
U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/”
|
|
4223
|
-
U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴
|
|
4224
|
-
U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴
|
|
4225
|
-
U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴
|
|
4226
|
-
U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴
|
|
4227
|
-
U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴
|
|
4228
|
-
U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴
|
|
4229
|
-
U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾
|
|
4230
|
-
U+2C75 Ⱶ 拉丁字母“H”的左半部
|
|
4231
|
-
U+2C76 ⱶ 拉丁字母“h”的左半部
|
|
4232
|
-
U+2C77 ⱷ 希腊字母“φ”的上半部
|
|
4197
|
+
这些字符主要是 罕见的拉丁字母变体 ,通常用于:
|
|
4198
|
+
某些非洲语言或方言;
|
|
4199
|
+
古文字、语音学符号;
|
|
4200
|
+
特殊排版或装饰性字体。
|
|
4233
4201
|
*/
|
|
4234
|
-
if(/.*[\u00A1-\u0105]+.*$/.test(str)){
|
|
4235
|
-
return true;
|
|
4236
|
-
}
|
|
4237
4202
|
if(/.*[\u2C60-\u2C77]+.*$/.test(str)){
|
|
4238
4203
|
return true;
|
|
4239
4204
|
}
|
|
@@ -4244,7 +4209,8 @@ var translate = {
|
|
|
4244
4209
|
/*
|
|
4245
4210
|
文本翻译的替换。
|
|
4246
4211
|
|
|
4247
|
-
|
|
4212
|
+
@Deprecated 2025.4.26 最新的在 translate.util.textReplace
|
|
4213
|
+
|
|
4248
4214
|
text: 原始文本,翻译的某句或者某个词就在这个文本之中
|
|
4249
4215
|
translateOriginal: 翻译的某个词或句,在翻译之前的文本
|
|
4250
4216
|
translateResult: 翻译的某个词或句,在翻译之后的文本,翻译结果
|
|
@@ -4255,56 +4221,12 @@ var translate = {
|
|
|
4255
4221
|
使用此方法:
|
|
4256
4222
|
var text = '你世好word世界';
|
|
4257
4223
|
var translateOriginal = '世';
|
|
4258
|
-
var translateResult = '
|
|
4224
|
+
var translateResult = '世杰'; //翻译结果
|
|
4259
4225
|
translate.language.textTranslateReplace(text, translateOriginal, translateResult, 'english');
|
|
4260
|
-
|
|
4226
|
+
|
|
4261
4227
|
*/
|
|
4262
4228
|
textTranslateReplace:function(text, translateOriginal, translateResult, language){
|
|
4263
|
-
|
|
4264
|
-
return text;
|
|
4265
|
-
}
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
let replaceResultText = ''+translateResult; //要替换的结果文本(这个文本可能前面有加空格或者后面有加空格的)
|
|
4269
|
-
|
|
4270
|
-
if(translate.language.wordBlankConnector(translate.to)){
|
|
4271
|
-
let originalIndex = text.indexOf(translateOriginal); //翻译之前,翻译的单词在字符串中的其实坐标(0开始)
|
|
4272
|
-
//console.log("originalIndex: "+originalIndex);
|
|
4273
|
-
|
|
4274
|
-
//要先判断后面,不然先判断前面,加了后它的长度就又变了
|
|
4275
|
-
|
|
4276
|
-
//判断它后面是否还有文本
|
|
4277
|
-
if(originalIndex+1 < text.length){
|
|
4278
|
-
let char = text.charAt(originalIndex+translateOriginal.length);
|
|
4279
|
-
//console.log(char);
|
|
4280
|
-
if(!(/\s/.test(char))){
|
|
4281
|
-
//不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
4282
|
-
//text = text.replace(translateOriginal, translateResult+' ');
|
|
4283
|
-
replaceResultText = replaceResultText + ' ';
|
|
4284
|
-
}
|
|
4285
|
-
}
|
|
4286
|
-
|
|
4287
|
-
//判断它前面是否还有文本
|
|
4288
|
-
if(originalIndex > 0){
|
|
4289
|
-
let char = text.charAt(originalIndex-1);
|
|
4290
|
-
//console.log(char);
|
|
4291
|
-
if(!(/\s/.test(char))){
|
|
4292
|
-
//不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
4293
|
-
//text = text.replace(translateOriginal, ' '+translateResult);
|
|
4294
|
-
replaceResultText = ' '+replaceResultText;
|
|
4295
|
-
}
|
|
4296
|
-
}
|
|
4297
|
-
}
|
|
4298
|
-
let resultText = text.replace(translateOriginal, replaceResultText);
|
|
4299
|
-
|
|
4300
|
-
if(resultText.indexOf(translateOriginal) > -1){
|
|
4301
|
-
//还有第二个、第三个单词一样,也要替换
|
|
4302
|
-
//console.log(this);
|
|
4303
|
-
resultText = this.textTranslateReplace(resultText, translateOriginal, translateResult, language);
|
|
4304
|
-
}
|
|
4305
|
-
|
|
4306
|
-
//console.log(resultText);
|
|
4307
|
-
return resultText;
|
|
4229
|
+
return translate.util.textReplace(text, translateOriginal, translateResult, language);
|
|
4308
4230
|
}
|
|
4309
4231
|
},
|
|
4310
4232
|
//用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。
|
|
@@ -4334,6 +4256,138 @@ var translate = {
|
|
|
4334
4256
|
},
|
|
4335
4257
|
|
|
4336
4258
|
util:{
|
|
4259
|
+
/*
|
|
4260
|
+
文本替换,将替换完毕的结果返回
|
|
4261
|
+
自定义术语等都是通过这个来进行替换
|
|
4262
|
+
2025.4.26 从 language 中 拿到这里
|
|
4263
|
+
|
|
4264
|
+
text: 原始文本,翻译的某句或者某个词就在这个文本之中
|
|
4265
|
+
translateOriginal: 翻译的某个词或句,在翻译之前的文本
|
|
4266
|
+
translateResult: 翻译的某个词或句,在翻译之后的文本,翻译结果
|
|
4267
|
+
language: 显示的语种,这里是对应的 translateResult 这个文本的语种。 也就是最终替换之后要显示给用户的语种。比如将中文翻译为英文,这里也就是英文。 这里会根据显示的语种不同,来自主决定是否前后加空格进行分割。 另外这里传入的语种也是 translate.js 的语种标识
|
|
4268
|
+
|
|
4269
|
+
(注意,如果 translateResult 中发现 translateOriginal 的存在,将不进行任何处理,因为没必要了,还会造成死循环。直接将 text 返回)
|
|
4270
|
+
|
|
4271
|
+
使用此方法:
|
|
4272
|
+
var text = '你世好word世界';
|
|
4273
|
+
var translateOriginal = '世';
|
|
4274
|
+
var translateResult = '世杰'; //翻译结果
|
|
4275
|
+
translate.language.textTranslateReplace(text, translateOriginal, translateResult, 'english');
|
|
4276
|
+
|
|
4277
|
+
*/
|
|
4278
|
+
textReplace:function(text, translateOriginal, translateResult, language){
|
|
4279
|
+
|
|
4280
|
+
//如果要替换的源文本直接就是整个文本,那也就不用在做什么判断了,直接将 翻译的结果文本返回就好了
|
|
4281
|
+
if(text == translateOriginal){
|
|
4282
|
+
return translateResult;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
//当前替换后,替换结果结束位置的下标。
|
|
4286
|
+
//一开始还没进行替换,那么这个下标就是 0
|
|
4287
|
+
//比如 你好吗 中的 好 替换为 "好的" 那最后结果为 "你好的吗" ,这里是 “的” 的下标 2
|
|
4288
|
+
let currentReplaceEndIndex = 0;
|
|
4289
|
+
|
|
4290
|
+
//while最大循环次数30次,免得出现未知异常导致死循环
|
|
4291
|
+
let maxWhileNumber = 30;
|
|
4292
|
+
|
|
4293
|
+
//因为text中可能有多个位置要被替换,所以使用循环
|
|
4294
|
+
while(text.indexOf(translateOriginal, currentReplaceEndIndex) > -1 && maxWhileNumber-- > 0){
|
|
4295
|
+
//console.log('text:'+text+'\tcurrentReplaceEndIndex:'+currentReplaceEndIndex);
|
|
4296
|
+
|
|
4297
|
+
//要替换的结果文本(这个文本可能前面有加空格或者后面有加空格的)
|
|
4298
|
+
let replaceResultText = ''+translateResult;
|
|
4299
|
+
//替换的文本 ,这里有可能会追加上某些标点符号,所以单独也列出来,而不是使用方法中传入的 translateOriginal
|
|
4300
|
+
let replaceOriginalText = '' + translateOriginal;
|
|
4301
|
+
|
|
4302
|
+
//根据不同的语种,如果有的语种需要加空格来进行区分单词,那么也要进行空格的判定
|
|
4303
|
+
if(translate.language.wordBlankConnector(translate.to)){
|
|
4304
|
+
let originalIndex = text.indexOf(translateOriginal, currentReplaceEndIndex); //翻译之前,翻译的单词在字符串中的起始坐标(0开始)
|
|
4305
|
+
//console.log("originalIndex: "+originalIndex);
|
|
4306
|
+
|
|
4307
|
+
//要先判断后面,不然先判断前面,加了后它的长度就又变了
|
|
4308
|
+
|
|
4309
|
+
//判断它后面是否还有文本
|
|
4310
|
+
if(originalIndex+1 < text.length){
|
|
4311
|
+
let char = text.charAt(originalIndex+translateOriginal.length);
|
|
4312
|
+
//console.log(char);
|
|
4313
|
+
if(/。/.test(char)){
|
|
4314
|
+
replaceResultText = replaceResultText + '. ';
|
|
4315
|
+
replaceOriginalText = translateOriginal + '。';
|
|
4316
|
+
}else if(/,/.test(char)){
|
|
4317
|
+
replaceResultText = replaceResultText + ', ';
|
|
4318
|
+
replaceOriginalText = translateOriginal + ',';
|
|
4319
|
+
}else if(!(/\s/.test(char))){
|
|
4320
|
+
//不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
4321
|
+
//text = text.replace(translateOriginal, translateResult+' ');
|
|
4322
|
+
replaceResultText = replaceResultText + ' ';
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
|
|
4326
|
+
//判断它前面是否还有文本
|
|
4327
|
+
if(originalIndex > 0){
|
|
4328
|
+
let char = text.charAt(originalIndex-1);
|
|
4329
|
+
//console.log(char);
|
|
4330
|
+
if(!(/\s/.test(char))){
|
|
4331
|
+
//不是空白字符,补充上一个空格,用于将两个单词隔开
|
|
4332
|
+
//text = text.replace(translateOriginal, ' '+translateResult);
|
|
4333
|
+
replaceResultText = ' '+replaceResultText;
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
}else{
|
|
4337
|
+
//如果是其他语种比如英语法语翻译为中文、日文,那么标点符号也要判断的,这个因为目前这个场景还没咋遇到,就不判断了,遇到了在加。
|
|
4338
|
+
|
|
4339
|
+
}
|
|
4340
|
+
|
|
4341
|
+
let replaceResult = translate.util.replaceFromIndex(text, currentReplaceEndIndex, replaceOriginalText, replaceResultText);
|
|
4342
|
+
if(replaceResult.replaceEndIndex < 1){
|
|
4343
|
+
console.log('while中已经 indexOf发现了,但是实际没有替换,出现异常了!理论上这是不应该出现的。 text:'+text+' , translateOriginal:'+translateOriginal);
|
|
4344
|
+
}else{
|
|
4345
|
+
currentReplaceEndIndex = replaceResult.replaceEndIndex;
|
|
4346
|
+
text = replaceResult.text;
|
|
4347
|
+
}
|
|
4348
|
+
|
|
4349
|
+
}
|
|
4350
|
+
|
|
4351
|
+
//console.log(resultText);
|
|
4352
|
+
return text;
|
|
4353
|
+
},
|
|
4354
|
+
/*
|
|
4355
|
+
js 的 replace 能力,这个是可以指定从第几个字符开始进行replace
|
|
4356
|
+
1. 这里可以 replaceText 本身包含着 originalText
|
|
4357
|
+
2. originalText 可以出现多次
|
|
4358
|
+
|
|
4359
|
+
@param
|
|
4360
|
+
text 要进行替换的原始文本
|
|
4361
|
+
index 要从 text 的哪个下标开始。 (第一个字符下标是0)
|
|
4362
|
+
originalText 要替换的文本,被替换的文本
|
|
4363
|
+
replaceText 替换为的文本,将 originalText 替换为什么
|
|
4364
|
+
replaceFromIndex('你好吗?你也好?', 0, '你', '你是谁');
|
|
4365
|
+
|
|
4366
|
+
@return 对象
|
|
4367
|
+
text 替换的结果
|
|
4368
|
+
replaceEndIndex 当前替换后,替换结果结束位置的下标。
|
|
4369
|
+
如果没进行替换,那么这个下标就是 0
|
|
4370
|
+
比如 你好吗 中的 好 替换为 "好的" 那最后结果为 "你好的吗" ,这里是 “的” 的下标 2
|
|
4371
|
+
*/
|
|
4372
|
+
replaceFromIndex:function(text, index, originalText, replaceText){
|
|
4373
|
+
const before = text.slice(0, index);
|
|
4374
|
+
const after = text.slice(index);
|
|
4375
|
+
const originalTextIndex = after.indexOf(originalText);
|
|
4376
|
+
if(originalTextIndex > -1){
|
|
4377
|
+
const replacedAfter = after.replace(originalText, replaceText);
|
|
4378
|
+
return {
|
|
4379
|
+
text: before + replacedAfter,
|
|
4380
|
+
replaceEndIndex: index + originalTextIndex + replaceText.length
|
|
4381
|
+
}
|
|
4382
|
+
}else{
|
|
4383
|
+
//没有发现可替换的字符,那么就原样返回
|
|
4384
|
+
return {
|
|
4385
|
+
text: before + replacedAfter,
|
|
4386
|
+
replaceEndIndex: 0
|
|
4387
|
+
};
|
|
4388
|
+
}
|
|
4389
|
+
},
|
|
4390
|
+
|
|
4337
4391
|
/* 生成一个随机UUID,复制于 https://gitee.com/mail_osc/kefu.js */
|
|
4338
4392
|
uuid:function() {
|
|
4339
4393
|
var d = new Date().getTime();
|
|
@@ -5100,6 +5154,7 @@ var translate = {
|
|
|
5100
5154
|
//console.log('response------');
|
|
5101
5155
|
//console.log(xhr);
|
|
5102
5156
|
},
|
|
5157
|
+
|
|
5103
5158
|
/*
|
|
5104
5159
|
速度检测控制中心, 检测主备翻译接口的响应速度进行排列,真正请求时,按照排列的顺序进行请求
|
|
5105
5160
|
v2.8.2增加
|
|
@@ -5146,6 +5201,16 @@ var translate = {
|
|
|
5146
5201
|
hostQueueIndex:-1, //当前使用的 hostQueue的数组下标, -1表示还未初始化赋予值,不可直接使用,通过 getHostQueueIndex() 使用
|
|
5147
5202
|
disableTime:1000000, //不可用的时间,storage中存储的 speedDetectionControl_hostQueue 其中 time 这里,如果值是 这个,便是代表这个host处于不可用状态
|
|
5148
5203
|
|
|
5204
|
+
/*
|
|
5205
|
+
设置当前使用的翻译通道 host
|
|
5206
|
+
适用于 进行中时,中途切临时换翻译通道。
|
|
5207
|
+
*/
|
|
5208
|
+
setCurrentHost:function(host){
|
|
5209
|
+
translate.storage.set('speedDetectionControl_hostQueue','');
|
|
5210
|
+
translate.request.api.host=host;
|
|
5211
|
+
translate.request.speedDetectionControl.checkHostQueue = new Array();
|
|
5212
|
+
translate.request.speedDetectionControl.checkResponseSpeed_Storage(host, 0);
|
|
5213
|
+
},
|
|
5149
5214
|
|
|
5150
5215
|
//获取 host queue 队列
|
|
5151
5216
|
getHostQueue:function(){
|
|
@@ -5153,7 +5218,7 @@ var translate = {
|
|
|
5153
5218
|
//还没有,先从本地存储中取,看之前是否已经设置过了
|
|
5154
5219
|
// 只有经过真正的网络测速后,才会加入 storage 的 hostQueue
|
|
5155
5220
|
var storage_hostQueue = translate.storage.get('speedDetectionControl_hostQueue');
|
|
5156
|
-
if(storage_hostQueue == null || typeof(storage_hostQueue) == 'undefined'){
|
|
5221
|
+
if(storage_hostQueue == null || typeof(storage_hostQueue) == 'undefined' || storage_hostQueue == ''){
|
|
5157
5222
|
//本地存储中没有,也就是之前没设置过,是第一次用,那么直接讲 translate.request.api.host 赋予之
|
|
5158
5223
|
//translate.request.api.host
|
|
5159
5224
|
|
|
@@ -6136,28 +6201,34 @@ var translate = {
|
|
|
6136
6201
|
|
|
6137
6202
|
|
|
6138
6203
|
if(translate.progress.api.isTip){
|
|
6139
|
-
translate.listener.execute.renderStartByApi.push(function(uuid){
|
|
6204
|
+
translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
|
|
6140
6205
|
for(var lang in translate.nodeQueue[uuid].list){
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6206
|
+
//console.log('lang:'+lang);
|
|
6207
|
+
//console.log(translate.nodeQueue[uuid].list[lang]);
|
|
6208
|
+
if(translate.language.getCurrent() == lang){
|
|
6209
|
+
//忽略这个语种
|
|
6210
|
+
//console.log('ignore-------');
|
|
6211
|
+
continue;
|
|
6212
|
+
}
|
|
6213
|
+
|
|
6145
6214
|
for(var hash in translate.nodeQueue[uuid].list[lang]){
|
|
6146
6215
|
for(var nodeindex in translate.nodeQueue[uuid].list[lang][hash].nodes){
|
|
6147
6216
|
var node = translate.nodeQueue[uuid].list[lang][hash].nodes[nodeindex].node;
|
|
6217
|
+
//console.log(node);
|
|
6148
6218
|
var nodeParent = node.parentNode;
|
|
6149
6219
|
if(nodeParent == null){
|
|
6150
6220
|
continue;
|
|
6151
6221
|
}
|
|
6222
|
+
/* 这里先不考虑多隐藏的问题,只要符合的都隐藏,宁愿吧一些不需要隐藏的也会跟着一起隐藏
|
|
6152
6223
|
if(nodeParent.childNodes.length != 1){
|
|
6224
|
+
//这个文本节点所在的元素里,不止有这一个文本元素,还有别的文本元素
|
|
6153
6225
|
continue;
|
|
6154
6226
|
}
|
|
6155
|
-
|
|
6227
|
+
*/
|
|
6156
6228
|
if(typeof(nodeParent.className) == 'undefined' || nodeParent.className == null || nodeParent.className == ''){
|
|
6157
6229
|
nodeParent.className = ' translate_api_in_progress';
|
|
6158
6230
|
}else{
|
|
6159
6231
|
//这个元素本身有class了,那就追加
|
|
6160
|
-
|
|
6161
6232
|
if(nodeParent.className.indexOf('translate_api_in_progress') > -1){
|
|
6162
6233
|
continue;
|
|
6163
6234
|
}
|
|
@@ -6169,107 +6240,209 @@ var translate = {
|
|
|
6169
6240
|
}
|
|
6170
6241
|
}
|
|
6171
6242
|
});
|
|
6172
|
-
translate.listener.execute.renderFinishByApi.push(function(uuid){
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
continue;
|
|
6190
|
-
}
|
|
6191
|
-
*/
|
|
6243
|
+
translate.listener.execute.renderFinishByApi.push(function(uuid, from, to){
|
|
6244
|
+
//console.log('uuid:'+uuid+', from:'+from+', to:'+to);
|
|
6245
|
+
|
|
6246
|
+
for(var hash in translate.nodeQueue[uuid].list[from]){
|
|
6247
|
+
for(var nodeindex in translate.nodeQueue[uuid].list[from][hash].nodes){
|
|
6248
|
+
var node = translate.nodeQueue[uuid].list[from][hash].nodes[nodeindex].node;
|
|
6249
|
+
var nodeParent = node.parentNode;
|
|
6250
|
+
if(nodeParent == null){
|
|
6251
|
+
continue;
|
|
6252
|
+
}
|
|
6253
|
+
|
|
6254
|
+
/*
|
|
6255
|
+
注释这个,因为可能是给这个元素动态追加删除导致其子元素不是11
|
|
6256
|
+
if(nodeParent.childNodes.length != 1){
|
|
6257
|
+
continue;
|
|
6258
|
+
}
|
|
6259
|
+
*/
|
|
6192
6260
|
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6261
|
+
var parentClassName = nodeParent.className;
|
|
6262
|
+
if(typeof(parentClassName) == 'undefined' || parentClassName == null || parentClassName == ''){
|
|
6263
|
+
continue;
|
|
6264
|
+
}
|
|
6265
|
+
if(parentClassName.indexOf('translate_api_in_progress') < -1){
|
|
6266
|
+
continue;
|
|
6267
|
+
}
|
|
6268
|
+
|
|
6269
|
+
nodeParent.className = parentClassName.replace(/translate_api_in_progress/g, '');
|
|
6270
|
+
//nodeParent.className = parentClassName.replace(/loading/g, '');
|
|
6271
|
+
}
|
|
6272
|
+
}
|
|
6273
|
+
|
|
6206
6274
|
});
|
|
6207
6275
|
|
|
6208
6276
|
}
|
|
6209
6277
|
}
|
|
6210
6278
|
}
|
|
6211
6279
|
},
|
|
6280
|
+
|
|
6281
|
+
/*js dispose start*/
|
|
6212
6282
|
/*
|
|
6213
|
-
对js
|
|
6214
|
-
obj: 可以是JS定义的 对象、数组、甚至是单个具体的值
|
|
6283
|
+
对js对象内的值进行翻译,可以是JS定义的 对象、数组、甚至是单个具体的值
|
|
6215
6284
|
*/
|
|
6216
|
-
|
|
6285
|
+
js:{
|
|
6286
|
+
|
|
6217
6287
|
/*
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6288
|
+
jsString 传入的js对象的字符串格式
|
|
6289
|
+
targetLanguage 翻译为的目标语言
|
|
6290
|
+
successFunction 执行成功后触发,传入格式 function(obj){ console.log(obj); } 其中 obj 是翻译之后的结果
|
|
6291
|
+
failureFunction 执行失败后触发,传入格式 function(failureInfo){ console.log(failureInfo); } 其中 failureInfo 是失败原因
|
|
6292
|
+
|
|
6293
|
+
示例:
|
|
6294
|
+
|
|
6295
|
+
var str = `
|
|
6296
|
+
{
|
|
6297
|
+
"hello":"你好",
|
|
6298
|
+
"word":"单词",
|
|
6299
|
+
"你是谁": [
|
|
6300
|
+
"世界",
|
|
6301
|
+
"大海"
|
|
6302
|
+
]
|
|
6303
|
+
}
|
|
6304
|
+
`
|
|
6305
|
+
translate.js.transString(str,'english',function(obj){ console.log(obj); }, function(failureInfo){ console.log(failureInfo); });
|
|
6306
|
+
|
|
6221
6307
|
*/
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
//console.log(`${parentKey}: ${obj}`);
|
|
6260
|
-
if(typeof(kvs[obj]) == 'undefined'){
|
|
6261
|
-
kvs[obj] = new Array();
|
|
6262
|
-
}
|
|
6263
|
-
kvs[obj].push('not key');
|
|
6264
|
-
}
|
|
6308
|
+
transString: function (jsString, targetLanguage, successFunction, failureFunction) {
|
|
6309
|
+
let jsObject;
|
|
6310
|
+
try{
|
|
6311
|
+
jsObject = JSON.parse(jsString);
|
|
6312
|
+
}catch(e){
|
|
6313
|
+
failureFunction(e);
|
|
6314
|
+
return;
|
|
6315
|
+
}
|
|
6316
|
+
translate.js.transObject(jsObject, targetLanguage, successFunction, failureFunction);
|
|
6317
|
+
},
|
|
6318
|
+
|
|
6319
|
+
/*
|
|
6320
|
+
jsObject 传入的js对象,支持对象、数组等
|
|
6321
|
+
targetLanguage 翻译为的目标语言
|
|
6322
|
+
successFunction 执行成功后触发,传入格式 function(obj){ console.log(obj); } 其中 obj 是翻译之后的结果
|
|
6323
|
+
failureFunction 执行失败后触发,传入格式 function(failureInfo){ console.log(failureInfo); } 其中 failureInfo 是失败原因
|
|
6324
|
+
|
|
6325
|
+
示例:
|
|
6326
|
+
|
|
6327
|
+
var obj = {
|
|
6328
|
+
"hello":"你好",
|
|
6329
|
+
"word":"单词",
|
|
6330
|
+
"世界":["世界","大海"]
|
|
6331
|
+
};
|
|
6332
|
+
translate.js.transObject(obj,'english',function(obj){ console.log(obj); }, function(failureInfo){ console.log(failureInfo); });
|
|
6333
|
+
|
|
6334
|
+
*/
|
|
6335
|
+
transObject: function (jsObject, targetLanguage, successFunction, failureFunction) {
|
|
6336
|
+
let kvs = translate.js.find(jsObject);
|
|
6337
|
+
//console.log(JSON.stringify(kvs, null, 2));
|
|
6338
|
+
|
|
6339
|
+
/**** 第二步,将文本值进行翻译 ***/
|
|
6340
|
+
//先将其 kvs 的key 取出来
|
|
6341
|
+
var texts = new Array();
|
|
6342
|
+
for (const key in kvs) {
|
|
6343
|
+
texts.push(key);
|
|
6344
|
+
}
|
|
6265
6345
|
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6346
|
+
var obj = {
|
|
6347
|
+
from:'auto',
|
|
6348
|
+
to: targetLanguage,
|
|
6349
|
+
texts: texts
|
|
6350
|
+
}
|
|
6351
|
+
translate.request.translateText(obj, function (data) {
|
|
6352
|
+
//打印翻译结果
|
|
6353
|
+
//console.log(data);
|
|
6354
|
+
if(typeof(data.result) == 'undefined' || data.result == 0){
|
|
6355
|
+
failureFunction('network connect failure');
|
|
6356
|
+
return;
|
|
6357
|
+
}
|
|
6358
|
+
if(data.result == 0){
|
|
6359
|
+
failureFunction(data.info);
|
|
6360
|
+
return;
|
|
6361
|
+
}
|
|
6362
|
+
|
|
6363
|
+
/**** 第三步,将翻译结果赋予 jsObject ***/
|
|
6364
|
+
const translatedTexts = data.text; // 获取翻译结果数组
|
|
6365
|
+
if (translatedTexts && translatedTexts.length === texts.length) {
|
|
6366
|
+
texts.forEach((originalText, index) => {
|
|
6367
|
+
const translatedText = translatedTexts[index]; // 根据索引获取翻译结果
|
|
6368
|
+
const paths = kvs[originalText]; // 获取该文本的路径数组
|
|
6369
|
+
if (paths && paths.length > 0) {
|
|
6370
|
+
paths.forEach(path => {
|
|
6371
|
+
translate.js.setValueByPath(jsObject, path, translatedText); // 更新 jsObject
|
|
6372
|
+
});
|
|
6373
|
+
}
|
|
6374
|
+
});
|
|
6375
|
+
} else {
|
|
6376
|
+
console.error("翻译结果长度不匹配或为空");
|
|
6377
|
+
}
|
|
6378
|
+
successFunction(jsObject);
|
|
6379
|
+
//console.log("翻译后的 jsObject:", jsObject);
|
|
6380
|
+
});
|
|
6381
|
+
},
|
|
6382
|
+
setValueByPath: function(obj, path, value){
|
|
6383
|
+
const parts = path.replace(/\[(\d+)\]/g, '.$1').split('.');
|
|
6384
|
+
let current = obj;
|
|
6385
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
6386
|
+
current = current[parts[i]];
|
|
6387
|
+
}
|
|
6388
|
+
current[parts[parts.length - 1]] = value;
|
|
6389
|
+
},
|
|
6390
|
+
/*
|
|
6391
|
+
对js对象进行翻译
|
|
6392
|
+
obj: 可以是JS定义的 对象、数组、甚至是单个具体的值
|
|
6393
|
+
|
|
6394
|
+
var obj = {
|
|
6395
|
+
"hello":"你好",
|
|
6396
|
+
"word":"单词",
|
|
6397
|
+
"世界":["世界","大海"]
|
|
6398
|
+
};
|
|
6399
|
+
translate.js.find(obj);
|
|
6400
|
+
|
|
6401
|
+
*/
|
|
6402
|
+
find: function (obj, parentKey = '') {
|
|
6403
|
+
let kvs = {};
|
|
6404
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
6405
|
+
if (Array.isArray(obj)) {
|
|
6406
|
+
obj.forEach((item, index) => {
|
|
6407
|
+
const currentKey = parentKey ? `${parentKey}[${index}]` : `[${index}]`;
|
|
6408
|
+
const subKvs = translate.js.find(item, currentKey);
|
|
6409
|
+
for (const [text, paths] of Object.entries(subKvs)) {
|
|
6410
|
+
if (!kvs[text]) {
|
|
6411
|
+
kvs[text] = [];
|
|
6412
|
+
}
|
|
6413
|
+
kvs[text] = kvs[text].concat(paths);
|
|
6414
|
+
}
|
|
6415
|
+
});
|
|
6416
|
+
} else {
|
|
6417
|
+
for (const key in obj) {
|
|
6418
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
|
6419
|
+
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
6420
|
+
const subKvs = translate.js.find(obj[key], currentKey);
|
|
6421
|
+
for (const [text, paths] of Object.entries(subKvs)) {
|
|
6422
|
+
if (!kvs[text]) {
|
|
6423
|
+
kvs[text] = [];
|
|
6424
|
+
}
|
|
6425
|
+
kvs[text] = kvs[text].concat(paths);
|
|
6426
|
+
}
|
|
6427
|
+
} else if (typeof obj[key] === 'string') {
|
|
6428
|
+
if (typeof kvs[obj[key]] === 'undefined') {
|
|
6429
|
+
kvs[obj[key]] = [];
|
|
6430
|
+
}
|
|
6431
|
+
kvs[obj[key]].push(currentKey);
|
|
6432
|
+
}
|
|
6433
|
+
}
|
|
6434
|
+
}
|
|
6435
|
+
} else if (typeof obj === 'string') {
|
|
6436
|
+
if (typeof kvs[obj] === 'undefined') {
|
|
6437
|
+
kvs[obj] = [];
|
|
6438
|
+
}
|
|
6439
|
+
kvs[obj].push(parentKey);
|
|
6440
|
+
}
|
|
6441
|
+
return kvs;
|
|
6442
|
+
}
|
|
6443
|
+
},
|
|
6444
|
+
/*js dispose end*/
|
|
6269
6445
|
|
|
6270
|
-
return kvs;
|
|
6271
|
-
}
|
|
6272
|
-
/*jsObject end*/
|
|
6273
6446
|
|
|
6274
6447
|
|
|
6275
6448
|
}
|