i18n-jsautotranslate 3.13.0 → 3.13.6

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.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/index.js +224 -33
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -275,8 +275,9 @@ tcdn是translate.js 的高级版本,它的能力是让你原本的网站可以
275
275
  如果您在使用过程中遇到任何异常情况,请详细说一下您遇到的问题。如果可以,请写下您的网站,以便我们可以更全面地测试,以便快速找到问题所在
276
276
  作者微信:xnx3com(使用交流可加QQ群进行,我看微信很不及时)
277
277
  Telegram : [untran](https://t.me/untran)
278
+ 交流QQ群:240567964
278
279
  交流QQ群:181781514 (已满)
279
- 交流QQ群:641047127
280
+ 交流QQ群:641047127 (已满)
280
281
  微信公众号:wangmarket
281
282
  github: [https://github.com/xnx3/translate](https://github.com/xnx3/translate)
282
283
  gitee: [https://gitee.com/mail_osc/translate](https://gitee.com/mail_osc/translate)
package/index.js CHANGED
@@ -3,8 +3,10 @@
3
3
  国际化,网页自动翻译。
4
4
  作者:管雷鸣
5
5
  开原仓库:https://github.com/xnx3/translate
6
-
7
6
  */
7
+ if(typeof(translate) == 'object' && typeof(translate.version) == 'string'){
8
+ throw new Error('translate.js 已经加载过一次了,当前是重复加载,避免你的翻译出现异常,已帮你拦截此次加载。本信息只是给你一个提示,你可以检查一下你的项目中是否出现了重复引入 translate.js ,当然,这个异常并不会影响到你的具体使用,它已经自动帮你处理拦截了这个异常,只不过提示出来是让你知道,你的代码里出现了重复引入的情况。');
9
+ }
8
10
  var translate = {
9
11
  /**
10
12
  * 当前的版本
@@ -12,7 +14,7 @@ var translate = {
12
14
  * 格式:major.minor.patch.date
13
15
  */
14
16
  // AUTO_VERSION_START
15
- version: '3.13.0.20250124',
17
+ version: '3.13.6.20250217',
16
18
  // AUTO_VERSION_END
17
19
  /*
18
20
  当前使用的版本,默认使用v2. 可使用 setUseVersion2();
@@ -606,7 +608,7 @@ var translate = {
606
608
  //console.log('beforeChar:'+beforeChar+', str:'+str)
607
609
  var lang = translate.language.getCharLanguage(beforeChar);
608
610
  //console.log(lang);
609
- if(lang == 'english'){
611
+ if(lang == 'english' || lang == 'romance'){
610
612
  //调出,不能强拆
611
613
  continue;
612
614
  }
@@ -621,7 +623,7 @@ var translate = {
621
623
  //后面有别的字符,判断是什么字符,如果是英文,那么这个是不能被拆分的,要忽略
622
624
  afterChar = str.substr(index+originalText.length,1);
623
625
  var lang = translate.language.getCharLanguage(afterChar);
624
- if(lang == 'english'){
626
+ if(lang == 'english' || lang == 'romance'){
625
627
  //跳出,不能强拆
626
628
  continue;
627
629
  }
@@ -865,6 +867,18 @@ var translate = {
865
867
  if(document.readyState == 'complete'){
866
868
  //dom加载完成,进行启动
867
869
  clearInterval(translate.temp_linstenerStartInterval);//停止
870
+
871
+ //如果不需要翻译的情况,是不需要进行监听的
872
+ if(translate.language.getCurrent() == translate.language.getLocal()){
873
+ if(translate.language.translateLocal){
874
+ //本地语种也要强制翻译跟本地语种不一致的语种
875
+ }else{
876
+ //console.log('本地语种跟目标语种一致,不进行翻译操作,无需监听。');
877
+ return;
878
+ }
879
+ }
880
+
881
+ //console.log('进行监听。。');
868
882
  translate.listener.addListener();
869
883
  }
870
884
 
@@ -1757,7 +1771,7 @@ var translate = {
1757
1771
  //console.log(translate.nodeQueue[uuid]['list'][lang]);
1758
1772
  //console.log(firstScan);
1759
1773
  for(var ti=0; ti<twoScan.length; ti++){
1760
- twoHash = twoScan[ti];
1774
+ var twoHash = twoScan[ti];
1761
1775
  //console.log(twoHash + '-- '+firstScan.indexOf(twoHash));
1762
1776
  if(firstScan.indexOf(twoHash) == -1){
1763
1777
  //需要追加了
@@ -1925,6 +1939,11 @@ var translate = {
1925
1939
  return;
1926
1940
  }
1927
1941
 
1942
+ if(typeof(translate.nodeQueue[uuid]) == 'undefined'){
1943
+ console.log('提示:你很可能多次引入了 translate.js 所以造成了翻译本身的数据错乱,这只是个提示,它还是会给你正常翻译的,但是你最好不要重复引入太多次 translate.js ,正常情况下只需要引入一次 translate.js 就可以了。太多的话很可能会导致你页面卡顿');
1944
+ return;
1945
+ }
1946
+
1928
1947
  //console.log('-----待翻译3:----');
1929
1948
  //console.log(translate.nodeQueue);
1930
1949
 
@@ -3311,8 +3330,8 @@ var translate = {
3311
3330
  ]
3312
3331
  ]
3313
3332
  }
3314
- languageName 是当前字符串是什么语种。它的识别有以下特点:
3315
- 1. 如果出现英语跟中文、法语、德语等混合的情况,也就是不纯粹英语的情况,那么会以其他语种为准,而不是识别为英语。不论英语字符出现的比例占多少。
3333
+ languageName 是当前字符串最终判定结果是什么语种。它的识别有以下特点:
3334
+ 1. 如果出现英语跟中文、罗曼语族、德语等混合的情况,也就是不纯粹英语的情况,那么会以其他语种为准,而不是识别为英语。不论英语字符出现的比例占多少。
3316
3335
  2. 如果出现简体中文跟繁体中文混合的情况,那么识别为繁体中文。不论简体中文字符出现的比例占多少。
3317
3336
  3. 除了以上两种规则外,如果出现了多个语种,那么会识别为出现字符数量最多的语种当做当前句子的语种。(注意是字符数,而不是语种的数组数)
3318
3337
  languageArray 对传入字符串进行分析,识别出都有哪些语种,每个语种的字符是什么
@@ -3341,16 +3360,28 @@ var translate = {
3341
3360
  //过滤 语种的字符数小于总字符数 百分之五的,低于这个数,将忽略
3342
3361
  var langkeys = [];
3343
3362
  for(var lang in langsNumber){
3344
- if(langsNumber[lang]/allNumber > 0.05){
3363
+ if(langsNumber[lang]/allNumber > 0.01){
3345
3364
  langkeys[langkeys.length] = lang+'';
3346
3365
  }
3347
3366
  }
3348
3367
 
3349
-
3350
3368
  if(langkeys.length > 1 && langkeys.indexOf('english') > -1){
3351
- //console.log('出现了english, 并且english跟其他语种一起出现,那么删除english,因为什么法语德语乱七八糟的都有英语。而且中文跟英文一起,如果认为是英文的话,有时候中文会不被翻译');
3352
- //langkeys.splice(langkeys.indexOf('english'), 1);
3353
- langsNumber['english'] = 0;
3369
+ //console.log('出现了english, 并且english跟其他语种一起出现那么删除english,因为什么法语德语乱七八糟的都有英语。而且中文跟英文一起,如果认为是英文的话,有时候中文会不被翻译');
3370
+ //这里先判断一下是否有发现了 罗曼语族
3371
+ if(langkeys.indexOf('romance') > -1){
3372
+ //发现了,那么判断一下到底是 法语、西班牙语、葡萄牙语、意大利语 中的哪一种呢
3373
+ var romanceSentenceLanguage = translate.language.romanceSentenceAnaly(str);
3374
+ if(romanceSentenceLanguage.length == 0){
3375
+ console.log('语种识别异常,应该是 法语、西班牙语、葡萄牙语、意大利语 中的一种才是,除非是除了这四种语种之外的别的 罗曼语族 中的语种,当前已将 '+ str +'识别为英语。 你可以联系我们求助 https://translate.zvo.cn/4030.html');
3376
+ }else{
3377
+ //console.log(langsNumber);
3378
+ langsNumber[romanceSentenceLanguage] = langsNumber['romance']+langsNumber['english'];
3379
+ //console.log('set romance to '+romanceSentenceLanguage+' : \t'+str);
3380
+ langsNumber['english'] = 0;
3381
+ }
3382
+ }else{
3383
+ langsNumber['english'] = 0;
3384
+ }
3354
3385
  }
3355
3386
 
3356
3387
  if(langkeys.indexOf('chinese_simplified') > -1 && langkeys.indexOf('chinese_traditional') > -1){
@@ -3396,7 +3427,18 @@ var translate = {
3396
3427
 
3397
3428
  return result;
3398
3429
  },
3399
- // 传入一个char,返回这个char属于什么语种,返回如 chinese_simplified、english 如果返回空字符串,那么表示未获取到是什么语种
3430
+ /*
3431
+ 传入一个char,返回这个char属于什么语种,返回如 如果返回空字符串,那么表示未获取到是什么语种
3432
+ chinese_simplified 简体中文
3433
+ chinese_traditional 繁体中文
3434
+ russian 俄罗斯语
3435
+ english 英语
3436
+ romance 罗曼语族,它是 法语、西班牙语、意大利语、葡萄牙語 的集合,并不是单个语言
3437
+ specialCharacter 特殊字符,符号
3438
+ number 阿拉伯数字
3439
+ japanese 日语
3440
+ korean 韩语
3441
+ */
3400
3442
  getCharLanguage:function(charstr){
3401
3443
  if(charstr == null || typeof(charstr) == 'undefined'){
3402
3444
  return '';
@@ -3408,6 +3450,9 @@ var translate = {
3408
3450
  if(this.english(charstr)){
3409
3451
  return 'english';
3410
3452
  }
3453
+ if(this.romance(charstr)){
3454
+ return 'romance';
3455
+ }
3411
3456
  if(this.specialCharacter(charstr)){
3412
3457
  return 'specialCharacter';
3413
3458
  }
@@ -3735,16 +3780,6 @@ var translate = {
3735
3780
  return '';
3736
3781
  }
3737
3782
  },
3738
- //是否包含英文,true:包含
3739
- english:function(str){
3740
- if(/.*[\u0041-\u005a]+.*$/.test(str)){
3741
- return true;
3742
- } else if(/.*[\u0061-\u007a]+.*$/.test(str)){
3743
- return true;
3744
- } else {
3745
- return false;
3746
- }
3747
- },
3748
3783
  //是否包含日语,true:包含
3749
3784
  japanese:function(str){
3750
3785
  if(/.*[\u3040-\u309F\u30A0-\u30FF]+.*$/.test(str)){
@@ -3777,7 +3812,73 @@ var translate = {
3777
3812
  }
3778
3813
  return false;
3779
3814
  },
3780
-
3815
+ //是否包含英文,true:包含
3816
+ english:function(str){
3817
+ if(/.*[\u0041-\u005a]+.*$/.test(str)){
3818
+ return true;
3819
+ } else if(/.*[\u0061-\u007a]+.*$/.test(str)){
3820
+ return true;
3821
+ } else {
3822
+ return false;
3823
+ }
3824
+ },
3825
+ //是否包含 罗曼语族 的特殊字符,因为 法语、西班牙语、意大利语、葡萄牙語 都属于这个语族,单纯判断特殊字符已经不能判断出到底属于哪个语种了
3826
+ romance_dict:['é','è','ê','à','ç','œ','ñ','á','ó','ò','ì','ã','õ'],
3827
+ romance:function(str){
3828
+ if(this.romance_dict.indexOf(str) > -1){
3829
+ return true;
3830
+ } else {
3831
+ return false;
3832
+ }
3833
+ },
3834
+ //对 罗曼语族 的句子进行分析,看它是属于 法语、西班牙语、意大利语、葡萄牙語 的哪个。注意这个是传入的整体的句子,不是传入的单个字符
3835
+ //返回识别的语种: french、spanish、italian、portuguese 如果都没有识别出来,则返回空字符串
3836
+ romanceSentenceAnaly:function(text) {
3837
+ // 定义各语言的典型字母/符号权重 (可调整)
3838
+ const langFeatures = {
3839
+ 'french': { score:0 , chars: ['é','è','ê','à','ç','œ'] },
3840
+ 'spanish': { score:0 , chars: ['ñ','á','ó'], pairs: ['ll'] },
3841
+ 'italian': { score:0 , chars: ['ò','ì'], pairs: ['cc', 'ss'] },
3842
+ 'portuguese': { score:0 , chars: ['ã', 'õ'] }
3843
+ };
3844
+
3845
+ // 逐字扫描 + 相邻配对检测
3846
+ for (let i=0; i<text.length; i++) {
3847
+ const char = text[i].toLowerCase();
3848
+
3849
+ // 单字匹配
3850
+ Object.keys(langFeatures).forEach(lang => {
3851
+ if (langFeatures[lang].chars.includes(char)) {
3852
+ langFeatures[lang].score +=1;
3853
+ }
3854
+ });
3855
+
3856
+ // 双字配对检测 (如 ll)
3857
+ if(i < text.length -1) {
3858
+ const pair = text.slice(i,i+2).toLowerCase();
3859
+ Object.keys(langFeatures).forEach(lang => {
3860
+ const pairs = langFeatures[lang].pairs;
3861
+ if (pairs && pairs.includes(pair)) {
3862
+ langFeatures[lang].score += 2; // pair权重大于单字
3863
+ }
3864
+ });
3865
+ }
3866
+ }
3867
+
3868
+ // 结果判定 (取最高分)
3869
+ let maxLang = '';
3870
+ let maxScore = -1;
3871
+
3872
+ Object.keys(langFeatures).forEach(lang =>{
3873
+ if(langFeatures[lang].score > maxScore){
3874
+ maxScore = langFeatures[lang].score;
3875
+ maxLang = lang;
3876
+ }
3877
+ });
3878
+
3879
+ return maxLang || '';
3880
+ },
3881
+
3781
3882
  //是否包含特殊字符,包含,则是true
3782
3883
  specialCharacter:function(str){
3783
3884
  //如:① ⑴ ⒈
@@ -4234,14 +4335,19 @@ var translate = {
4234
4335
  },
4235
4336
  /**
4236
4337
  * 将一个 JSONArray 数组,按照文字长度进行拆分。
4237
- * 比如传入的 array 数组的文字长度是6200,传入的 size 是2000,那么就是将 array 数组拆分为多个长度不超出2000的数组返回。
4338
+ * 比如传入的 array 数组的文字长度是6200,传入的 stringLength 是2000,那么就是将 array 数组拆分为多个长度不超出2000的数组返回。
4339
+ * 如果传入了 maxSize = 5 那么会对拆分后的数组的长度进行判断,如果数组内元素超过5,那么还要进行缩短,拆分后的数组不允许超过这个数
4340
+ * 也就是拆分后的数组有两重限制,一是限制转化为文本形式的长度、再就是拆分后本身数组的大小。
4341
+ *
4238
4342
  * 注意,这个长度是指 array.toString() 后的长度,也就是包含了 [""] 这种符号的长度
4239
4343
  * @param array 要被拆分的数组,其内都是String类型,传入格式如 ["你好","世界"]
4240
- * @param size 要被拆分的长度
4344
+ * @param stringLength 要被拆分的数组转化为字符串之后的长度
4345
+ * @param maxSize 被拆分的数组最大包含多少个,数组大小最大允许多大,要小于等于这个数。 如果设置为0则是不启用这个,不对拆分后的数组进行判断。
4241
4346
  * @return 被拆分后的数组列表
4242
4347
  * @author 刘晓腾
4243
4348
  */
4244
- split:function(array, size) {
4349
+ split:function(array, size, maxSize) {
4350
+ let orgsize = size;
4245
4351
  let list = [];
4246
4352
  // 数组长度小于size,直接进行返回
4247
4353
  if(JSON.stringify(array).length <= size) {
@@ -4299,10 +4405,10 @@ var translate = {
4299
4405
  // 看看是否以引号开头,如果不是,需要拼两个引号
4300
4406
  if (s.startsWith("\"")) {
4301
4407
  // 拼一个引号,-1
4302
- endIndex = s.length() - 1;
4408
+ endIndex = s.length - 1;
4303
4409
  } else {
4304
4410
  // 拼两个引号,-2
4305
- endIndex = s.length() - 2;
4411
+ endIndex = s.length - 2;
4306
4412
  }
4307
4413
  if (!s.endsWith("\"")) {
4308
4414
  // 开始不是逗号了,不能-1
@@ -4339,8 +4445,94 @@ var translate = {
4339
4445
  }
4340
4446
  }
4341
4447
  }
4448
+ // 设置了maxSize,进行处理
4449
+ if (maxSize && maxSize > 0) {
4450
+ list = translate.util._splitMaxSize(list, orgsize, maxSize);
4451
+ }
4342
4452
  return list;
4343
4453
  },
4454
+ /**
4455
+ * 针对split函数中maxSize的处理
4456
+ * private
4457
+ * @param array 已拆分的二维数组
4458
+ * @param size 拆分的长度
4459
+ * @param maxSize 元素数量
4460
+ * @author 刘晓腾
4461
+ */
4462
+ _splitMaxSize:function(array, size, maxSize) {
4463
+ // console.log("------ splitMaxSize run ------")
4464
+
4465
+ // 返回的数据
4466
+ let list = [];
4467
+ // 暂存的数组,用来存储每次遍历时超出的数据
4468
+ let tmp = [];
4469
+
4470
+ // 遍历二维数组
4471
+ array.forEach(function(arr, index) {
4472
+ // 累加数组
4473
+ arr = tmp.concat(arr);
4474
+ // 计算元素数量
4475
+ let length = arr.length;
4476
+ // 数组中元素数量大于maxSize,对多余的元素进行移除
4477
+ if (length > maxSize) {
4478
+ // 第一个数组,包含前N个元素
4479
+ let firstArray = arr.slice(0, maxSize);
4480
+ // 第二个数组,包含剩下的元素
4481
+ let secondArray = arr.slice(maxSize);
4482
+
4483
+ // 处理长度
4484
+ let len = 1;
4485
+ while (JSON.stringify(firstArray).length > size) {
4486
+ // 长度超过限制,进行处理
4487
+ firstArray = arr.slice(0, maxSize - len);
4488
+ secondArray = arr.slice(maxSize - len);
4489
+ len++;
4490
+ if (len >= arr.length+1) {
4491
+ break;
4492
+ }
4493
+ }
4494
+
4495
+ // 第一个数组记录
4496
+ list.push(firstArray);
4497
+ // 第二个数组暂存
4498
+ tmp.length = 0;
4499
+ tmp = secondArray;
4500
+ } else {
4501
+ // 没超,只处理长度
4502
+ // 处理长度
4503
+ let firstArray = arr;
4504
+ let secondArray = [];
4505
+ let len = 1;
4506
+ while (JSON.stringify(firstArray).length > size) {
4507
+ // 长度超过限制,进行处理
4508
+ firstArray = arr.slice(0, maxSize - len);
4509
+ secondArray = arr.slice(maxSize - len);
4510
+ len++;
4511
+ if (len >= arr.length+1) {
4512
+ break;
4513
+ }
4514
+ }
4515
+
4516
+ // 第一个数组记录
4517
+ list.push(firstArray);
4518
+ // 第二个数组暂存
4519
+ tmp.length = 0;
4520
+ tmp = secondArray;
4521
+ }
4522
+
4523
+ });
4524
+
4525
+ // 临时数组中还有元素,也要进行处理
4526
+ if (tmp.length > 0) {
4527
+ let tmpl = [];
4528
+ tmpl.push(tmp);
4529
+ // 递归处理
4530
+ let l = translate.util._splitMaxSize(tmpl, size, maxSize);
4531
+ list = list.concat(l);
4532
+ }
4533
+
4534
+ return list;
4535
+ },
4344
4536
  /*
4345
4537
  浏览器的语种标识跟translate.js的语种标识的对应
4346
4538
  key: 浏览器的语种标识
@@ -4358,6 +4550,7 @@ var translate = {
4358
4550
  'nl':'dutch',
4359
4551
  'yo':'yoruba',
4360
4552
  'en':'english',
4553
+ 'en-US':'english',
4361
4554
  'kok':'gongen',
4362
4555
  'la':'latin',
4363
4556
  'ne':'nepali',
@@ -4543,10 +4736,8 @@ var translate = {
4543
4736
  */
4544
4737
  translate:function(path, data, func, abnormalFunc){
4545
4738
  var textArray = JSON.parse(decodeURIComponent(data.text));
4546
- let translateTextArray = translate.util.split(textArray, 48000);
4547
- //console.log(translateTextArray);
4739
+ let translateTextArray = translate.util.split(textArray, 40000, 900);
4548
4740
 
4549
-
4550
4741
  translate.request.send(translate.service.edge.api.auth, {}, function(auth){
4551
4742
  var from = translate.service.edge.language.getMap()[data.from];
4552
4743
  var to = translate.service.edge.language.getMap()[data.to];
@@ -5112,7 +5303,7 @@ var translate = {
5112
5303
 
5113
5304
  if(typeof(obj) == 'string'){
5114
5305
  //案例一的场景,传入单个字符串
5115
- texts[0] = [obj];
5306
+ texts[0] = obj;
5116
5307
  }else{
5117
5308
  //不是字符串了,而是对象了,判断是案例二还是案例三
5118
5309
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18n-jsautotranslate",
3
- "version": "3.13.0",
3
+ "version": "3.13.6",
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": {