From 954734b8265fa9ba182fc5506ac92b7d146f2a2c Mon Sep 17 00:00:00 2001 From: xnx3 Date: Sat, 7 Jan 2023 19:35:51 +0800 Subject: [PATCH 01/37] add translate --- component/pear/module/translate.js | 1434 ++++++++++++++++++++++++++++ component/pear/pear.js | 11 +- index.html | 1 + 3 files changed, 1444 insertions(+), 2 deletions(-) create mode 100644 component/pear/module/translate.js diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js new file mode 100644 index 0000000..12fcb88 --- /dev/null +++ b/component/pear/module/translate.js @@ -0,0 +1,1434 @@ +layui.define(function(exports){ + //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 + /** + * 国际化,网页自动翻译。 + * 整理人:管雷鸣 + */ + var translate = { + /* + * 当前的版本 + */ + version:'2.1.5.20230107', + useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 + setUseVersion2:function(){ + this.useVersion = 'v2'; + }, + /* + * 翻译的对象,也就是 new google.translate.TranslateElement(...) + */ + translate:null, + /* + * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr + * 已废弃,请使用 translate.selectLanguageTag.languages + */ + includedLanguages:'zh-CN,zh-TW,en', + /* + * 资源文件url的路径 + */ + resourcesUrl:'//res.zvo.cn/translate', + + /** + * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 + */ + selectLanguageTag:{ + /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ + show:true, + /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ + languages:'zh-CN,zh-TW,en', + render:function(){ //v2增加 + + //判断如果不显示select选择语言,直接就隐藏掉 + if(!translate.selectLanguageTag.show){ + return; + } + + //判断translate 的id是否存在,不存在就创建一个 + if(document.getElementById('translate') == null){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); + }else{ + //存在,那么判断一下 select是否存在,要是存在就不重复创建了 + if(document.getElementById('translateSelectLanguage') != null){ + //select存在了,就不重复创建了 + return; + } + } + + //从服务器加载支持的语言库 + translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ + if(data.result == 0){ + console.log('load language list error : '+data.info); + return; + } + + //select的onchange事件 + var onchange = function(event){ + var language = event.target.value; + translate.changeLanguage(language); + } + + //创建 select 标签 + var selectLanguage = document.createElement("select"); + selectLanguage.id = 'translateSelectLanguage'; + selectLanguage.className = 'translateSelectLanguage'; + for(var i = 0; i 0 + //已经创建过了,存在 + selectId = 'translate'; + } + + translate.translate = new google.translate.TranslateElement( + { + //这参数没用,请忽略 + pageLanguage: 'zh-CN', + //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi + //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', + includedLanguages: translate.selectLanguageTag.languages, + //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ + layout: 0, + //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 + //autoDisplay: false, + //disableAutoTranslation:false, + //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 + }, + selectId //触发按钮的id + ); + }, + + /** + * 初始化,如加载js、css资源 + */ + init:function(){ + /****** 先判断当前协议,定义资源路径 ******/ + var protocol = window.location.protocol; + if(window.location.protocol == 'file:'){ + //本地的,那就用http + protocol = 'http:'; + } + if(this.resourcesUrl.indexOf('://') == -1){ + //还没设置过,进行设置 + this.resourcesUrl = protocol + this.resourcesUrl; + } + + //this.resourcesUrl = 'file://G:/git/translate'; + + }, + /** + * 执行翻译操作 + */ + execute_v1:function(){ + /*********** 判断translate 的id是否存在,不存在就创建一个 */ + if(document.getElementById('translate') == null){ + if(translate.selectLanguageTag.show){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); + } + } + + /* 处理1.0 - 1.1 升级的 */ + if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ + /* 用户1.0版本设置过这个,那么就以这个为主 */ + translate.selectLanguageTag.languages = translate.includedLanguages; + console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); + } + + + /****** 先加载资源 ******/ + var head0 = document.getElementsByTagName('head')[0]; + var script = document.createElement("script"); //创建一个script标签 + script.type = "text/javascript"; + //script.async = true; + script.src = this.resourcesUrl+'/js/element.js'; + head0.appendChild(script); + }, + + /** + * 设置Cookie,失效时间一年。 + * @param name + * @param value + */ + setCookie:function (name,value){ + var cookieString=name+"="+escape(value); + document.cookie=cookieString; + }, + + //获取Cookie。若是不存再,返回空字符串 + getCookie:function (name){ + var strCookie=document.cookie; + var arrCookie=strCookie.split("; "); + for(var i=0;i 0){ + return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); + }else{ + return translate.localLanguage; + } + }, + + /** + * 切换语言,比如切换为英语、法语 + * @param languageName 要切换的语言语种。传入如 en、zh-CN + * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 + * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 + */ + changeLanguage:function(languageName){ + //判断使用的是否是v1.x + var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; + if(v1.indexOf(','+languageName+',') > -1){ + //用的是v1.x + + translate.check(); + + var googtrans = '/'+translate.localLanguage+'/'+languageName; + + //先清空泛解析域名的设置 + var s = document.location.host.split('.'); + if(s.length > 2){ + var fanDomain = s[s.length-2]+'.'+s[s.length-1]; + document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; + document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; + } + + translate.setCookie('googtrans', ''+googtrans); + location.reload(); + return; + } + + //用的是v2.x或更高 + this.setUseVersion2(); + this.to = languageName; + translate.storage.set('to',languageName); //设置目标翻译语言 + location.reload(); //刷新页面 + }, + + /** + * 自检提示,适用于 v1.x, 在 v2.x中已废弃 + */ + check:function(){ + if(window.location.protocol == 'file:'){ + console.log('\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------'); + } + }, + + + /**************************** v2.0 */ + to:'', //翻译为的目标语言,如 english 、chinese_simplified + //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 + //如果使用后,第二次在用,那就优先以用户所选择的为主,这个就不管用了 + //默认是false,不使用,可设置true:使用 + //使用 setAutoDiscriminateLocalLanguage 进行设置 + autoDiscriminateLocalLanguage:false, + documents:[], //指定要翻译的元素的集合,可设置多个,如设置: document.getElementsByTagName('DIV') + //翻译时忽略的一些东西,比如忽略某个tag、某个class等 + ignore:{ + tag:['style', 'script', 'img', 'head', 'link', 'i', 'pre', 'code'], + class:['ignore','translateSelectLanguage'] + }, + setAutoDiscriminateLocalLanguage:function(){ + this.autoDiscriminateLocalLanguage = true; + }, + //待翻译的页面的node队列,key为 english、chinese value[ hash,value为node对象的数组 ] + nodeQueue:{}, + //指定要翻译的元素的集合,可传入一个元素或多个元素 + //如设置一个元素,可传入如: document.getElementsById('test') + //如设置多个元素,可传入如: document.getElementsByTagName('DIV') + setDocuments:function(documents){ + if (documents == null || typeof(documents) == 'undefined') { + return; + } + + if(typeof(documents.length) == 'undefined'){ + //不是数组,是单个元素 + this.documents[0] = documents; + }else{ + //是数组,直接赋予 + this.documents = documents; + } + //清空翻译队列,下次翻译时重新检索 + this.nodeQueue = {}; + }, + listener:{ + //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) + isExecuteFinish:false, + //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 + isStart:false, + //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + start:function(){ + if(translate.listener.isStart){ + //已开启了 + return; + } + + //判断是否是执行完一次了 + translate.temp_linstenerStartInterval = setInterval(function(){ + if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + if(translate.listener.isStart){ + //已开启了 + return; + } + clearInterval(translate.temp_linstenerStartInterval);//停止 + translate.listener.isStart = true; + translate.listener.addListener(); + //console.log('translate.temp_linstenerStartInterval Finish!'); + } + }, 50); + }, + //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 + addListener:function(){ + //选择需要观察变动的节点 + //const targetNode = document.getElementById('some-id'); + const targetNode = document; + // 观察器的配置(需要观察什么变动) + const config = { attributes: true, childList: true, subtree: true }; + // 当观察到变动时执行的回调函数 + const callback = function(mutationsList, observer) { + var documents = []; //有变动的元素 + + // Use traditional 'for loops' for IE 11 + for(let mutation of mutationsList) { + if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { + //多了个组件 + documents.push.apply(documents,mutation.addedNodes); + //console.log(mutation.addedNodes.nodeValue); + } + //else if (mutation.type === 'attributes') { + // console.log('The ' + mutation.attributeName + ' attribute was modified.'); + //} + } + + //console.log(documents); + if(documents.length > 0){ + //有变动,需要看看是否需要翻译 + translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 + translate.execute(); + } + }; + // 创建一个观察器实例并传入回调函数 + const observer = new MutationObserver(callback); + // 以上述配置开始观察目标节点 + observer.observe(targetNode, config); + } + }, + //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 + renderTask:class{ + constructor(){ + /* + * 任务列表 + * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 + * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 + * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 + */ + this.taskQueue = []; + + /* + * 要进行翻译的node元素, + * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 + * 二维数组,也就是value中包含的node集合 [node,node,...] + */ + this.nodeQueue = []; + } + + /** + * 向替换队列中增加替换任务 + * node:要替换的字符属于那个node元素 + * originalText:待翻译的字符 + * resultText:翻译后的结果字符 + */ + add(node, originalText, resultText){ + var hash = translate.util.hash(node.nodeValue); //node中内容的hash + + /****** 加入翻译的元素队列 */ + if(typeof(this.nodeQueue[hash]) == 'undefined'){ + this.nodeQueue[hash] = new Array(); + } + this.nodeQueue[hash].push(node); + + /****** 加入翻译的任务队列 */ + var tasks = this.taskQueue[hash]; + if(tasks == null || typeof(tasks) == 'undefined'){ + //console.log(node.nodeValue); + tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 + } + var task = new Array(); + task['originalText'] = originalText; + task['resultText'] = resultText; + tasks.push(task); + this.taskQueue[hash] = tasks; + /****** 加入翻译的任务队列 end */ + } + //进行替换渲染任务,对页面进行渲染替换翻译 + execute(){ + + //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 + for(var hash in this.taskQueue){ + var tasks = this.taskQueue[hash]; + tasks.sort(function(a,b){ + return b.originalText.length - a.originalText.length; + }); + this.taskQueue[hash] = tasks; + } + //console.log(this.taskQueue); + //console.log(this.nodeQueue); + //对nodeQueue进行翻译 + for(var hash in this.nodeQueue){ + var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务 + for(var node_index = 0; node_index < this.nodeQueue[hash].length; node_index++){ + //对这个node元素进行替换翻译字符 + for(var task_index=0; task_index 0){ + this.to = to_storage; + } + } + + //渲染select选择语言 + try{ + this.selectLanguageTag.render(); + }catch(e){ + console.log(e); + } + + //判断是否还未指定翻译的目标语言 + if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ + //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 + if(this.autoDiscriminateLocalLanguage){ + this.executeByLocalLanguage(); + } + + //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 + return; + } + + //进行翻译操作 + + //检索当前是否已经检索过翻译目标了 + if(this.nodeQueue == null || typeof(this.nodeQueue.length) == 'undefined' || this.nodeQueue.length == 0){ + var all; + if(this.documents == null || this.documents.length == 0){ + all = document.all; //如果未设置,那么翻译所有的 + }else{ + //设置了翻译指定的元素,那么赋予 + all = this.documents; + } + + for(var i = 0; i< all.length & i < 20; i++){ + var node = all[i]; + this.whileNodes(node); + } + } + + //translateTextArray[lang][0] + var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] + var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 + + for(var lang in this.nodeQueue){ //一维数组,取语言 + //console.log('lang:'+lang); //lang为english这种语言标识 + if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ + //console.log('lang is null : '+lang); + continue; + } + + translateTextArray[lang] = []; + translateHashArray[lang] = []; + + let task = new translate.renderTask(); + //二维数组,取hash、value + for(var hash in this.nodeQueue[lang]){ + //取原始的词,还未经过翻译的,需要进行翻译的词 + var originalWord = this.nodeQueue[lang][hash]['original']; + //根据hash,判断本地是否有缓存了 + var cache = this.storage.get('hash_'+translate.to+'_'+hash); + //console.log(key+', '+cache); + if(cache != null && cache.length > 0){ + //有缓存了 + //console.log('find cache:'+cache); + //console.log(this.nodeQueue[lang][hash]['nodes']); + //直接将缓存赋予 + //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ + //this.nodeQueue[lang][hash][index].nodeValue = cache; + + for(var node_index = 0; node_index < this.nodeQueue[lang][hash]['nodes'].length; node_index++){ + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; + //console.log(originalWord); + task.add(this.nodeQueue[lang][hash]['nodes'][node_index], originalWord, cache); + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); + } + //} + + continue; //跳出,不用在传入下面的翻译接口了 + } + + /* + //取出数组 + var queueNodes = this.nodeQueue[lang][hash]; + if(queueNodes.length > 0){ + //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 + var valueStr = queueNodes[0].nodeValue; + valueStr = this.util.charReplace(valueStr); + + translateTextArray[lang].push(valueStr); + translateHashArray[lang].push(hash); + } + */ + + //加入待翻译数组 + translateTextArray[lang].push(originalWord); + translateHashArray[lang].push(hash); + } + task.execute(); //执行渲染任务 + } + + + //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english + var fanyiLangs = []; + for(var lang in this.nodeQueue){ //一维数组,取语言 + if(translateTextArray[lang].length < 1){ + continue; + } + fanyiLangs.push(lang); + } + + /******* 用以记录当前是否进行完第一次翻译了 *******/ + if(!translate.listener.isExecuteFinish){ + translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 + //判断是否是执行完一次了 + translate.temp_executeFinishInterval = setInterval(function(){ + if(translate.temp_executeFinishNumber == fanyiLangs.length){ + translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 + clearInterval(translate.temp_executeFinishInterval);//停止 + //console.log('translate.execute() Finish!'); + } + }, 50); + } + + if(fanyiLangs.length == 0){ + //没有需要翻译的,直接退出 + return; + } + + //进行掉接口翻译 + for(var lang_index in fanyiLangs){ //一维数组,取语言 + var lang = fanyiLangs[lang_index]; + //console.log(lang) + if(translateTextArray[lang].length < 1){ + return; + } + + /*** 翻译开始 ***/ + var url = 'https://api.translate.zvo.cn/translate.json'; + var data = { + from:lang, + to:this.to, + //text:JSON.stringify(translateTextArray[lang]) + text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) + }; + this.request.post(url, data, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('=======ERROR START======='); + console.log(translateTextArray[data.from]); + //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); + + console.log('response : '+data.info); + console.log('=======ERROR END ======='); + translate.temp_executeFinishNumber++; //记录执行完的次数 + return; + } + + let task = new translate.renderTask(); + //遍历 translateHashArray + for(var i=0; i 0){ + for(var i = 0; i -1){ + //忽略tag + //console.log('忽略tag:'+parentNodeName); + return; + } + + /****** 判断忽略的class ******/ + var ignoreClass = false; //是否是被忽略的class,true是 + var parentNode = node.parentNode; + while(node != parentNode && parentNode != null){ + //console.log('node:'+node+', parentNode:'+parentNode); + if(parentNode.className != null){ + if(this.ignore.class.indexOf(parentNode.className) > -1){ + //发现ignore.class 当前是处于被忽略的 class + ignoreClass = true; + } + } + + parentNode = parentNode.parentNode; + } + if(ignoreClass){ + //console.log('ignore class : node:'+node.nodeValue); + return; + } + /**** 判断忽略的class结束 ******/ + + //console.log(node.nodeName+', '+node.nodeValue); + if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ + //input 输入框,要对 placeholder 做翻译 + //console.log('input---'+node.attributes); + if(node.attributes == null || typeof(node.attributes) == 'undefined'){ + return; + } + + if(typeof(node.attributes['placeholder']) != 'undefined'){ + //console.log(node.attributes['placeholder'].nodeValue); + //加入要翻译的node队列 + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; + //加入要翻译的node队列 + //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); + this.addNodeToQueue(node.attributes['placeholder']); + } + + //console.log(node.getAttribute("placeholder")); + }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ + + //过滤掉无效的值 + if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ + }else{ + return; + } + + //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); + + //console.log(node.nodeName); + //console.log(node.parentNode.nodeName); + //console.log(node.nodeValue); + //加入要翻译的node队列 + this.addNodeToQueue(node); + //translate.addNodeToQueue(translate.hash(node.nodeValue), node); + //translate.nodeQueue[translate.hash(node.nodeValue)] = node; + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; + //node.nodeValue = node.nodeValue+'|'; + + } + }, + //将发现的元素节点加入待翻译队列 + addNodeToQueue:function(node){ + if(node.nodeValue == null || node.nodeValue.length == 0){ + return; + } + var key = this.util.hash(node.nodeValue); + if(this.util.findTag(node.nodeValue)){ + console.log('find tag ignore : '+node.nodeValue); + return; + } + + //获取当前是什么语种 + var langs = this.language.get(node.nodeValue); + //console.log('langs'); + //console.log(langs); + + //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 + if(typeof(langs[translate.to]) != 'undefined'){ + delete langs[translate.to]; + } + + /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ + this.nodeQueue[lang] = new Array(); + } + //创建二维数组 + if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ + this.nodeQueue[lang][key] = new Array(); + } + */ + + for(var lang in langs) { + + //创建一维数组, key为语种,如 english + if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ + this.nodeQueue[lang] = new Array(); + } + + //遍历出该语种下有哪些词需要翻译 + for(var word_index = 0; word_index < langs[lang].length; word_index++){ + var word = langs[lang][word_index]; //要翻译的词 + var hash = this.util.hash(word); //要翻译的词的hash + + + //创建二维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) + if(this.nodeQueue[lang][hash] == null || typeof(this.nodeQueue[lang][hash]) == 'undefined'){ + this.nodeQueue[lang][hash] = new Array(); + + /* + * 创建三维数组,存放具体数据 + * key: nodes 包含了这个hash的node元素的数组集合,array 多个 + * key: original 原始的要翻译的词或句子,html加载完成但还没翻译前的文本,用于支持当前页面多次语种翻译切换而无需跳转 + */ + this.nodeQueue[lang][hash]['nodes'] = new Array(); + this.nodeQueue[lang][hash]['original'] = word; + + //其中key: nodes 是第四维数组,里面存放具体的node元素对象 + + } + + //往四维数组nodes中追加node元素 + this.nodeQueue[lang][hash]['nodes'][this.nodeQueue[lang][hash]['nodes'].length]=node; + } + + } + + + + //this.nodeQueue[lang][key][this.nodeQueue[lang][key].length]=node; //往数组中追加 + }, + + language:{ + //获取当前字符是什么语种。返回值是一个语言标识,有 chinese_simplified简体中文、japanese日语、korean韩语、 + // //会自动将特殊字符、要翻译的目标语种给过滤掉 + get:function(str){ + //将str拆分为单个char进行判断 + + var langs = new Array(); //当前字符串包含哪些语言的数组,其内如 english + var langStrs = new Array(); //存放不同语言的文本,格式如 ['english'][0] = 'hello' + + var upLangs = ''; //上一个字符的语种是什么,格式如 english + for(var i=0; i -1){ + newLangs.splice(index,1); //移除 + } + + //移除特殊字符 + var index = newLangs.indexOf('specialCharacter'); + if(index > -1){ + newLangs.splice(index,1); //移除数组中的特殊字符 + } + + if(newLangs.length > 0){ + //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) + return newLangs[0]; + }else{ + //没找到,直接返回空字符串 + return ''; + } + */ + + + //去除特殊符号 + //for(var i = 0; i<等符号 + if(/.*[\u3001-\u3036]+.*$/.test(str)){ + return true; + } + + /* + //阿拉伯数字 0-9 + if(/.*[\u0030-\u0039]+.*$/.test(str)){ + return true; + } + */ + + /* + U+0020 空格 + U+0021 ! 叹号 + U+0022 " 双引号 + U+0023 # 井号 + U+0024 $ 价钱/货币符号 + U+0025 % 百分比符号 + U+0026 & 英文“and”的简写符号 + U+0027 ' 引号 + U+0028 ( 开 左圆括号 + U+0029 ) 关 右圆括号 + U+002A * 星号 + U+002B + 加号 + U+002C , 逗号 + U+002D - 连字号/减号 + U+002E . 句号 + U+002F / 左斜杠 + U+0030 0 数字 0 + U+0031 1 数字 1 + U+0032 2 数字 2 + U+0033 3 数字 3 + U+0034 4 数字 4 + U+0035 5 数字 5 + U+0036 6 数字 6 + U+0037 7 数字 7 + U+0038 8 数字 8 + U+0039 9 数字 9 + U+003A : 冒号 + U+003B ; 分号 + U+003C < 小于符号 + U+003D = 等于号 + U+003E > 大于符号 + U+003F ? 问号 + U+0040 @ 英文“at”的简写符号 + U+0041 A 拉丁字母 A + U+0042 B 拉丁字母 B + U+0043 C 拉丁字母 C + U+0044 D 拉丁字母 D + U+0045 E 拉丁字母 E + U+0046 F 拉丁字母 F + U+0047 G 拉丁字母 G + U+0048 H 拉丁字母 H + U+0049 I 拉丁字母 I + U+004A J 拉丁字母 J + U+004B K 拉丁字母 K + U+004C L 拉丁字母 L + U+004D M 拉丁字母 M + U+004E N 拉丁字母 N + U+004F O 拉丁字母 O + U+0050 P 拉丁字母 P + U+0051 Q 拉丁字母 Q + U+0052 R 拉丁字母 R + U+0053 S 拉丁字母 S + U+0054 T 拉丁字母 T + U+0055 U 拉丁字母 U + U+0056 V 拉丁字母 V + U+0057 W 拉丁字母 W + U+0058 X 拉丁字母 X + U+0059 Y 拉丁字母 Y + U+005A Z 拉丁字母 Z + U+005B [ 开 方括号 + U+005C \ 右斜杠 + U+005D ] 关 方括号 + U+005E ^ 抑扬(重音)符号 + U+005F _ 底线 + U+0060 ` 重音符 + U+0061 a 拉丁字母 a + U+0062 b 拉丁字母 b + U+0063 c 拉丁字母 c + U+0064 d 拉丁字母 d + U+0065 e 拉丁字母 e + U+0066 f 拉丁字母 f + U+0067 g 拉丁字母 g + U+0068 h 拉丁字母 h + U+0069 i 拉丁字母 i + U+006A j 拉丁字母 j + U+006B k 拉丁字母 k + U+006C l 拉丁字母 l(L的小写) + U+006D m 拉丁字母 m + U+006E n 拉丁字母 n + U+006F o 拉丁字母 o + U+0070 p 拉丁字母 p + U+0071 q 拉丁字母 q + U+0072 r 拉丁字母 r + U+0073 s 拉丁字母 s + U+0074 t 拉丁字母 t + U+0075 u 拉丁字母 u + U+0076 v 拉丁字母 v + U+0077 w 拉丁字母 w + U+0078 x 拉丁字母 x + U+0079 y 拉丁字母 y + U+007A z 拉丁字母 z + U+007B { 开 左花括号 + U+007C | 直线 + U+007D } 关 右花括号 + U+007E ~ 波浪纹 + */ + if(/.*[\u0020-\u007e]+.*$/.test(str)){ + return true; + } + + //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 + if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ + return true; + } + if(/.*[\u2000-\u200B]+.*$/.test(str)){ + return true; + } + + /* + 拉丁字母 + 代码 显示 描述 + U+00A1 ¡ 倒转的叹号 + U+00A2 ¢ (货币单位)分钱、毫子 + U+00A3 £ (货币)英镑 + U+00A4 ¤ (货币)当货币未有符号时以此替代 + U+00A5 ¥ (货币)日元 + U+00A6 ¦ 两条断开的直线 + U+00A7 § 文件分不同部分 + U+00A8 ¨ (语言)分音 + U+00A9 © 版权符 + U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 + U+00AB « 双重角形引号 + U+00AC ¬ 逻辑非 + U+00AE ® 商标 + U+00AF ¯ 长音 + U+00B0 ° 角度 + U+00B1 ± 正负号 + U+00B2 ² 二次方 + U+00B3 ³ 三次方 + U+00B4 ´ 锐音符 + U+00B5 µ 百万分之一,10?6 + U+00B6 ¶ 文章分段 + U+00B7 · 间隔号 + U+00B8 ¸ 软音符 + U+00B9 ¹ 一次方 + U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 + U+00BB » 指向右的双箭头 + U+00BC ¼ 四分之一 + U+00BD ½ 二分之一 + U+00BE ¾ 四分之三 + U+00BF ¿ 倒转的问号 + U+00C1 Á 在拉丁字母 A 上加锐音符 + U+00C2 Â 在拉丁字母 A 上加抑扬符“^” + U+00C3 Ã 在拉丁字母 A 上加“~” + U+00C4 Ä 在拉丁字母 A 上加分音符“..” + U+00C5 Å 在拉丁字母 A 上加角度符“°” + U+00C6 Æ 拉丁字母 A、E 的混合 + U+00C7 Ç 在拉丁字母 C 下加软音符 + U+00C8 È 在拉丁字母 E 上加重音符 + U+00C9 É 在拉丁字母 E 上加锐音符 + U+00CA Ê 在拉丁字母 E 上加抑扬符 + U+00CB Ë 在拉丁字母 E 上加分音符 + U+00CC Ì 在拉丁字母 I 上加重音符 + U+00CD Í 在拉丁字母 I 上加锐音符 + U+00CE Î 在拉丁字母 I 上加抑扬符 + U+00CF Ï 在拉丁字母 I 上加分音符 + U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 + U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” + U+00D2 Ò 在拉丁字母 O 上加重音符 + U+00D3 Ó 在拉丁字母 O 上加锐音符 + U+00D4 Ô 在拉丁字母 O 上加抑扬符 + U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” + U+00D6 Ö 在拉丁字母 O 上加分音符 + U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 + U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” + U+00D9 Ù 在拉丁字母 U 上加重音符 + U+00DA Ú 在拉丁字母 U 上加锐音符 + U+00DB Û 在拉丁字母 U 上加抑扬符 + U+00DC Ü 在拉丁字母 U 上加分音符 + U+00DD Ý 在拉丁字母 Y 上加锐音符 + U+00DE Þ 古拉丁字母,现已被“Th”取替 + U+00DF ß 德文字母 + U+00E0 à 在拉丁字母 a 上加重音符 + U+00E1 á 在拉丁字母 a 上加锐音符 + U+00E2 â 在拉丁字母 a 上加抑扬符 + U+00E3 ã 在拉丁字母 a 上加波浪纹“~” + U+00E4 ä 在拉丁字母 a 上加分音符 + U+00E5 å 在拉丁字母 a 上加角度符“°” + U+00E6 æ 拉丁字母 a、e 的混合 + U+00E7 ç 在拉丁字母 c 下加软音符 + U+00E8 è 在拉丁字母 e 上加锐音符 + U+00E9 é 在拉丁字母 e 上加重音符 + U+00EA ê 在拉丁字母 e 上加抑扬符 + U+00EB ë 在拉丁字母 e 上加分音符 + U+00EC ì 在拉丁字母 i 上加重音符 + U+00ED í 在拉丁字母 i 上加锐音符 + U+00EE î 在拉丁字母 i 上加抑扬符 + U+00EF ï 在拉丁字母 i 上加分音符 + U+00F0 ð 古拉丁字母 + U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” + U+00F2 ò 在拉丁字母 o 上加重音符 + U+00F3 ó 在拉丁字母 o 上加锐音符 + U+00F4 ô 在拉丁字母 o 上加抑扬符 + U+00F5 õ 在拉丁字母 o 上加波浪纹“~” + U+00F6 ö 在拉丁字母 o 上加分音符 + U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 + U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” + U+00F9 ù 在拉丁字母 u 上加重音符 + U+00FA ú 在拉丁字母 u 上加锐音符 + U+00FB ? 在拉丁字母 u 上加抑扬符 + U+00FC ü 在拉丁字母 u 上加分音符 + U+00FD ý 在拉丁字母 y 上加锐音符 + U+00FE þ 古拉丁字母,现已被“th”取替 + U+00FF ü 在拉丁字母 u 上加分音符 + 拉丁字母(扩展 A) + 代码 显示 描述 + U+0100 Ā 在拉丁字母 A 上加长音符 + U+0101 ā 在拉丁字母 a 上加长音符 + U+0102 Ă 在拉丁字母 A 上加短音符 + U+0103 ă 在拉丁字母 a 上加短音符 + U+0104 Ą 在拉丁字母 A 上加反尾形符 + U+0105 ą 在拉丁字母 a 上加反尾形符 + 拉丁字母(扩展 C) + 代码 显示 描述 + U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” + U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” + U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” + U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” + U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 + U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” + U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” + U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 + U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 + U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 + U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 + U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 + U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 + U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 + U+2C75 Ⱶ 拉丁字母“H”的左半部 + U+2C76 ⱶ 拉丁字母“h”的左半部 + U+2C77 ⱷ 希腊字母“φ”的上半部 + */ + if(/.*[\u00A1-\u0105]+.*$/.test(str)){ + return true; + } + if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ + return true; + } + + + return false; + } + }, + //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 + //如果使用后,第二次在用,那就优先以用户所选择的为主 + executeByLocalLanguage:function(){ + this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('==== ERROR 获取当前用户所在区域异常 ===='); + console.log(data.info); + console.log('==== ERROR END ===='); + }else{ + translate.setUseVersion2(); + translate.storage.set('to',data.language); //设置目标翻译语言 + translate.to = data.language; //设置目标语言 + translate.selectLanguageTag + translate.execute(); //执行翻译 + } + }); + }, + + util:{ + //判断字符串中是否存在tag标签。 true存在 + findTag:function(str) { + var reg = /<[^>]+>/g; + return reg.test(str); + }, + //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 + arrayFindMaxNumber:function(arr){ + + // 储存每个元素出现的次数 + var numbers = {} + + // 储存出现最多次的元素 + var maxStr = [] + + // 储存最多出现的元素次数 + var maxNum = 0 + + for(var i =0,len=arr.length;imaxNum){ + maxNum = numbers[arr[i]] + } + } + + for(var item in numbers){ + if(numbers[item]===maxNum){ + maxStr.push(item) + } + } + + return maxStr; + }, + //对字符串进行hash化,目的取唯一值进行标识 + hash:function(str){ + if(str == null || typeof(str) == 'undefined'){ + return str; + } + var hash = 0, i, chr; + if (str.length === 0){ + return hash; + } + + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash+''; + }, + //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 + charReplace:function(str){ + + if(str == null){ + return ''; + } + str = str.trim(); + str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 + //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 + return str; + }, + }, + //request请求来源于 https://github.com/xnx3/request + request:{ + /** + * post请求 + * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php + * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} + * @param func 请求完成的回调,传入如 function(data){ console.log(data); } + */ + post:function(url, data, func){ + var headers = { + 'content-type':'application/x-www-form-urlencoded' + }; + this.send(url, data, func, 'post', true, headers, null); + }, + /** + * 发送请求 + * url 请求的url + * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} + * func 请求完成的回调,传入如 function(data){} + * method 请求方式,可传入 post、get + * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 + * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; + * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} + */ + send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ + //post提交的参数 + var params = ''; + if(data != null){ + for(var index in data){ + if(params.length > 0){ + params = params + '&'; + } + params = params + index + '=' + data[index]; + } + } + + var xhr=null; + try{ + xhr=new XMLHttpRequest(); + }catch(e){ + xhr=new ActiveXObject("Microsoft.XMLHTTP"); + } + //2.调用open方法(true----异步) + xhr.open(method,url,isAsynchronize); + //设置headers + if(headers != null){ + for(var index in headers){ + xhr.setRequestHeader(index,headers[index]); + } + } + xhr.send(params); + //4.请求状态改变事件 + xhr.onreadystatechange=function(){ + if(xhr.readyState==4){ + if(xhr.status==200){ + //请求正常,响应码 200 + var json = null; + try{ + json = JSON.parse(xhr.responseText); + }catch(e){ + console.log(e); + } + if(json == null){ + func(xhr.responseText); + }else{ + func(json); + } + }else{ + if(abnormalFunc != null){ + abnormalFunc(xhr); + } + } + } + } + } + }, + //存储,本地缓存 + storage:{ + set:function(key,value){ + localStorage.setItem(key,value); + }, + get:function(key){ + return localStorage.getItem(key); + } + } + + /**************************** v2.0 end */ + + } + + //默认就是用新的v2版本 + translate.setUseVersion2(); + //输出 translate 接口 + exports('translate', translate); +}); \ No newline at end of file diff --git a/component/pear/pear.js b/component/pear/pear.js index 2f19802..146c790 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -44,7 +44,14 @@ layui.config({ nprogress: "nprogress", // 进度过渡 watermark:"watermark/watermark", //水印 fullscreen:"fullscreen", //全屏组件 - popover:"popover/popover" //汽泡组件 -}).use(['layer', 'theme'], function () { + popover:"popover/popover", //汽泡组件 + translate:"translate" //多语言翻译组件 +}).use(['layer', 'theme', 'translate'], function () { layui.theme.changeTheme(window, false); + + var translate = layui.translate; + //当页面加载完后执行翻译操作 + window.onload = function () { + translate.execute(); + }; }); \ No newline at end of file diff --git a/index.html b/index.html index dd0b314..06d4405 100644 --- a/index.html +++ b/index.html @@ -33,6 +33,7 @@
    +
  • -- Gitee From 265286059499bf664e1b6eadaec201392364f39c Mon Sep 17 00:00:00 2001 From: xnx3 Date: Sat, 7 Jan 2023 19:46:44 +0800 Subject: [PATCH 02/37] =?UTF-8?q?=E5=A2=9E=E5=8A=A0css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/css/module/translate.css | 7 +++++++ component/pear/css/pear.css | 3 ++- component/pear/pear.js | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 component/pear/css/module/translate.css diff --git a/component/pear/css/module/translate.css b/component/pear/css/module/translate.css new file mode 100644 index 0000000..65a02c4 --- /dev/null +++ b/component/pear/css/module/translate.css @@ -0,0 +1,7 @@ +/* 将所有内页的切换语言都隐藏掉,只留顶部右上角一个切换语言入口 */ +#translate{ + display: none; +} +.layui-header>ul>#translate{ + display: block; +} \ No newline at end of file diff --git a/component/pear/css/pear.css b/component/pear/css/pear.css index c43e364..f6fb2ed 100644 --- a/component/pear/css/pear.css +++ b/component/pear/css/pear.css @@ -27,4 +27,5 @@ @import url("module/tab.css"); @import url("module/tag.css"); @import url("module/fullscreen.css"); -@import url("module/popover.min.css"); \ No newline at end of file +@import url("module/popover.min.css"); +@import url("module/translate.css"); \ No newline at end of file diff --git a/component/pear/pear.js b/component/pear/pear.js index 146c790..71fdd1b 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -52,6 +52,7 @@ layui.config({ var translate = layui.translate; //当页面加载完后执行翻译操作 window.onload = function () { + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 translate.execute(); }; }); \ No newline at end of file -- Gitee From 4abc2c1f0d4aa1d9d901afc7fa931b5e9e392f6e Mon Sep 17 00:00:00 2001 From: xnx3 Date: Sat, 7 Jan 2023 20:13:03 +0800 Subject: [PATCH 03/37] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/css/module/translate.css | 2 +- component/pear/module/translate.js | 1432 +---------------------- 2 files changed, 6 insertions(+), 1428 deletions(-) diff --git a/component/pear/css/module/translate.css b/component/pear/css/module/translate.css index 65a02c4..ed82b95 100644 --- a/component/pear/css/module/translate.css +++ b/component/pear/css/module/translate.css @@ -3,5 +3,5 @@ display: none; } .layui-header>ul>#translate{ - display: block; + display: inline; } \ No newline at end of file diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 12fcb88..2b4a9f2 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -1,1431 +1,9 @@ -layui.define(function(exports){ +/* + * 多语言翻译,作者:管雷鸣 + */ +layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('mod1', callback); //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - /** - * 国际化,网页自动翻译。 - * 整理人:管雷鸣 - */ - var translate = { - /* - * 当前的版本 - */ - version:'2.1.5.20230107', - useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 - setUseVersion2:function(){ - this.useVersion = 'v2'; - }, - /* - * 翻译的对象,也就是 new google.translate.TranslateElement(...) - */ - translate:null, - /* - * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr - * 已废弃,请使用 translate.selectLanguageTag.languages - */ - includedLanguages:'zh-CN,zh-TW,en', - /* - * 资源文件url的路径 - */ - resourcesUrl:'//res.zvo.cn/translate', - - /** - * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 - */ - selectLanguageTag:{ - /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ - show:true, - /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ - languages:'zh-CN,zh-TW,en', - render:function(){ //v2增加 - - //判断如果不显示select选择语言,直接就隐藏掉 - if(!translate.selectLanguageTag.show){ - return; - } - - //判断translate 的id是否存在,不存在就创建一个 - if(document.getElementById('translate') == null){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - }else{ - //存在,那么判断一下 select是否存在,要是存在就不重复创建了 - if(document.getElementById('translateSelectLanguage') != null){ - //select存在了,就不重复创建了 - return; - } - } - - //从服务器加载支持的语言库 - translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ - if(data.result == 0){ - console.log('load language list error : '+data.info); - return; - } - - //select的onchange事件 - var onchange = function(event){ - var language = event.target.value; - translate.changeLanguage(language); - } - - //创建 select 标签 - var selectLanguage = document.createElement("select"); - selectLanguage.id = 'translateSelectLanguage'; - selectLanguage.className = 'translateSelectLanguage'; - for(var i = 0; i 0 - //已经创建过了,存在 - selectId = 'translate'; - } - - translate.translate = new google.translate.TranslateElement( - { - //这参数没用,请忽略 - pageLanguage: 'zh-CN', - //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi - //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', - includedLanguages: translate.selectLanguageTag.languages, - //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ - layout: 0, - //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 - //autoDisplay: false, - //disableAutoTranslation:false, - //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 - }, - selectId //触发按钮的id - ); - }, - - /** - * 初始化,如加载js、css资源 - */ - init:function(){ - /****** 先判断当前协议,定义资源路径 ******/ - var protocol = window.location.protocol; - if(window.location.protocol == 'file:'){ - //本地的,那就用http - protocol = 'http:'; - } - if(this.resourcesUrl.indexOf('://') == -1){ - //还没设置过,进行设置 - this.resourcesUrl = protocol + this.resourcesUrl; - } - - //this.resourcesUrl = 'file://G:/git/translate'; - - }, - /** - * 执行翻译操作 - */ - execute_v1:function(){ - /*********** 判断translate 的id是否存在,不存在就创建一个 */ - if(document.getElementById('translate') == null){ - if(translate.selectLanguageTag.show){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - } - } - - /* 处理1.0 - 1.1 升级的 */ - if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ - /* 用户1.0版本设置过这个,那么就以这个为主 */ - translate.selectLanguageTag.languages = translate.includedLanguages; - console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); - } - - - /****** 先加载资源 ******/ - var head0 = document.getElementsByTagName('head')[0]; - var script = document.createElement("script"); //创建一个script标签 - script.type = "text/javascript"; - //script.async = true; - script.src = this.resourcesUrl+'/js/element.js'; - head0.appendChild(script); - }, - - /** - * 设置Cookie,失效时间一年。 - * @param name - * @param value - */ - setCookie:function (name,value){ - var cookieString=name+"="+escape(value); - document.cookie=cookieString; - }, - - //获取Cookie。若是不存再,返回空字符串 - getCookie:function (name){ - var strCookie=document.cookie; - var arrCookie=strCookie.split("; "); - for(var i=0;i 0){ - return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); - }else{ - return translate.localLanguage; - } - }, - - /** - * 切换语言,比如切换为英语、法语 - * @param languageName 要切换的语言语种。传入如 en、zh-CN - * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 - * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 - */ - changeLanguage:function(languageName){ - //判断使用的是否是v1.x - var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; - if(v1.indexOf(','+languageName+',') > -1){ - //用的是v1.x - - translate.check(); - - var googtrans = '/'+translate.localLanguage+'/'+languageName; - - //先清空泛解析域名的设置 - var s = document.location.host.split('.'); - if(s.length > 2){ - var fanDomain = s[s.length-2]+'.'+s[s.length-1]; - document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; - document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; - } - - translate.setCookie('googtrans', ''+googtrans); - location.reload(); - return; - } - - //用的是v2.x或更高 - this.setUseVersion2(); - this.to = languageName; - translate.storage.set('to',languageName); //设置目标翻译语言 - location.reload(); //刷新页面 - }, - - /** - * 自检提示,适用于 v1.x, 在 v2.x中已废弃 - */ - check:function(){ - if(window.location.protocol == 'file:'){ - console.log('\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------'); - } - }, - - - /**************************** v2.0 */ - to:'', //翻译为的目标语言,如 english 、chinese_simplified - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主,这个就不管用了 - //默认是false,不使用,可设置true:使用 - //使用 setAutoDiscriminateLocalLanguage 进行设置 - autoDiscriminateLocalLanguage:false, - documents:[], //指定要翻译的元素的集合,可设置多个,如设置: document.getElementsByTagName('DIV') - //翻译时忽略的一些东西,比如忽略某个tag、某个class等 - ignore:{ - tag:['style', 'script', 'img', 'head', 'link', 'i', 'pre', 'code'], - class:['ignore','translateSelectLanguage'] - }, - setAutoDiscriminateLocalLanguage:function(){ - this.autoDiscriminateLocalLanguage = true; - }, - //待翻译的页面的node队列,key为 english、chinese value[ hash,value为node对象的数组 ] - nodeQueue:{}, - //指定要翻译的元素的集合,可传入一个元素或多个元素 - //如设置一个元素,可传入如: document.getElementsById('test') - //如设置多个元素,可传入如: document.getElementsByTagName('DIV') - setDocuments:function(documents){ - if (documents == null || typeof(documents) == 'undefined') { - return; - } - - if(typeof(documents.length) == 'undefined'){ - //不是数组,是单个元素 - this.documents[0] = documents; - }else{ - //是数组,直接赋予 - this.documents = documents; - } - //清空翻译队列,下次翻译时重新检索 - this.nodeQueue = {}; - }, - listener:{ - //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) - isExecuteFinish:false, - //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 - isStart:false, - //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - start:function(){ - if(translate.listener.isStart){ - //已开启了 - return; - } - - //判断是否是执行完一次了 - translate.temp_linstenerStartInterval = setInterval(function(){ - if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 - if(translate.listener.isStart){ - //已开启了 - return; - } - clearInterval(translate.temp_linstenerStartInterval);//停止 - translate.listener.isStart = true; - translate.listener.addListener(); - //console.log('translate.temp_linstenerStartInterval Finish!'); - } - }, 50); - }, - //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 - addListener:function(){ - //选择需要观察变动的节点 - //const targetNode = document.getElementById('some-id'); - const targetNode = document; - // 观察器的配置(需要观察什么变动) - const config = { attributes: true, childList: true, subtree: true }; - // 当观察到变动时执行的回调函数 - const callback = function(mutationsList, observer) { - var documents = []; //有变动的元素 - - // Use traditional 'for loops' for IE 11 - for(let mutation of mutationsList) { - if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { - //多了个组件 - documents.push.apply(documents,mutation.addedNodes); - //console.log(mutation.addedNodes.nodeValue); - } - //else if (mutation.type === 'attributes') { - // console.log('The ' + mutation.attributeName + ' attribute was modified.'); - //} - } - - //console.log(documents); - if(documents.length > 0){ - //有变动,需要看看是否需要翻译 - translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 - translate.execute(); - } - }; - // 创建一个观察器实例并传入回调函数 - const observer = new MutationObserver(callback); - // 以上述配置开始观察目标节点 - observer.observe(targetNode, config); - } - }, - //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 - renderTask:class{ - constructor(){ - /* - * 任务列表 - * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 - * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 - */ - this.taskQueue = []; - - /* - * 要进行翻译的node元素, - * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 - * 二维数组,也就是value中包含的node集合 [node,node,...] - */ - this.nodeQueue = []; - } - - /** - * 向替换队列中增加替换任务 - * node:要替换的字符属于那个node元素 - * originalText:待翻译的字符 - * resultText:翻译后的结果字符 - */ - add(node, originalText, resultText){ - var hash = translate.util.hash(node.nodeValue); //node中内容的hash - - /****** 加入翻译的元素队列 */ - if(typeof(this.nodeQueue[hash]) == 'undefined'){ - this.nodeQueue[hash] = new Array(); - } - this.nodeQueue[hash].push(node); - - /****** 加入翻译的任务队列 */ - var tasks = this.taskQueue[hash]; - if(tasks == null || typeof(tasks) == 'undefined'){ - //console.log(node.nodeValue); - tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - } - var task = new Array(); - task['originalText'] = originalText; - task['resultText'] = resultText; - tasks.push(task); - this.taskQueue[hash] = tasks; - /****** 加入翻译的任务队列 end */ - } - //进行替换渲染任务,对页面进行渲染替换翻译 - execute(){ - - //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 - for(var hash in this.taskQueue){ - var tasks = this.taskQueue[hash]; - tasks.sort(function(a,b){ - return b.originalText.length - a.originalText.length; - }); - this.taskQueue[hash] = tasks; - } - //console.log(this.taskQueue); - //console.log(this.nodeQueue); - //对nodeQueue进行翻译 - for(var hash in this.nodeQueue){ - var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务 - for(var node_index = 0; node_index < this.nodeQueue[hash].length; node_index++){ - //对这个node元素进行替换翻译字符 - for(var task_index=0; task_index 0){ - this.to = to_storage; - } - } - - //渲染select选择语言 - try{ - this.selectLanguageTag.render(); - }catch(e){ - console.log(e); - } - - //判断是否还未指定翻译的目标语言 - if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ - //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 - if(this.autoDiscriminateLocalLanguage){ - this.executeByLocalLanguage(); - } - - //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 - return; - } - - //进行翻译操作 - - //检索当前是否已经检索过翻译目标了 - if(this.nodeQueue == null || typeof(this.nodeQueue.length) == 'undefined' || this.nodeQueue.length == 0){ - var all; - if(this.documents == null || this.documents.length == 0){ - all = document.all; //如果未设置,那么翻译所有的 - }else{ - //设置了翻译指定的元素,那么赋予 - all = this.documents; - } - - for(var i = 0; i< all.length & i < 20; i++){ - var node = all[i]; - this.whileNodes(node); - } - } - - //translateTextArray[lang][0] - var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] - var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 - - for(var lang in this.nodeQueue){ //一维数组,取语言 - //console.log('lang:'+lang); //lang为english这种语言标识 - if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ - //console.log('lang is null : '+lang); - continue; - } - - translateTextArray[lang] = []; - translateHashArray[lang] = []; - - let task = new translate.renderTask(); - //二维数组,取hash、value - for(var hash in this.nodeQueue[lang]){ - //取原始的词,还未经过翻译的,需要进行翻译的词 - var originalWord = this.nodeQueue[lang][hash]['original']; - //根据hash,判断本地是否有缓存了 - var cache = this.storage.get('hash_'+translate.to+'_'+hash); - //console.log(key+', '+cache); - if(cache != null && cache.length > 0){ - //有缓存了 - //console.log('find cache:'+cache); - //console.log(this.nodeQueue[lang][hash]['nodes']); - //直接将缓存赋予 - //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ - //this.nodeQueue[lang][hash][index].nodeValue = cache; - - for(var node_index = 0; node_index < this.nodeQueue[lang][hash]['nodes'].length; node_index++){ - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; - //console.log(originalWord); - task.add(this.nodeQueue[lang][hash]['nodes'][node_index], originalWord, cache); - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); - } - //} - - continue; //跳出,不用在传入下面的翻译接口了 - } - - /* - //取出数组 - var queueNodes = this.nodeQueue[lang][hash]; - if(queueNodes.length > 0){ - //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 - var valueStr = queueNodes[0].nodeValue; - valueStr = this.util.charReplace(valueStr); - - translateTextArray[lang].push(valueStr); - translateHashArray[lang].push(hash); - } - */ - - //加入待翻译数组 - translateTextArray[lang].push(originalWord); - translateHashArray[lang].push(hash); - } - task.execute(); //执行渲染任务 - } - - - //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english - var fanyiLangs = []; - for(var lang in this.nodeQueue){ //一维数组,取语言 - if(translateTextArray[lang].length < 1){ - continue; - } - fanyiLangs.push(lang); - } - - /******* 用以记录当前是否进行完第一次翻译了 *******/ - if(!translate.listener.isExecuteFinish){ - translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 - //判断是否是执行完一次了 - translate.temp_executeFinishInterval = setInterval(function(){ - if(translate.temp_executeFinishNumber == fanyiLangs.length){ - translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 - clearInterval(translate.temp_executeFinishInterval);//停止 - //console.log('translate.execute() Finish!'); - } - }, 50); - } - - if(fanyiLangs.length == 0){ - //没有需要翻译的,直接退出 - return; - } - - //进行掉接口翻译 - for(var lang_index in fanyiLangs){ //一维数组,取语言 - var lang = fanyiLangs[lang_index]; - //console.log(lang) - if(translateTextArray[lang].length < 1){ - return; - } - - /*** 翻译开始 ***/ - var url = 'https://api.translate.zvo.cn/translate.json'; - var data = { - from:lang, - to:this.to, - //text:JSON.stringify(translateTextArray[lang]) - text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) - }; - this.request.post(url, data, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('=======ERROR START======='); - console.log(translateTextArray[data.from]); - //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); - - console.log('response : '+data.info); - console.log('=======ERROR END ======='); - translate.temp_executeFinishNumber++; //记录执行完的次数 - return; - } - - let task = new translate.renderTask(); - //遍历 translateHashArray - for(var i=0; i 0){ - for(var i = 0; i -1){ - //忽略tag - //console.log('忽略tag:'+parentNodeName); - return; - } - - /****** 判断忽略的class ******/ - var ignoreClass = false; //是否是被忽略的class,true是 - var parentNode = node.parentNode; - while(node != parentNode && parentNode != null){ - //console.log('node:'+node+', parentNode:'+parentNode); - if(parentNode.className != null){ - if(this.ignore.class.indexOf(parentNode.className) > -1){ - //发现ignore.class 当前是处于被忽略的 class - ignoreClass = true; - } - } - - parentNode = parentNode.parentNode; - } - if(ignoreClass){ - //console.log('ignore class : node:'+node.nodeValue); - return; - } - /**** 判断忽略的class结束 ******/ - - //console.log(node.nodeName+', '+node.nodeValue); - if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ - //input 输入框,要对 placeholder 做翻译 - //console.log('input---'+node.attributes); - if(node.attributes == null || typeof(node.attributes) == 'undefined'){ - return; - } - - if(typeof(node.attributes['placeholder']) != 'undefined'){ - //console.log(node.attributes['placeholder'].nodeValue); - //加入要翻译的node队列 - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; - //加入要翻译的node队列 - //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); - this.addNodeToQueue(node.attributes['placeholder']); - } - - //console.log(node.getAttribute("placeholder")); - }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ - - //过滤掉无效的值 - if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ - }else{ - return; - } - - //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); - - //console.log(node.nodeName); - //console.log(node.parentNode.nodeName); - //console.log(node.nodeValue); - //加入要翻译的node队列 - this.addNodeToQueue(node); - //translate.addNodeToQueue(translate.hash(node.nodeValue), node); - //translate.nodeQueue[translate.hash(node.nodeValue)] = node; - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; - //node.nodeValue = node.nodeValue+'|'; - - } - }, - //将发现的元素节点加入待翻译队列 - addNodeToQueue:function(node){ - if(node.nodeValue == null || node.nodeValue.length == 0){ - return; - } - var key = this.util.hash(node.nodeValue); - if(this.util.findTag(node.nodeValue)){ - console.log('find tag ignore : '+node.nodeValue); - return; - } - - //获取当前是什么语种 - var langs = this.language.get(node.nodeValue); - //console.log('langs'); - //console.log(langs); - - //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 - if(typeof(langs[translate.to]) != 'undefined'){ - delete langs[translate.to]; - } - - /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ - this.nodeQueue[lang] = new Array(); - } - //创建二维数组 - if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ - this.nodeQueue[lang][key] = new Array(); - } - */ - - for(var lang in langs) { - - //创建一维数组, key为语种,如 english - if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ - this.nodeQueue[lang] = new Array(); - } - - //遍历出该语种下有哪些词需要翻译 - for(var word_index = 0; word_index < langs[lang].length; word_index++){ - var word = langs[lang][word_index]; //要翻译的词 - var hash = this.util.hash(word); //要翻译的词的hash - - - //创建二维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) - if(this.nodeQueue[lang][hash] == null || typeof(this.nodeQueue[lang][hash]) == 'undefined'){ - this.nodeQueue[lang][hash] = new Array(); - - /* - * 创建三维数组,存放具体数据 - * key: nodes 包含了这个hash的node元素的数组集合,array 多个 - * key: original 原始的要翻译的词或句子,html加载完成但还没翻译前的文本,用于支持当前页面多次语种翻译切换而无需跳转 - */ - this.nodeQueue[lang][hash]['nodes'] = new Array(); - this.nodeQueue[lang][hash]['original'] = word; - - //其中key: nodes 是第四维数组,里面存放具体的node元素对象 - - } - - //往四维数组nodes中追加node元素 - this.nodeQueue[lang][hash]['nodes'][this.nodeQueue[lang][hash]['nodes'].length]=node; - } - - } - - - - //this.nodeQueue[lang][key][this.nodeQueue[lang][key].length]=node; //往数组中追加 - }, - - language:{ - //获取当前字符是什么语种。返回值是一个语言标识,有 chinese_simplified简体中文、japanese日语、korean韩语、 - // //会自动将特殊字符、要翻译的目标语种给过滤掉 - get:function(str){ - //将str拆分为单个char进行判断 - - var langs = new Array(); //当前字符串包含哪些语言的数组,其内如 english - var langStrs = new Array(); //存放不同语言的文本,格式如 ['english'][0] = 'hello' - - var upLangs = ''; //上一个字符的语种是什么,格式如 english - for(var i=0; i -1){ - newLangs.splice(index,1); //移除 - } - - //移除特殊字符 - var index = newLangs.indexOf('specialCharacter'); - if(index > -1){ - newLangs.splice(index,1); //移除数组中的特殊字符 - } - - if(newLangs.length > 0){ - //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) - return newLangs[0]; - }else{ - //没找到,直接返回空字符串 - return ''; - } - */ - - - //去除特殊符号 - //for(var i = 0; i<等符号 - if(/.*[\u3001-\u3036]+.*$/.test(str)){ - return true; - } - - /* - //阿拉伯数字 0-9 - if(/.*[\u0030-\u0039]+.*$/.test(str)){ - return true; - } - */ - - /* - U+0020 空格 - U+0021 ! 叹号 - U+0022 " 双引号 - U+0023 # 井号 - U+0024 $ 价钱/货币符号 - U+0025 % 百分比符号 - U+0026 & 英文“and”的简写符号 - U+0027 ' 引号 - U+0028 ( 开 左圆括号 - U+0029 ) 关 右圆括号 - U+002A * 星号 - U+002B + 加号 - U+002C , 逗号 - U+002D - 连字号/减号 - U+002E . 句号 - U+002F / 左斜杠 - U+0030 0 数字 0 - U+0031 1 数字 1 - U+0032 2 数字 2 - U+0033 3 数字 3 - U+0034 4 数字 4 - U+0035 5 数字 5 - U+0036 6 数字 6 - U+0037 7 数字 7 - U+0038 8 数字 8 - U+0039 9 数字 9 - U+003A : 冒号 - U+003B ; 分号 - U+003C < 小于符号 - U+003D = 等于号 - U+003E > 大于符号 - U+003F ? 问号 - U+0040 @ 英文“at”的简写符号 - U+0041 A 拉丁字母 A - U+0042 B 拉丁字母 B - U+0043 C 拉丁字母 C - U+0044 D 拉丁字母 D - U+0045 E 拉丁字母 E - U+0046 F 拉丁字母 F - U+0047 G 拉丁字母 G - U+0048 H 拉丁字母 H - U+0049 I 拉丁字母 I - U+004A J 拉丁字母 J - U+004B K 拉丁字母 K - U+004C L 拉丁字母 L - U+004D M 拉丁字母 M - U+004E N 拉丁字母 N - U+004F O 拉丁字母 O - U+0050 P 拉丁字母 P - U+0051 Q 拉丁字母 Q - U+0052 R 拉丁字母 R - U+0053 S 拉丁字母 S - U+0054 T 拉丁字母 T - U+0055 U 拉丁字母 U - U+0056 V 拉丁字母 V - U+0057 W 拉丁字母 W - U+0058 X 拉丁字母 X - U+0059 Y 拉丁字母 Y - U+005A Z 拉丁字母 Z - U+005B [ 开 方括号 - U+005C \ 右斜杠 - U+005D ] 关 方括号 - U+005E ^ 抑扬(重音)符号 - U+005F _ 底线 - U+0060 ` 重音符 - U+0061 a 拉丁字母 a - U+0062 b 拉丁字母 b - U+0063 c 拉丁字母 c - U+0064 d 拉丁字母 d - U+0065 e 拉丁字母 e - U+0066 f 拉丁字母 f - U+0067 g 拉丁字母 g - U+0068 h 拉丁字母 h - U+0069 i 拉丁字母 i - U+006A j 拉丁字母 j - U+006B k 拉丁字母 k - U+006C l 拉丁字母 l(L的小写) - U+006D m 拉丁字母 m - U+006E n 拉丁字母 n - U+006F o 拉丁字母 o - U+0070 p 拉丁字母 p - U+0071 q 拉丁字母 q - U+0072 r 拉丁字母 r - U+0073 s 拉丁字母 s - U+0074 t 拉丁字母 t - U+0075 u 拉丁字母 u - U+0076 v 拉丁字母 v - U+0077 w 拉丁字母 w - U+0078 x 拉丁字母 x - U+0079 y 拉丁字母 y - U+007A z 拉丁字母 z - U+007B { 开 左花括号 - U+007C | 直线 - U+007D } 关 右花括号 - U+007E ~ 波浪纹 - */ - if(/.*[\u0020-\u007e]+.*$/.test(str)){ - return true; - } - - //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 - if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ - return true; - } - if(/.*[\u2000-\u200B]+.*$/.test(str)){ - return true; - } - - /* - 拉丁字母 - 代码 显示 描述 - U+00A1 ¡ 倒转的叹号 - U+00A2 ¢ (货币单位)分钱、毫子 - U+00A3 £ (货币)英镑 - U+00A4 ¤ (货币)当货币未有符号时以此替代 - U+00A5 ¥ (货币)日元 - U+00A6 ¦ 两条断开的直线 - U+00A7 § 文件分不同部分 - U+00A8 ¨ (语言)分音 - U+00A9 © 版权符 - U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 - U+00AB « 双重角形引号 - U+00AC ¬ 逻辑非 - U+00AE ® 商标 - U+00AF ¯ 长音 - U+00B0 ° 角度 - U+00B1 ± 正负号 - U+00B2 ² 二次方 - U+00B3 ³ 三次方 - U+00B4 ´ 锐音符 - U+00B5 µ 百万分之一,10?6 - U+00B6 ¶ 文章分段 - U+00B7 · 间隔号 - U+00B8 ¸ 软音符 - U+00B9 ¹ 一次方 - U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 - U+00BB » 指向右的双箭头 - U+00BC ¼ 四分之一 - U+00BD ½ 二分之一 - U+00BE ¾ 四分之三 - U+00BF ¿ 倒转的问号 - U+00C1 Á 在拉丁字母 A 上加锐音符 - U+00C2 Â 在拉丁字母 A 上加抑扬符“^” - U+00C3 Ã 在拉丁字母 A 上加“~” - U+00C4 Ä 在拉丁字母 A 上加分音符“..” - U+00C5 Å 在拉丁字母 A 上加角度符“°” - U+00C6 Æ 拉丁字母 A、E 的混合 - U+00C7 Ç 在拉丁字母 C 下加软音符 - U+00C8 È 在拉丁字母 E 上加重音符 - U+00C9 É 在拉丁字母 E 上加锐音符 - U+00CA Ê 在拉丁字母 E 上加抑扬符 - U+00CB Ë 在拉丁字母 E 上加分音符 - U+00CC Ì 在拉丁字母 I 上加重音符 - U+00CD Í 在拉丁字母 I 上加锐音符 - U+00CE Î 在拉丁字母 I 上加抑扬符 - U+00CF Ï 在拉丁字母 I 上加分音符 - U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 - U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” - U+00D2 Ò 在拉丁字母 O 上加重音符 - U+00D3 Ó 在拉丁字母 O 上加锐音符 - U+00D4 Ô 在拉丁字母 O 上加抑扬符 - U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” - U+00D6 Ö 在拉丁字母 O 上加分音符 - U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 - U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” - U+00D9 Ù 在拉丁字母 U 上加重音符 - U+00DA Ú 在拉丁字母 U 上加锐音符 - U+00DB Û 在拉丁字母 U 上加抑扬符 - U+00DC Ü 在拉丁字母 U 上加分音符 - U+00DD Ý 在拉丁字母 Y 上加锐音符 - U+00DE Þ 古拉丁字母,现已被“Th”取替 - U+00DF ß 德文字母 - U+00E0 à 在拉丁字母 a 上加重音符 - U+00E1 á 在拉丁字母 a 上加锐音符 - U+00E2 â 在拉丁字母 a 上加抑扬符 - U+00E3 ã 在拉丁字母 a 上加波浪纹“~” - U+00E4 ä 在拉丁字母 a 上加分音符 - U+00E5 å 在拉丁字母 a 上加角度符“°” - U+00E6 æ 拉丁字母 a、e 的混合 - U+00E7 ç 在拉丁字母 c 下加软音符 - U+00E8 è 在拉丁字母 e 上加锐音符 - U+00E9 é 在拉丁字母 e 上加重音符 - U+00EA ê 在拉丁字母 e 上加抑扬符 - U+00EB ë 在拉丁字母 e 上加分音符 - U+00EC ì 在拉丁字母 i 上加重音符 - U+00ED í 在拉丁字母 i 上加锐音符 - U+00EE î 在拉丁字母 i 上加抑扬符 - U+00EF ï 在拉丁字母 i 上加分音符 - U+00F0 ð 古拉丁字母 - U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” - U+00F2 ò 在拉丁字母 o 上加重音符 - U+00F3 ó 在拉丁字母 o 上加锐音符 - U+00F4 ô 在拉丁字母 o 上加抑扬符 - U+00F5 õ 在拉丁字母 o 上加波浪纹“~” - U+00F6 ö 在拉丁字母 o 上加分音符 - U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 - U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” - U+00F9 ù 在拉丁字母 u 上加重音符 - U+00FA ú 在拉丁字母 u 上加锐音符 - U+00FB ? 在拉丁字母 u 上加抑扬符 - U+00FC ü 在拉丁字母 u 上加分音符 - U+00FD ý 在拉丁字母 y 上加锐音符 - U+00FE þ 古拉丁字母,现已被“th”取替 - U+00FF ü 在拉丁字母 u 上加分音符 - 拉丁字母(扩展 A) - 代码 显示 描述 - U+0100 Ā 在拉丁字母 A 上加长音符 - U+0101 ā 在拉丁字母 a 上加长音符 - U+0102 Ă 在拉丁字母 A 上加短音符 - U+0103 ă 在拉丁字母 a 上加短音符 - U+0104 Ą 在拉丁字母 A 上加反尾形符 - U+0105 ą 在拉丁字母 a 上加反尾形符 - 拉丁字母(扩展 C) - 代码 显示 描述 - U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” - U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” - U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” - U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” - U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 - U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” - U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” - U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 - U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 - U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 - U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 - U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 - U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 - U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 - U+2C75 Ⱶ 拉丁字母“H”的左半部 - U+2C76 ⱶ 拉丁字母“h”的左半部 - U+2C77 ⱷ 希腊字母“φ”的上半部 - */ - if(/.*[\u00A1-\u0105]+.*$/.test(str)){ - return true; - } - if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ - return true; - } - - - return false; - } - }, - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主 - executeByLocalLanguage:function(){ - this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('==== ERROR 获取当前用户所在区域异常 ===='); - console.log(data.info); - console.log('==== ERROR END ===='); - }else{ - translate.setUseVersion2(); - translate.storage.set('to',data.language); //设置目标翻译语言 - translate.to = data.language; //设置目标语言 - translate.selectLanguageTag - translate.execute(); //执行翻译 - } - }); - }, - - util:{ - //判断字符串中是否存在tag标签。 true存在 - findTag:function(str) { - var reg = /<[^>]+>/g; - return reg.test(str); - }, - //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 - arrayFindMaxNumber:function(arr){ - - // 储存每个元素出现的次数 - var numbers = {} - - // 储存出现最多次的元素 - var maxStr = [] - - // 储存最多出现的元素次数 - var maxNum = 0 - - for(var i =0,len=arr.length;imaxNum){ - maxNum = numbers[arr[i]] - } - } - - for(var item in numbers){ - if(numbers[item]===maxNum){ - maxStr.push(item) - } - } - - return maxStr; - }, - //对字符串进行hash化,目的取唯一值进行标识 - hash:function(str){ - if(str == null || typeof(str) == 'undefined'){ - return str; - } - var hash = 0, i, chr; - if (str.length === 0){ - return hash; - } - - for (i = 0; i < str.length; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer - } - return hash+''; - }, - //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 - charReplace:function(str){ - - if(str == null){ - return ''; - } - str = str.trim(); - str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 - //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 - return str; - }, - }, - //request请求来源于 https://github.com/xnx3/request - request:{ - /** - * post请求 - * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php - * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} - * @param func 请求完成的回调,传入如 function(data){ console.log(data); } - */ - post:function(url, data, func){ - var headers = { - 'content-type':'application/x-www-form-urlencoded' - }; - this.send(url, data, func, 'post', true, headers, null); - }, - /** - * 发送请求 - * url 请求的url - * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} - * func 请求完成的回调,传入如 function(data){} - * method 请求方式,可传入 post、get - * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 - * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; - * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} - */ - send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ - //post提交的参数 - var params = ''; - if(data != null){ - for(var index in data){ - if(params.length > 0){ - params = params + '&'; - } - params = params + index + '=' + data[index]; - } - } - - var xhr=null; - try{ - xhr=new XMLHttpRequest(); - }catch(e){ - xhr=new ActiveXObject("Microsoft.XMLHTTP"); - } - //2.调用open方法(true----异步) - xhr.open(method,url,isAsynchronize); - //设置headers - if(headers != null){ - for(var index in headers){ - xhr.setRequestHeader(index,headers[index]); - } - } - xhr.send(params); - //4.请求状态改变事件 - xhr.onreadystatechange=function(){ - if(xhr.readyState==4){ - if(xhr.status==200){ - //请求正常,响应码 200 - var json = null; - try{ - json = JSON.parse(xhr.responseText); - }catch(e){ - console.log(e); - } - if(json == null){ - func(xhr.responseText); - }else{ - func(json); - } - }else{ - if(abnormalFunc != null){ - abnormalFunc(xhr); - } - } - } - } - } - }, - //存储,本地缓存 - storage:{ - set:function(key,value){ - localStorage.setItem(key,value); - }, - get:function(key){ - return localStorage.getItem(key); - } - } - - /**************************** v2.0 end */ - - } + var translate={version:"2.1.5.20230107",useVersion:"v1",setUseVersion2:function(){this.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",render:function(){if(translate.selectLanguageTag.show){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}this.setUseVersion2(),this.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){this.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?this.documents[0]=e:this.documents=e,this.nodeQueue={})},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.listener.isStart||(translate.temp_linstenerStartInterval=setInterval(function(){if(translate.listener.isExecuteFinish){if(translate.listener.isStart)return;clearInterval(translate.temp_linstenerStartInterval),translate.listener.isStart=!0,translate.listener.addListener()}},50))},addListener:function(){const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&(translate.setDocuments(n),translate.execute())}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodeQueue=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodeQueue[a]&&(this.nodeQueue[a]=new Array),this.nodeQueue[a].push(e);var s=this.taskQueue[a];null!=s&&void 0!==s||(s=new Array);var r=new Array;r.originalText=t,r.resultText=n,s.push(r),this.taskQueue[a]=s}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodeQueue)for(var t=this.taskQueue[e],n=0;n0&&(this.to=e)}try{this.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=this.to&&void 0!==this.to&&0!=this.to.length){if(null==this.nodeQueue||void 0===this.nodeQueue.length||0==this.nodeQueue.length){var t;t=null==this.documents||0==this.documents.length?document.all:this.documents;for(var n=0;n0)for(var c=0;c0)for(var n=0;n-1)){for(var n=!1,a=e.parentNode;e!=a&&null!=a;)null!=a.className&&this.ignore.class.indexOf(a.className)>-1&&(n=!0),a=a.parentNode;if(!n)if("INPUT"==e.nodeName||"TEXTAREA"==e.nodeName){if(null==e.attributes||void 0===e.attributes)return;void 0!==e.attributes.placeholder&&this.addNodeToQueue(e.attributes.placeholder)}else if(null!=e.nodeValue&&e.nodeValue.trim().length>0){if(!(null!=e.nodeValue&&"string"==typeof e.nodeValue&&e.nodeValue.length>0))return;this.addNodeToQueue(e)}}}},addNodeToQueue:function(e){if(null!=e.nodeValue&&0!=e.nodeValue.length){this.util.hash(e.nodeValue);if(!this.util.findTag(e.nodeValue)){var t=this.language.get(e.nodeValue);for(var n in void 0!==t[translate.to]&&delete t[translate.to],t){null!=this.nodeQueue[n]&&void 0!==this.nodeQueue[n]||(this.nodeQueue[n]=new Array);for(var a=0;a]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,s=0,r=e.length;sa&&(a=t[e[s]]);for(var l in t)t[l]===a&&n.push(l);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+i+"="+t[i];var u=null;try{u=new XMLHttpRequest}catch(e){u=new ActiveXObject("Microsoft.XMLHTTP")}if(u.open(a,e,s),null!=r)for(var i in r)u.setRequestHeader(i,r[i]);u.send(o),u.onreadystatechange=function(){if(4==u.readyState)if(200==u.status){var e=null;try{e=JSON.parse(u.responseText)}catch(e){console.log(e)}n(null==e?u.responseText:e)}else null!=l&&l(u)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); -- Gitee From 26a38885f5539d7ff878e5bbb045be49ec497b20 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Sat, 7 Jan 2023 20:20:19 +0800 Subject: [PATCH 04/37] =?UTF-8?q?=E8=B0=83=E8=AF=95js=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 1439 +++++++++++++++++++++++++++- 1 file changed, 1437 insertions(+), 2 deletions(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 2b4a9f2..8d0b934 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,8 +3,1443 @@ */ layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('mod1', callback); //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.5.20230107",useVersion:"v1",setUseVersion2:function(){this.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",render:function(){if(translate.selectLanguageTag.show){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}this.setUseVersion2(),this.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){this.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?this.documents[0]=e:this.documents=e,this.nodeQueue={})},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.listener.isStart||(translate.temp_linstenerStartInterval=setInterval(function(){if(translate.listener.isExecuteFinish){if(translate.listener.isStart)return;clearInterval(translate.temp_linstenerStartInterval),translate.listener.isStart=!0,translate.listener.addListener()}},50))},addListener:function(){const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&(translate.setDocuments(n),translate.execute())}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodeQueue=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodeQueue[a]&&(this.nodeQueue[a]=new Array),this.nodeQueue[a].push(e);var s=this.taskQueue[a];null!=s&&void 0!==s||(s=new Array);var r=new Array;r.originalText=t,r.resultText=n,s.push(r),this.taskQueue[a]=s}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodeQueue)for(var t=this.taskQueue[e],n=0;n0&&(this.to=e)}try{this.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=this.to&&void 0!==this.to&&0!=this.to.length){if(null==this.nodeQueue||void 0===this.nodeQueue.length||0==this.nodeQueue.length){var t;t=null==this.documents||0==this.documents.length?document.all:this.documents;for(var n=0;n0)for(var c=0;c0)for(var n=0;n-1)){for(var n=!1,a=e.parentNode;e!=a&&null!=a;)null!=a.className&&this.ignore.class.indexOf(a.className)>-1&&(n=!0),a=a.parentNode;if(!n)if("INPUT"==e.nodeName||"TEXTAREA"==e.nodeName){if(null==e.attributes||void 0===e.attributes)return;void 0!==e.attributes.placeholder&&this.addNodeToQueue(e.attributes.placeholder)}else if(null!=e.nodeValue&&e.nodeValue.trim().length>0){if(!(null!=e.nodeValue&&"string"==typeof e.nodeValue&&e.nodeValue.length>0))return;this.addNodeToQueue(e)}}}},addNodeToQueue:function(e){if(null!=e.nodeValue&&0!=e.nodeValue.length){this.util.hash(e.nodeValue);if(!this.util.findTag(e.nodeValue)){var t=this.language.get(e.nodeValue);for(var n in void 0!==t[translate.to]&&delete t[translate.to],t){null!=this.nodeQueue[n]&&void 0!==this.nodeQueue[n]||(this.nodeQueue[n]=new Array);for(var a=0;a]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,s=0,r=e.length;sa&&(a=t[e[s]]);for(var l in t)t[l]===a&&n.push(l);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+i+"="+t[i];var u=null;try{u=new XMLHttpRequest}catch(e){u=new ActiveXObject("Microsoft.XMLHTTP")}if(u.open(a,e,s),null!=r)for(var i in r)u.setRequestHeader(i,r[i]);u.send(o),u.onreadystatechange=function(){if(4==u.readyState)if(200==u.status){var e=null;try{e=JSON.parse(u.responseText)}catch(e){console.log(e)}n(null==e?u.responseText:e)}else null!=l&&l(u)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} - + /** + * 国际化,网页自动翻译。 + * 整理人:管雷鸣 + */ + var translate = { + /* + * 当前的版本 + */ + version:'2.1.5.20230107', + useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 + setUseVersion2:function(){ + this.useVersion = 'v2'; + }, + /* + * 翻译的对象,也就是 new google.translate.TranslateElement(...) + */ + translate:null, + /* + * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr + * 已废弃,请使用 translate.selectLanguageTag.languages + */ + includedLanguages:'zh-CN,zh-TW,en', + /* + * 资源文件url的路径 + */ + resourcesUrl:'//res.zvo.cn/translate', + + /** + * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 + */ + selectLanguageTag:{ + /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ + show:true, + /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ + languages:'zh-CN,zh-TW,en', + render:function(){ //v2增加 + + //判断如果不显示select选择语言,直接就隐藏掉 + if(!translate.selectLanguageTag.show){ + return; + } + + //判断translate 的id是否存在,不存在就创建一个 + if(document.getElementById('translate') == null){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); + }else{ + //存在,那么判断一下 select是否存在,要是存在就不重复创建了 + if(document.getElementById('translateSelectLanguage') != null){ + //select存在了,就不重复创建了 + return; + } + } + + //从服务器加载支持的语言库 + translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ + if(data.result == 0){ + console.log('load language list error : '+data.info); + return; + } + + //select的onchange事件 + var onchange = function(event){ + var language = event.target.value; + translate.changeLanguage(language); + } + + //创建 select 标签 + var selectLanguage = document.createElement("select"); + selectLanguage.id = 'translateSelectLanguage'; + selectLanguage.className = 'translateSelectLanguage'; + for(var i = 0; i 0 + //已经创建过了,存在 + selectId = 'translate'; + } + + translate.translate = new google.translate.TranslateElement( + { + //这参数没用,请忽略 + pageLanguage: 'zh-CN', + //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi + //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', + includedLanguages: translate.selectLanguageTag.languages, + //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ + layout: 0, + //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 + //autoDisplay: false, + //disableAutoTranslation:false, + //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 + }, + selectId //触发按钮的id + ); + }, + + /** + * 初始化,如加载js、css资源 + */ + init:function(){ + /****** 先判断当前协议,定义资源路径 ******/ + var protocol = window.location.protocol; + if(window.location.protocol == 'file:'){ + //本地的,那就用http + protocol = 'http:'; + } + if(this.resourcesUrl.indexOf('://') == -1){ + //还没设置过,进行设置 + this.resourcesUrl = protocol + this.resourcesUrl; + } + + //this.resourcesUrl = 'file://G:/git/translate'; + + }, + /** + * 执行翻译操作 + */ + execute_v1:function(){ + /*********** 判断translate 的id是否存在,不存在就创建一个 */ + if(document.getElementById('translate') == null){ + if(translate.selectLanguageTag.show){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); + } + } + + /* 处理1.0 - 1.1 升级的 */ + if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ + /* 用户1.0版本设置过这个,那么就以这个为主 */ + translate.selectLanguageTag.languages = translate.includedLanguages; + console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); + } + + + /****** 先加载资源 ******/ + var head0 = document.getElementsByTagName('head')[0]; + var script = document.createElement("script"); //创建一个script标签 + script.type = "text/javascript"; + //script.async = true; + script.src = this.resourcesUrl+'/js/element.js'; + head0.appendChild(script); + }, + + /** + * 设置Cookie,失效时间一年。 + * @param name + * @param value + */ + setCookie:function (name,value){ + var cookieString=name+"="+escape(value); + document.cookie=cookieString; + }, + + //获取Cookie。若是不存再,返回空字符串 + getCookie:function (name){ + var strCookie=document.cookie; + var arrCookie=strCookie.split("; "); + for(var i=0;i 0){ + return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); + }else{ + return translate.localLanguage; + } + }, + + /** + * 切换语言,比如切换为英语、法语 + * @param languageName 要切换的语言语种。传入如 en、zh-CN + * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 + * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 + */ + changeLanguage:function(languageName){ + //判断使用的是否是v1.x + var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; + if(v1.indexOf(','+languageName+',') > -1){ + //用的是v1.x + + translate.check(); + + var googtrans = '/'+translate.localLanguage+'/'+languageName; + + //先清空泛解析域名的设置 + var s = document.location.host.split('.'); + if(s.length > 2){ + var fanDomain = s[s.length-2]+'.'+s[s.length-1]; + document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; + document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; + } + + translate.setCookie('googtrans', ''+googtrans); + location.reload(); + return; + } + + //用的是v2.x或更高 + this.setUseVersion2(); + this.to = languageName; + translate.storage.set('to',languageName); //设置目标翻译语言 + location.reload(); //刷新页面 + }, + + /** + * 自检提示,适用于 v1.x, 在 v2.x中已废弃 + */ + check:function(){ + if(window.location.protocol == 'file:'){ + console.log('\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------'); + } + }, + + + /**************************** v2.0 */ + to:'', //翻译为的目标语言,如 english 、chinese_simplified + //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 + //如果使用后,第二次在用,那就优先以用户所选择的为主,这个就不管用了 + //默认是false,不使用,可设置true:使用 + //使用 setAutoDiscriminateLocalLanguage 进行设置 + autoDiscriminateLocalLanguage:false, + documents:[], //指定要翻译的元素的集合,可设置多个,如设置: document.getElementsByTagName('DIV') + //翻译时忽略的一些东西,比如忽略某个tag、某个class等 + ignore:{ + tag:['style', 'script', 'img', 'head', 'link', 'i', 'pre', 'code'], + class:['ignore','translateSelectLanguage'] + }, + setAutoDiscriminateLocalLanguage:function(){ + this.autoDiscriminateLocalLanguage = true; + }, + //待翻译的页面的node队列,key为 english、chinese value[ hash,value为node对象的数组 ] + nodeQueue:{}, + //指定要翻译的元素的集合,可传入一个元素或多个元素 + //如设置一个元素,可传入如: document.getElementsById('test') + //如设置多个元素,可传入如: document.getElementsByTagName('DIV') + setDocuments:function(documents){ + if (documents == null || typeof(documents) == 'undefined') { + return; + } + + if(typeof(documents.length) == 'undefined'){ + //不是数组,是单个元素 + this.documents[0] = documents; + }else{ + //是数组,直接赋予 + this.documents = documents; + } + //清空翻译队列,下次翻译时重新检索 + this.nodeQueue = {}; + }, + listener:{ + //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) + isExecuteFinish:false, + //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 + isStart:false, + //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + start:function(){ + if(translate.listener.isStart){ + //已开启了 + return; + } + + //判断是否是执行完一次了 + translate.temp_linstenerStartInterval = setInterval(function(){ + if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + if(translate.listener.isStart){ + //已开启了 + return; + } + clearInterval(translate.temp_linstenerStartInterval);//停止 + translate.listener.isStart = true; + translate.listener.addListener(); + //console.log('translate.temp_linstenerStartInterval Finish!'); + } + }, 50); + }, + //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 + addListener:function(){ + //选择需要观察变动的节点 + //const targetNode = document.getElementById('some-id'); + const targetNode = document; + // 观察器的配置(需要观察什么变动) + const config = { attributes: true, childList: true, subtree: true }; + // 当观察到变动时执行的回调函数 + const callback = function(mutationsList, observer) { + var documents = []; //有变动的元素 + + // Use traditional 'for loops' for IE 11 + for(let mutation of mutationsList) { + if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { + //多了个组件 + documents.push.apply(documents,mutation.addedNodes); + //console.log(mutation.addedNodes.nodeValue); + } + //else if (mutation.type === 'attributes') { + // console.log('The ' + mutation.attributeName + ' attribute was modified.'); + //} + } + + //console.log(documents); + if(documents.length > 0){ + //有变动,需要看看是否需要翻译 + translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 + translate.execute(); + } + }; + // 创建一个观察器实例并传入回调函数 + const observer = new MutationObserver(callback); + // 以上述配置开始观察目标节点 + observer.observe(targetNode, config); + } + }, + //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 + renderTask:class{ + constructor(){ + /* + * 任务列表 + * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 + * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 + * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 + */ + this.taskQueue = []; + + /* + * 要进行翻译的node元素, + * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 + * 二维数组,也就是value中包含的node集合 [node,node,...] + */ + this.nodeQueue = []; + } + + /** + * 向替换队列中增加替换任务 + * node:要替换的字符属于那个node元素 + * originalText:待翻译的字符 + * resultText:翻译后的结果字符 + */ + add(node, originalText, resultText){ + var hash = translate.util.hash(node.nodeValue); //node中内容的hash + + /****** 加入翻译的元素队列 */ + if(typeof(this.nodeQueue[hash]) == 'undefined'){ + this.nodeQueue[hash] = new Array(); + } + this.nodeQueue[hash].push(node); + //console.log(node) + + /****** 加入翻译的任务队列 */ + var tasks = this.taskQueue[hash]; + if(tasks == null || typeof(tasks) == 'undefined'){ + //console.log(node.nodeValue); + tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 + } + var task = new Array(); + task['originalText'] = originalText; + task['resultText'] = resultText; + tasks.push(task); + this.taskQueue[hash] = tasks; + /****** 加入翻译的任务队列 end */ + } + //进行替换渲染任务,对页面进行渲染替换翻译 + execute(){ + + //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 + for(var hash in this.taskQueue){ + var tasks = this.taskQueue[hash]; + tasks.sort(function(a,b){ + return b.originalText.length - a.originalText.length; + }); + this.taskQueue[hash] = tasks; + } + + //console.log(this.taskQueue); + //console.log(this.nodeQueue); + + //对nodeQueue进行翻译 + for(var hash in this.nodeQueue){ + var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务 + for(var node_index = 0; node_index < this.nodeQueue[hash].length; node_index++){ + //对这个node元素进行替换翻译字符 + for(var task_index=0; task_index 0){ + this.to = to_storage; + } + } + + //渲染select选择语言 + try{ + this.selectLanguageTag.render(); + }catch(e){ + console.log(e); + } + + //判断是否还未指定翻译的目标语言 + if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ + //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 + if(this.autoDiscriminateLocalLanguage){ + this.executeByLocalLanguage(); + } + + //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 + return; + } + + //进行翻译操作 + + //检索当前是否已经检索过翻译目标了 + if(this.nodeQueue == null || typeof(this.nodeQueue.length) == 'undefined' || this.nodeQueue.length == 0){ + var all; + if(this.documents == null || this.documents.length == 0){ + all = document.all; //如果未设置,那么翻译所有的 + }else{ + //设置了翻译指定的元素,那么赋予 + all = this.documents; + } + + for(var i = 0; i< all.length & i < 20; i++){ + var node = all[i]; + this.whileNodes(node); + } + } + + //translateTextArray[lang][0] + var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] + var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 + + for(var lang in this.nodeQueue){ //一维数组,取语言 + //console.log('lang:'+lang); //lang为english这种语言标识 + if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ + //console.log('lang is null : '+lang); + continue; + } + + translateTextArray[lang] = []; + translateHashArray[lang] = []; + + let task = new translate.renderTask(); + //二维数组,取hash、value + for(var hash in this.nodeQueue[lang]){ + //取原始的词,还未经过翻译的,需要进行翻译的词 + var originalWord = this.nodeQueue[lang][hash]['original']; + //根据hash,判断本地是否有缓存了 + var cache = this.storage.get('hash_'+translate.to+'_'+hash); + //console.log(key+', '+cache); + if(cache != null && cache.length > 0){ + //有缓存了 + //console.log('find cache:'+cache); + //console.log(this.nodeQueue[lang][hash]['nodes']); + //直接将缓存赋予 + //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ + //this.nodeQueue[lang][hash][index].nodeValue = cache; + + for(var node_index = 0; node_index < this.nodeQueue[lang][hash]['nodes'].length; node_index++){ + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; + //console.log(originalWord); + task.add(this.nodeQueue[lang][hash]['nodes'][node_index], originalWord, cache); + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); + } + //} + + continue; //跳出,不用在传入下面的翻译接口了 + } + + /* + //取出数组 + var queueNodes = this.nodeQueue[lang][hash]; + if(queueNodes.length > 0){ + //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 + var valueStr = queueNodes[0].nodeValue; + valueStr = this.util.charReplace(valueStr); + + translateTextArray[lang].push(valueStr); + translateHashArray[lang].push(hash); + } + */ + + //加入待翻译数组 + translateTextArray[lang].push(originalWord); + translateHashArray[lang].push(hash); + } + task.execute(); //执行渲染任务 + } + + + //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english + var fanyiLangs = []; + for(var lang in this.nodeQueue){ //一维数组,取语言 + if(translateTextArray[lang].length < 1){ + continue; + } + fanyiLangs.push(lang); + } + + /******* 用以记录当前是否进行完第一次翻译了 *******/ + if(!translate.listener.isExecuteFinish){ + translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 + //判断是否是执行完一次了 + translate.temp_executeFinishInterval = setInterval(function(){ + if(translate.temp_executeFinishNumber == fanyiLangs.length){ + translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 + clearInterval(translate.temp_executeFinishInterval);//停止 + //console.log('translate.execute() Finish!'); + } + }, 50); + } + + if(fanyiLangs.length == 0){ + //没有需要翻译的,直接退出 + return; + } + + //进行掉接口翻译 + for(var lang_index in fanyiLangs){ //一维数组,取语言 + var lang = fanyiLangs[lang_index]; + //console.log(lang) + if(translateTextArray[lang].length < 1){ + return; + } + + /*** 翻译开始 ***/ + var url = 'https://api.translate.zvo.cn/translate.json'; + var data = { + from:lang, + to:this.to, + //text:JSON.stringify(translateTextArray[lang]) + text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) + }; + this.request.post(url, data, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('=======ERROR START======='); + console.log(translateTextArray[data.from]); + //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); + + console.log('response : '+data.info); + console.log('=======ERROR END ======='); + translate.temp_executeFinishNumber++; //记录执行完的次数 + return; + } + + let task = new translate.renderTask(); + //遍历 translateHashArray + for(var i=0; i 0){ + for(var i = 0; i -1){ + //忽略tag + //console.log('忽略tag:'+parentNodeName); + return; + } + + /****** 判断忽略的class ******/ + var ignoreClass = false; //是否是被忽略的class,true是 + var parentNode = node.parentNode; + while(node != parentNode && parentNode != null){ + //console.log('node:'+node+', parentNode:'+parentNode); + if(parentNode.className != null){ + if(this.ignore.class.indexOf(parentNode.className) > -1){ + //发现ignore.class 当前是处于被忽略的 class + ignoreClass = true; + } + } + + parentNode = parentNode.parentNode; + } + if(ignoreClass){ + //console.log('ignore class : node:'+node.nodeValue); + return; + } + /**** 判断忽略的class结束 ******/ + + //console.log(node.nodeName+', '+node.nodeValue); + if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ + //input 输入框,要对 placeholder 做翻译 + //console.log('input---'+node.attributes); + if(node.attributes == null || typeof(node.attributes) == 'undefined'){ + return; + } + + if(typeof(node.attributes['placeholder']) != 'undefined'){ + //console.log(node.attributes['placeholder'].nodeValue); + //加入要翻译的node队列 + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; + //加入要翻译的node队列 + //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); + this.addNodeToQueue(node.attributes['placeholder']); + } + + //console.log(node.getAttribute("placeholder")); + }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ + + //过滤掉无效的值 + if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ + }else{ + return; + } + + //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); + + //console.log(node.nodeName); + //console.log(node.parentNode.nodeName); + //console.log(node.nodeValue); + //加入要翻译的node队列 + this.addNodeToQueue(node); + //translate.addNodeToQueue(translate.hash(node.nodeValue), node); + //translate.nodeQueue[translate.hash(node.nodeValue)] = node; + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; + //node.nodeValue = node.nodeValue+'|'; + + } + }, + //将发现的元素节点加入待翻译队列 + addNodeToQueue:function(node){ + if(node.nodeValue == null || node.nodeValue.length == 0){ + return; + } + var key = this.util.hash(node.nodeValue); + if(this.util.findTag(node.nodeValue)){ + //console.log('find tag ignore : '+node.nodeValue); + return; + } + + //获取当前是什么语种 + var langs = this.language.get(node.nodeValue); + //console.log('langs'); + //console.log(langs); + + //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 + if(typeof(langs[translate.to]) != 'undefined'){ + delete langs[translate.to]; + } + + /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ + this.nodeQueue[lang] = new Array(); + } + //创建二维数组 + if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ + this.nodeQueue[lang][key] = new Array(); + } + */ + + for(var lang in langs) { + + //创建一维数组, key为语种,如 english + if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ + this.nodeQueue[lang] = new Array(); + } + + //遍历出该语种下有哪些词需要翻译 + for(var word_index = 0; word_index < langs[lang].length; word_index++){ + var word = langs[lang][word_index]; //要翻译的词 + var hash = this.util.hash(word); //要翻译的词的hash + + + //创建二维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) + if(this.nodeQueue[lang][hash] == null || typeof(this.nodeQueue[lang][hash]) == 'undefined'){ + this.nodeQueue[lang][hash] = new Array(); + + /* + * 创建三维数组,存放具体数据 + * key: nodes 包含了这个hash的node元素的数组集合,array 多个 + * key: original 原始的要翻译的词或句子,html加载完成但还没翻译前的文本,用于支持当前页面多次语种翻译切换而无需跳转 + */ + this.nodeQueue[lang][hash]['nodes'] = new Array(); + this.nodeQueue[lang][hash]['original'] = word; + + //其中key: nodes 是第四维数组,里面存放具体的node元素对象 + + } + + //往四维数组nodes中追加node元素 + this.nodeQueue[lang][hash]['nodes'][this.nodeQueue[lang][hash]['nodes'].length]=node; + } + + } + + + + //this.nodeQueue[lang][key][this.nodeQueue[lang][key].length]=node; //往数组中追加 + }, + + language:{ + //获取当前字符是什么语种。返回值是一个语言标识,有 chinese_simplified简体中文、japanese日语、korean韩语、 + // //会自动将特殊字符、要翻译的目标语种给过滤掉 + get:function(str){ + //将str拆分为单个char进行判断 + + var langs = new Array(); //当前字符串包含哪些语言的数组,其内如 english + var langStrs = new Array(); //存放不同语言的文本,格式如 ['english'][0] = 'hello' + + var upLangs = ''; //上一个字符的语种是什么,格式如 english + for(var i=0; i -1){ + newLangs.splice(index,1); //移除 + } + + //移除特殊字符 + var index = newLangs.indexOf('specialCharacter'); + if(index > -1){ + newLangs.splice(index,1); //移除数组中的特殊字符 + } + + if(newLangs.length > 0){ + //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) + return newLangs[0]; + }else{ + //没找到,直接返回空字符串 + return ''; + } + */ + + + //去除特殊符号 + //for(var i = 0; i<等符号 + if(/.*[\u3001-\u3036]+.*$/.test(str)){ + return true; + } + + /* + //阿拉伯数字 0-9 + if(/.*[\u0030-\u0039]+.*$/.test(str)){ + return true; + } + */ + + /* + U+0020 空格 + U+0021 ! 叹号 + U+0022 " 双引号 + U+0023 # 井号 + U+0024 $ 价钱/货币符号 + U+0025 % 百分比符号 + U+0026 & 英文“and”的简写符号 + U+0027 ' 引号 + U+0028 ( 开 左圆括号 + U+0029 ) 关 右圆括号 + U+002A * 星号 + U+002B + 加号 + U+002C , 逗号 + U+002D - 连字号/减号 + U+002E . 句号 + U+002F / 左斜杠 + U+0030 0 数字 0 + U+0031 1 数字 1 + U+0032 2 数字 2 + U+0033 3 数字 3 + U+0034 4 数字 4 + U+0035 5 数字 5 + U+0036 6 数字 6 + U+0037 7 数字 7 + U+0038 8 数字 8 + U+0039 9 数字 9 + U+003A : 冒号 + U+003B ; 分号 + U+003C < 小于符号 + U+003D = 等于号 + U+003E > 大于符号 + U+003F ? 问号 + U+0040 @ 英文“at”的简写符号 + U+0041 A 拉丁字母 A + U+0042 B 拉丁字母 B + U+0043 C 拉丁字母 C + U+0044 D 拉丁字母 D + U+0045 E 拉丁字母 E + U+0046 F 拉丁字母 F + U+0047 G 拉丁字母 G + U+0048 H 拉丁字母 H + U+0049 I 拉丁字母 I + U+004A J 拉丁字母 J + U+004B K 拉丁字母 K + U+004C L 拉丁字母 L + U+004D M 拉丁字母 M + U+004E N 拉丁字母 N + U+004F O 拉丁字母 O + U+0050 P 拉丁字母 P + U+0051 Q 拉丁字母 Q + U+0052 R 拉丁字母 R + U+0053 S 拉丁字母 S + U+0054 T 拉丁字母 T + U+0055 U 拉丁字母 U + U+0056 V 拉丁字母 V + U+0057 W 拉丁字母 W + U+0058 X 拉丁字母 X + U+0059 Y 拉丁字母 Y + U+005A Z 拉丁字母 Z + U+005B [ 开 方括号 + U+005C \ 右斜杠 + U+005D ] 关 方括号 + U+005E ^ 抑扬(重音)符号 + U+005F _ 底线 + U+0060 ` 重音符 + U+0061 a 拉丁字母 a + U+0062 b 拉丁字母 b + U+0063 c 拉丁字母 c + U+0064 d 拉丁字母 d + U+0065 e 拉丁字母 e + U+0066 f 拉丁字母 f + U+0067 g 拉丁字母 g + U+0068 h 拉丁字母 h + U+0069 i 拉丁字母 i + U+006A j 拉丁字母 j + U+006B k 拉丁字母 k + U+006C l 拉丁字母 l(L的小写) + U+006D m 拉丁字母 m + U+006E n 拉丁字母 n + U+006F o 拉丁字母 o + U+0070 p 拉丁字母 p + U+0071 q 拉丁字母 q + U+0072 r 拉丁字母 r + U+0073 s 拉丁字母 s + U+0074 t 拉丁字母 t + U+0075 u 拉丁字母 u + U+0076 v 拉丁字母 v + U+0077 w 拉丁字母 w + U+0078 x 拉丁字母 x + U+0079 y 拉丁字母 y + U+007A z 拉丁字母 z + U+007B { 开 左花括号 + U+007C | 直线 + U+007D } 关 右花括号 + U+007E ~ 波浪纹 + */ + if(/.*[\u0020-\u007e]+.*$/.test(str)){ + return true; + } + + //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 + if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ + return true; + } + if(/.*[\u2000-\u200B]+.*$/.test(str)){ + return true; + } + + /* + 拉丁字母 + 代码 显示 描述 + U+00A1 ¡ 倒转的叹号 + U+00A2 ¢ (货币单位)分钱、毫子 + U+00A3 £ (货币)英镑 + U+00A4 ¤ (货币)当货币未有符号时以此替代 + U+00A5 ¥ (货币)日元 + U+00A6 ¦ 两条断开的直线 + U+00A7 § 文件分不同部分 + U+00A8 ¨ (语言)分音 + U+00A9 © 版权符 + U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 + U+00AB « 双重角形引号 + U+00AC ¬ 逻辑非 + U+00AE ® 商标 + U+00AF ¯ 长音 + U+00B0 ° 角度 + U+00B1 ± 正负号 + U+00B2 ² 二次方 + U+00B3 ³ 三次方 + U+00B4 ´ 锐音符 + U+00B5 µ 百万分之一,10?6 + U+00B6 ¶ 文章分段 + U+00B7 · 间隔号 + U+00B8 ¸ 软音符 + U+00B9 ¹ 一次方 + U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 + U+00BB » 指向右的双箭头 + U+00BC ¼ 四分之一 + U+00BD ½ 二分之一 + U+00BE ¾ 四分之三 + U+00BF ¿ 倒转的问号 + U+00C1 Á 在拉丁字母 A 上加锐音符 + U+00C2 Â 在拉丁字母 A 上加抑扬符“^” + U+00C3 Ã 在拉丁字母 A 上加“~” + U+00C4 Ä 在拉丁字母 A 上加分音符“..” + U+00C5 Å 在拉丁字母 A 上加角度符“°” + U+00C6 Æ 拉丁字母 A、E 的混合 + U+00C7 Ç 在拉丁字母 C 下加软音符 + U+00C8 È 在拉丁字母 E 上加重音符 + U+00C9 É 在拉丁字母 E 上加锐音符 + U+00CA Ê 在拉丁字母 E 上加抑扬符 + U+00CB Ë 在拉丁字母 E 上加分音符 + U+00CC Ì 在拉丁字母 I 上加重音符 + U+00CD Í 在拉丁字母 I 上加锐音符 + U+00CE Î 在拉丁字母 I 上加抑扬符 + U+00CF Ï 在拉丁字母 I 上加分音符 + U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 + U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” + U+00D2 Ò 在拉丁字母 O 上加重音符 + U+00D3 Ó 在拉丁字母 O 上加锐音符 + U+00D4 Ô 在拉丁字母 O 上加抑扬符 + U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” + U+00D6 Ö 在拉丁字母 O 上加分音符 + U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 + U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” + U+00D9 Ù 在拉丁字母 U 上加重音符 + U+00DA Ú 在拉丁字母 U 上加锐音符 + U+00DB Û 在拉丁字母 U 上加抑扬符 + U+00DC Ü 在拉丁字母 U 上加分音符 + U+00DD Ý 在拉丁字母 Y 上加锐音符 + U+00DE Þ 古拉丁字母,现已被“Th”取替 + U+00DF ß 德文字母 + U+00E0 à 在拉丁字母 a 上加重音符 + U+00E1 á 在拉丁字母 a 上加锐音符 + U+00E2 â 在拉丁字母 a 上加抑扬符 + U+00E3 ã 在拉丁字母 a 上加波浪纹“~” + U+00E4 ä 在拉丁字母 a 上加分音符 + U+00E5 å 在拉丁字母 a 上加角度符“°” + U+00E6 æ 拉丁字母 a、e 的混合 + U+00E7 ç 在拉丁字母 c 下加软音符 + U+00E8 è 在拉丁字母 e 上加锐音符 + U+00E9 é 在拉丁字母 e 上加重音符 + U+00EA ê 在拉丁字母 e 上加抑扬符 + U+00EB ë 在拉丁字母 e 上加分音符 + U+00EC ì 在拉丁字母 i 上加重音符 + U+00ED í 在拉丁字母 i 上加锐音符 + U+00EE î 在拉丁字母 i 上加抑扬符 + U+00EF ï 在拉丁字母 i 上加分音符 + U+00F0 ð 古拉丁字母 + U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” + U+00F2 ò 在拉丁字母 o 上加重音符 + U+00F3 ó 在拉丁字母 o 上加锐音符 + U+00F4 ô 在拉丁字母 o 上加抑扬符 + U+00F5 õ 在拉丁字母 o 上加波浪纹“~” + U+00F6 ö 在拉丁字母 o 上加分音符 + U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 + U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” + U+00F9 ù 在拉丁字母 u 上加重音符 + U+00FA ú 在拉丁字母 u 上加锐音符 + U+00FB ? 在拉丁字母 u 上加抑扬符 + U+00FC ü 在拉丁字母 u 上加分音符 + U+00FD ý 在拉丁字母 y 上加锐音符 + U+00FE þ 古拉丁字母,现已被“th”取替 + U+00FF ü 在拉丁字母 u 上加分音符 + 拉丁字母(扩展 A) + 代码 显示 描述 + U+0100 Ā 在拉丁字母 A 上加长音符 + U+0101 ā 在拉丁字母 a 上加长音符 + U+0102 Ă 在拉丁字母 A 上加短音符 + U+0103 ă 在拉丁字母 a 上加短音符 + U+0104 Ą 在拉丁字母 A 上加反尾形符 + U+0105 ą 在拉丁字母 a 上加反尾形符 + 拉丁字母(扩展 C) + 代码 显示 描述 + U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” + U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” + U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” + U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” + U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 + U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” + U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” + U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 + U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 + U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 + U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 + U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 + U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 + U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 + U+2C75 Ⱶ 拉丁字母“H”的左半部 + U+2C76 ⱶ 拉丁字母“h”的左半部 + U+2C77 ⱷ 希腊字母“φ”的上半部 + */ + if(/.*[\u00A1-\u0105]+.*$/.test(str)){ + return true; + } + if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ + return true; + } + + + return false; + } + }, + //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 + //如果使用后,第二次在用,那就优先以用户所选择的为主 + executeByLocalLanguage:function(){ + this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('==== ERROR 获取当前用户所在区域异常 ===='); + console.log(data.info); + console.log('==== ERROR END ===='); + }else{ + translate.setUseVersion2(); + translate.storage.set('to',data.language); //设置目标翻译语言 + translate.to = data.language; //设置目标语言 + translate.selectLanguageTag + translate.execute(); //执行翻译 + } + }); + }, + + util:{ + //判断字符串中是否存在tag标签。 true存在 + findTag:function(str) { + var reg = /<[^>]+>/g; + return reg.test(str); + }, + //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 + arrayFindMaxNumber:function(arr){ + + // 储存每个元素出现的次数 + var numbers = {} + + // 储存出现最多次的元素 + var maxStr = [] + + // 储存最多出现的元素次数 + var maxNum = 0 + + for(var i =0,len=arr.length;imaxNum){ + maxNum = numbers[arr[i]] + } + } + + for(var item in numbers){ + if(numbers[item]===maxNum){ + maxStr.push(item) + } + } + + return maxStr; + }, + //对字符串进行hash化,目的取唯一值进行标识 + hash:function(str){ + if(str == null || typeof(str) == 'undefined'){ + return str; + } + var hash = 0, i, chr; + if (str.length === 0){ + return hash; + } + + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash+''; + }, + //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 + charReplace:function(str){ + + if(str == null){ + return ''; + } + str = str.trim(); + str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 + //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 + return str; + }, + }, + //request请求来源于 https://github.com/xnx3/request + request:{ + /** + * post请求 + * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php + * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} + * @param func 请求完成的回调,传入如 function(data){ console.log(data); } + */ + post:function(url, data, func){ + var headers = { + 'content-type':'application/x-www-form-urlencoded' + }; + this.send(url, data, func, 'post', true, headers, null); + }, + /** + * 发送请求 + * url 请求的url + * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} + * func 请求完成的回调,传入如 function(data){} + * method 请求方式,可传入 post、get + * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 + * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; + * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} + */ + send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ + //post提交的参数 + var params = ''; + if(data != null){ + for(var index in data){ + if(params.length > 0){ + params = params + '&'; + } + params = params + index + '=' + data[index]; + } + } + + var xhr=null; + try{ + xhr=new XMLHttpRequest(); + }catch(e){ + xhr=new ActiveXObject("Microsoft.XMLHTTP"); + } + //2.调用open方法(true----异步) + xhr.open(method,url,isAsynchronize); + //设置headers + if(headers != null){ + for(var index in headers){ + xhr.setRequestHeader(index,headers[index]); + } + } + xhr.send(params); + //4.请求状态改变事件 + xhr.onreadystatechange=function(){ + if(xhr.readyState==4){ + if(xhr.status==200){ + //请求正常,响应码 200 + var json = null; + try{ + json = JSON.parse(xhr.responseText); + }catch(e){ + console.log(e); + } + if(json == null){ + func(xhr.responseText); + }else{ + func(json); + } + }else{ + if(abnormalFunc != null){ + abnormalFunc(xhr); + } + } + } + } + } + }, + //存储,本地缓存 + storage:{ + set:function(key,value){ + localStorage.setItem(key,value); + }, + get:function(key){ + return localStorage.getItem(key); + } + } + + + + /**************************** v2.0 end */ + + } + + + //这个只是v1使用到 + try{ + translate.init(); + //translate.execute(); + }catch(e){ console.log(e); } //默认就是用新的v2版本 translate.setUseVersion2(); //输出 translate 接口 -- Gitee From a4704a7f13790e6cfd655bb26535afb24241f94f Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 09:30:13 +0800 Subject: [PATCH 05/37] =?UTF-8?q?=E4=BC=98=E5=8C=96ajax=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 42 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 8d0b934..1977a85 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -11,7 +11,7 @@ layui.define(function(exports){ //提示:模块也可以依赖其它模块, /* * 当前的版本 */ - version:'2.1.5.20230107', + version:'2.1.6.20230108', useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 setUseVersion2:function(){ this.useVersion = 'v2'; @@ -309,24 +309,28 @@ layui.define(function(exports){ //提示:模块也可以依赖其它模块, isStart:false, //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 start:function(){ - if(translate.listener.isStart){ - //已开启了 - return; + window.onload = function(){ + /* if(translate.listener.isStart){ + //已开启了 + return; + } */ + + //判断是否是执行完一次了 + translate.temp_linstenerStartInterval = setInterval(function(){ + if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + /*if(translate.listener.isStart){ + //已开启了 + return; + }*/ + clearInterval(translate.temp_linstenerStartInterval);//停止 + translate.listener.isStart = true; + translate.listener.addListener(); + //console.log('translate.temp_linstenerStartInterval Finish!'); + } + }, 50); } - //判断是否是执行完一次了 - translate.temp_linstenerStartInterval = setInterval(function(){ - if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 - if(translate.listener.isStart){ - //已开启了 - return; - } - clearInterval(translate.temp_linstenerStartInterval);//停止 - translate.listener.isStart = true; - translate.listener.addListener(); - //console.log('translate.temp_linstenerStartInterval Finish!'); - } - }, 50); + }, //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 addListener:function(){ @@ -442,7 +446,7 @@ layui.define(function(exports){ //提示:模块也可以依赖其它模块, }, //执行翻译操作。翻译的是 nodeQueue 中的 - execute:function(){ + execute:function(documents){ if(this.useVersion == 'v1'){ //if(this.to == null || this.to == ''){ //采用1.x版本的翻译,使用google翻译 @@ -1440,6 +1444,8 @@ layui.define(function(exports){ //提示:模块也可以依赖其它模块, translate.init(); //translate.execute(); }catch(e){ console.log(e); } + + //默认就是用新的v2版本 translate.setUseVersion2(); //输出 translate 接口 -- Gitee From 990773ae6b7cc6b3fcb8cb638c1d50b70b4f3470 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 11:03:58 +0800 Subject: [PATCH 06/37] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 2722 ++++++++++++++-------------- 1 file changed, 1378 insertions(+), 1344 deletions(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 1977a85..6eb445b 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -1,1453 +1,1487 @@ -/* - * 多语言翻译,作者:管雷鸣 - */ -layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('mod1', callback); - //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 +/** + * 国际化,网页自动翻译。 + * 整理人:管雷鸣 + */ +var translate = { + /* + * 当前的版本 + */ + version:'2.1.6.20230108', + useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 + setUseVersion2:function(){ + this.useVersion = 'v2'; + }, + /* + * 翻译的对象,也就是 new google.translate.TranslateElement(...) + */ + translate:null, + /* + * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr + * 已废弃,请使用 translate.selectLanguageTag.languages + */ + includedLanguages:'zh-CN,zh-TW,en', + /* + * 资源文件url的路径 + */ + resourcesUrl:'//res.zvo.cn/translate', + /** - * 国际化,网页自动翻译。 - * 整理人:管雷鸣 + * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 */ - var translate = { - /* - * 当前的版本 - */ - version:'2.1.6.20230108', - useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 - setUseVersion2:function(){ - this.useVersion = 'v2'; - }, - /* - * 翻译的对象,也就是 new google.translate.TranslateElement(...) - */ - translate:null, - /* - * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr - * 已废弃,请使用 translate.selectLanguageTag.languages - */ - includedLanguages:'zh-CN,zh-TW,en', - /* - * 资源文件url的路径 - */ - resourcesUrl:'//res.zvo.cn/translate', - - /** - * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 - */ - selectLanguageTag:{ - /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ - show:true, - /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ - languages:'zh-CN,zh-TW,en', - render:function(){ //v2增加 - - //判断如果不显示select选择语言,直接就隐藏掉 - if(!translate.selectLanguageTag.show){ + selectLanguageTag:{ + /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ + show:true, + /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ + languages:'zh-CN,zh-TW,en', + alreadyRender:false, //当前是否已渲染过了 true为是 v2.2增加 + render:function(){ //v2增加 + if(translate.selectLanguageTag.alreadyRender){ + return; + } + translate.selectLanguageTag.alreadyRender = true; + + //判断如果不显示select选择语言,直接就隐藏掉 + if(!translate.selectLanguageTag.show){ + return; + } + + //判断translate 的id是否存在,不存在就创建一个 + if(document.getElementById('translate') == null){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); + }else{ + //存在,那么判断一下 select是否存在,要是存在就不重复创建了 + if(document.getElementById('translateSelectLanguage') != null){ + //select存在了,就不重复创建了 return; } - - //判断translate 的id是否存在,不存在就创建一个 - if(document.getElementById('translate') == null){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - }else{ - //存在,那么判断一下 select是否存在,要是存在就不重复创建了 - if(document.getElementById('translateSelectLanguage') != null){ - //select存在了,就不重复创建了 - return; - } + } + + //从服务器加载支持的语言库 + translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ + if(data.result == 0){ + console.log('load language list error : '+data.info); + return; + } + + //select的onchange事件 + var onchange = function(event){ + var language = event.target.value; + translate.changeLanguage(language); } - //从服务器加载支持的语言库 - translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ - if(data.result == 0){ - console.log('load language list error : '+data.info); - return; - } - - //select的onchange事件 - var onchange = function(event){ - var language = event.target.value; - translate.changeLanguage(language); - } - - //创建 select 标签 - var selectLanguage = document.createElement("select"); - selectLanguage.id = 'translateSelectLanguage'; - selectLanguage.className = 'translateSelectLanguage'; - for(var i = 0; i 0 + //已经创建过了,存在 + selectId = 'translate'; + } - /* - * 当前本地语言 - */ - //localLanguage:'zh-CN', - localLanguage:'zh-CN', + translate.translate = new google.translate.TranslateElement( + { + //这参数没用,请忽略 + pageLanguage: 'zh-CN', + //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi + //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', + includedLanguages: translate.selectLanguageTag.languages, + //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ + layout: 0, + //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 + //autoDisplay: false, + //disableAutoTranslation:false, + //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 + }, + selectId //触发按钮的id + ); + }, + + /** + * 初始化,如加载js、css资源 + */ + init:function(){ + /****** 先判断当前协议,定义资源路径 ******/ + var protocol = window.location.protocol; + if(window.location.protocol == 'file:'){ + //本地的,那就用http + protocol = 'http:'; + } + if(this.resourcesUrl.indexOf('://') == -1){ + //还没设置过,进行设置 + this.resourcesUrl = protocol + this.resourcesUrl; + } - /** - * google翻译执行的 - */ - googleTranslateElementInit:function(){ - var selectId = ''; - if(document.getElementById('translate') != null){ // && document.getElementById('translate').innerHTML.indexOf('translateSelectLanguage') > 0 - //已经创建过了,存在 - selectId = 'translate'; - } - - translate.translate = new google.translate.TranslateElement( - { - //这参数没用,请忽略 - pageLanguage: 'zh-CN', - //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi - //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', - includedLanguages: translate.selectLanguageTag.languages, - //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ - layout: 0, - //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 - //autoDisplay: false, - //disableAutoTranslation:false, - //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 - }, - selectId //触发按钮的id - ); - }, + //this.resourcesUrl = 'file://G:/git/translate'; - /** - * 初始化,如加载js、css资源 - */ - init:function(){ - /****** 先判断当前协议,定义资源路径 ******/ - var protocol = window.location.protocol; - if(window.location.protocol == 'file:'){ - //本地的,那就用http - protocol = 'http:'; + }, + /** + * 执行翻译操作 + */ + execute_v1:function(){ + /*********** 判断translate 的id是否存在,不存在就创建一个 */ + if(document.getElementById('translate') == null){ + if(translate.selectLanguageTag.show){ + var body_trans = document.getElementsByTagName('body')[0]; + var div = document.createElement("div"); //创建一个script标签 + div.id="translate"; + body_trans.appendChild(div); } - if(this.resourcesUrl.indexOf('://') == -1){ - //还没设置过,进行设置 - this.resourcesUrl = protocol + this.resourcesUrl; + } + + /* 处理1.0 - 1.1 升级的 */ + if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ + /* 用户1.0版本设置过这个,那么就以这个为主 */ + translate.selectLanguageTag.languages = translate.includedLanguages; + console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); + } + + + /****** 先加载资源 ******/ + var head0 = document.getElementsByTagName('head')[0]; + var script = document.createElement("script"); //创建一个script标签 + script.type = "text/javascript"; + //script.async = true; + script.src = this.resourcesUrl+'/js/element.js'; + head0.appendChild(script); + }, + + /** + * 设置Cookie,失效时间一年。 + * @param name + * @param value + */ + setCookie:function (name,value){ + var cookieString=name+"="+escape(value); + document.cookie=cookieString; + }, + + //获取Cookie。若是不存再,返回空字符串 + getCookie:function (name){ + var strCookie=document.cookie; + var arrCookie=strCookie.split("; "); + for(var i=0;i 0){ + return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); + }else{ + return translate.localLanguage; + } + }, + + /** + * 切换语言,比如切换为英语、法语 + * @param languageName 要切换的语言语种。传入如 en、zh-CN + * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 + * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 + */ + changeLanguage:function(languageName){ + //判断使用的是否是v1.x + var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; + if(v1.indexOf(','+languageName+',') > -1){ + //用的是v1.x - //this.resourcesUrl = 'file://G:/git/translate'; + translate.check(); - }, - /** - * 执行翻译操作 - */ - execute_v1:function(){ - /*********** 判断translate 的id是否存在,不存在就创建一个 */ - if(document.getElementById('translate') == null){ - if(translate.selectLanguageTag.show){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - } - } + var googtrans = '/'+translate.localLanguage+'/'+languageName; - /* 处理1.0 - 1.1 升级的 */ - if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ - /* 用户1.0版本设置过这个,那么就以这个为主 */ - translate.selectLanguageTag.languages = translate.includedLanguages; - console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); + //先清空泛解析域名的设置 + var s = document.location.host.split('.'); + if(s.length > 2){ + var fanDomain = s[s.length-2]+'.'+s[s.length-1]; + document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; + document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; } - - /****** 先加载资源 ******/ - var head0 = document.getElementsByTagName('head')[0]; - var script = document.createElement("script"); //创建一个script标签 - script.type = "text/javascript"; - //script.async = true; - script.src = this.resourcesUrl+'/js/element.js'; - head0.appendChild(script); - }, + translate.setCookie('googtrans', ''+googtrans); + location.reload(); + return; + } - /** - * 设置Cookie,失效时间一年。 - * @param name - * @param value - */ - setCookie:function (name,value){ - var cookieString=name+"="+escape(value); - document.cookie=cookieString; - }, + //用的是v2.x或更高 + this.setUseVersion2(); + this.to = languageName; + translate.storage.set('to',languageName); //设置目标翻译语言 + location.reload(); //刷新页面 + }, - //获取Cookie。若是不存再,返回空字符串 - getCookie:function (name){ - var strCookie=document.cookie; - var arrCookie=strCookie.split("; "); - for(var i=0;i 0){ - return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); - }else{ - return translate.localLanguage; - } - }, + 生命周期: 当execute()执行时创建, 当execute结束(其中的所有request接收到响应并渲染完毕)时销毁(当前暂时不销毁,以方便调试) + */ + nodeQueue:{}, + //指定要翻译的元素的集合,可传入一个元素或多个元素 + //如设置一个元素,可传入如: document.getElementsById('test') + //如设置多个元素,可传入如: document.getElementsByTagName('DIV') + setDocuments:function(documents){ + if (documents == null || typeof(documents) == 'undefined') { + return; + } - /** - * 切换语言,比如切换为英语、法语 - * @param languageName 要切换的语言语种。传入如 en、zh-CN - * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 - * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 - */ - changeLanguage:function(languageName){ - //判断使用的是否是v1.x - var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; - if(v1.indexOf(','+languageName+',') > -1){ - //用的是v1.x - - translate.check(); - - var googtrans = '/'+translate.localLanguage+'/'+languageName; - - //先清空泛解析域名的设置 - var s = document.location.host.split('.'); - if(s.length > 2){ - var fanDomain = s[s.length-2]+'.'+s[s.length-1]; - document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; - document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; - } + if(typeof(documents.length) == 'undefined'){ + //不是数组,是单个元素 + this.documents[0] = documents; + }else{ + //是数组,直接赋予 + this.documents = documents; + } + //清空翻译队列,下次翻译时重新检索 + this.nodeQueue = {}; + }, + listener:{ + //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) + isExecuteFinish:false, + //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 + isStart:false, + //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + start:function(){ + window.onload = function(){ + /* if(translate.listener.isStart){ + //已开启了 + return; + } */ - translate.setCookie('googtrans', ''+googtrans); - location.reload(); - return; + //判断是否是执行完一次了 + translate.temp_linstenerStartInterval = setInterval(function(){ + if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + /*if(translate.listener.isStart){ + //已开启了 + return; + }*/ + clearInterval(translate.temp_linstenerStartInterval);//停止 + translate.listener.isStart = true; + translate.listener.addListener(); + //console.log('translate.temp_linstenerStartInterval Finish!'); + } + }, 50); } - //用的是v2.x或更高 - this.setUseVersion2(); - this.to = languageName; - translate.storage.set('to',languageName); //设置目标翻译语言 - location.reload(); //刷新页面 + }, + //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 + addListener:function(){ + //选择需要观察变动的节点 + //const targetNode = document.getElementById('some-id'); + const targetNode = document; + // 观察器的配置(需要观察什么变动) + const config = { attributes: true, childList: true, subtree: true }; + // 当观察到变动时执行的回调函数 + const callback = function(mutationsList, observer) { + var documents = []; //有变动的元素 + + // Use traditional 'for loops' for IE 11 + for(let mutation of mutationsList) { + if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { + //多了个组件 + documents.push.apply(documents,mutation.addedNodes); + //console.log(mutation.addedNodes.nodeValue); + } + //else if (mutation.type === 'attributes') { + // console.log('The ' + mutation.attributeName + ' attribute was modified.'); + //} + } + + //console.log(documents); + if(documents.length > 0){ + //有变动,需要看看是否需要翻译 + translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 + translate.execute(); + } + }; + // 创建一个观察器实例并传入回调函数 + const observer = new MutationObserver(callback); + // 以上述配置开始观察目标节点 + observer.observe(targetNode, config); + } + }, + //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 + renderTask:class{ + constructor(){ + /* + * 任务列表 + * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 + * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 + * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 + */ + this.taskQueue = []; + + /* + * 要进行翻译的node元素, + * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 + * 二维数组,也就是value中包含的node集合 [node,node,...] + */ + this.nodeQueue = []; + } /** - * 自检提示,适用于 v1.x, 在 v2.x中已废弃 + * 向替换队列中增加替换任务 + * node:要替换的字符属于那个node元素 + * originalText:待翻译的字符 + * resultText:翻译后的结果字符 */ - check:function(){ - if(window.location.protocol == 'file:'){ - console.log('\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------'); - } - }, - - - /**************************** v2.0 */ - to:'', //翻译为的目标语言,如 english 、chinese_simplified - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主,这个就不管用了 - //默认是false,不使用,可设置true:使用 - //使用 setAutoDiscriminateLocalLanguage 进行设置 - autoDiscriminateLocalLanguage:false, - documents:[], //指定要翻译的元素的集合,可设置多个,如设置: document.getElementsByTagName('DIV') - //翻译时忽略的一些东西,比如忽略某个tag、某个class等 - ignore:{ - tag:['style', 'script', 'img', 'head', 'link', 'i', 'pre', 'code'], - class:['ignore','translateSelectLanguage'] - }, - setAutoDiscriminateLocalLanguage:function(){ - this.autoDiscriminateLocalLanguage = true; - }, - //待翻译的页面的node队列,key为 english、chinese value[ hash,value为node对象的数组 ] - nodeQueue:{}, - //指定要翻译的元素的集合,可传入一个元素或多个元素 - //如设置一个元素,可传入如: document.getElementsById('test') - //如设置多个元素,可传入如: document.getElementsByTagName('DIV') - setDocuments:function(documents){ - if (documents == null || typeof(documents) == 'undefined') { - return; - } + add(node, originalText, resultText){ + var hash = translate.util.hash(node.nodeValue); //node中内容的hash - if(typeof(documents.length) == 'undefined'){ - //不是数组,是单个元素 - this.documents[0] = documents; - }else{ - //是数组,直接赋予 - this.documents = documents; - } - //清空翻译队列,下次翻译时重新检索 - this.nodeQueue = {}; - }, - listener:{ - //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) - isExecuteFinish:false, - //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 - isStart:false, - //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - start:function(){ - window.onload = function(){ - /* if(translate.listener.isStart){ - //已开启了 - return; - } */ - - //判断是否是执行完一次了 - translate.temp_linstenerStartInterval = setInterval(function(){ - if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 - /*if(translate.listener.isStart){ - //已开启了 - return; - }*/ - clearInterval(translate.temp_linstenerStartInterval);//停止 - translate.listener.isStart = true; - translate.listener.addListener(); - //console.log('translate.temp_linstenerStartInterval Finish!'); - } - }, 50); - } - - - }, - //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 - addListener:function(){ - //选择需要观察变动的节点 - //const targetNode = document.getElementById('some-id'); - const targetNode = document; - // 观察器的配置(需要观察什么变动) - const config = { attributes: true, childList: true, subtree: true }; - // 当观察到变动时执行的回调函数 - const callback = function(mutationsList, observer) { - var documents = []; //有变动的元素 - - // Use traditional 'for loops' for IE 11 - for(let mutation of mutationsList) { - if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { - //多了个组件 - documents.push.apply(documents,mutation.addedNodes); - //console.log(mutation.addedNodes.nodeValue); - } - //else if (mutation.type === 'attributes') { - // console.log('The ' + mutation.attributeName + ' attribute was modified.'); - //} - } - - //console.log(documents); - if(documents.length > 0){ - //有变动,需要看看是否需要翻译 - translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 - translate.execute(); - } - }; - // 创建一个观察器实例并传入回调函数 - const observer = new MutationObserver(callback); - // 以上述配置开始观察目标节点 - observer.observe(targetNode, config); + /****** 加入翻译的元素队列 */ + if(typeof(this.nodeQueue[hash]) == 'undefined'){ + this.nodeQueue[hash] = new Array(); } - }, - //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 - renderTask:class{ - constructor(){ - /* - * 任务列表 - * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 - * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 - */ - this.taskQueue = []; - - /* - * 要进行翻译的node元素, - * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 - * 二维数组,也就是value中包含的node集合 [node,node,...] - */ - this.nodeQueue = []; + this.nodeQueue[hash].push(node); + //console.log(node) + + /****** 加入翻译的任务队列 */ + var tasks = this.taskQueue[hash]; + if(tasks == null || typeof(tasks) == 'undefined'){ + //console.log(node.nodeValue); + tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 } + var task = new Array(); + task['originalText'] = originalText; + task['resultText'] = resultText; + tasks.push(task); + this.taskQueue[hash] = tasks; + /****** 加入翻译的任务队列 end */ + } + //进行替换渲染任务,对页面进行渲染替换翻译 + execute(){ - /** - * 向替换队列中增加替换任务 - * node:要替换的字符属于那个node元素 - * originalText:待翻译的字符 - * resultText:翻译后的结果字符 - */ - add(node, originalText, resultText){ - var hash = translate.util.hash(node.nodeValue); //node中内容的hash - - /****** 加入翻译的元素队列 */ - if(typeof(this.nodeQueue[hash]) == 'undefined'){ - this.nodeQueue[hash] = new Array(); - } - this.nodeQueue[hash].push(node); - //console.log(node) - - /****** 加入翻译的任务队列 */ + //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 + for(var hash in this.taskQueue){ var tasks = this.taskQueue[hash]; - if(tasks == null || typeof(tasks) == 'undefined'){ - //console.log(node.nodeValue); - tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - } - var task = new Array(); - task['originalText'] = originalText; - task['resultText'] = resultText; - tasks.push(task); + tasks.sort(function(a,b){ + return b.originalText.length - a.originalText.length; + }); this.taskQueue[hash] = tasks; - /****** 加入翻译的任务队列 end */ } - //进行替换渲染任务,对页面进行渲染替换翻译 - execute(){ - - //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 - for(var hash in this.taskQueue){ - var tasks = this.taskQueue[hash]; - tasks.sort(function(a,b){ - return b.originalText.length - a.originalText.length; - }); - this.taskQueue[hash] = tasks; - } - - //console.log(this.taskQueue); - //console.log(this.nodeQueue); - - //对nodeQueue进行翻译 - for(var hash in this.nodeQueue){ - var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务 - for(var node_index = 0; node_index < this.nodeQueue[hash].length; node_index++){ - //对这个node元素进行替换翻译字符 - for(var task_index=0; task_index 0){ + this.to = to_storage; } - - //采用 2.x 版本的翻译,使用自有翻译算法 - - //如果页面打开第一次使用,先判断缓存中有没有上次使用的语种,从缓存中取出 - if(this.to == null || this.to == ''){ - var to_storage = this.storage.get('to'); - if(to_storage != null && typeof(to_storage) != 'undefined' && to_storage.length > 0){ - this.to = to_storage; - } + } + + //渲染select选择语言 + try{ + this.selectLanguageTag.render(); + }catch(e){ + console.log(e); + } + + //判断是否还未指定翻译的目标语言 + if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ + //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 + if(this.autoDiscriminateLocalLanguage){ + this.executeByLocalLanguage(); } - //渲染select选择语言 - try{ - this.selectLanguageTag.render(); - }catch(e){ - console.log(e); + //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 + return; + } + + /* + 进行翻译指定的node操作。优先级为: + 1. 这个方法已经指定的翻译 nodes + 2. setDocuments 指定的 + 3. 整个网页 + */ + var all; + if(typeof(docs) != 'undefined'){ + //1. 这个方法已经指定的翻译 nodes + }else if(this.documents != null && typeof(this.documents) != 'undefined' && this.documents.length > 0){ + //2. setDocuments 指定的 + all = this.documents; + }else{ + //3. 整个网页 + all = document.all; //翻译所有的 + } + + //检索目标内的node元素 + for(var i = 0; i< all.length & i < 20; i++){ + var node = all[i]; + this.whileNodes(uuid, node); + } + + //translateTextArray[lang][0] + var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] + var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 + + for(var lang in this.nodeQueue[uuid]){ //一维数组,取语言 + //console.log('lang:'+lang); //lang为english这种语言标识 + if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ + //console.log('lang is null : '+lang); + continue; } + + translateTextArray[lang] = []; + translateHashArray[lang] = []; - //判断是否还未指定翻译的目标语言 - if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ - //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 - if(this.autoDiscriminateLocalLanguage){ - this.executeByLocalLanguage(); + let task = new translate.renderTask(); + //二维数组,取hash、value + for(var hash in this.nodeQueue[uuid][lang]){ + //取原始的词,还未经过翻译的,需要进行翻译的词 + var originalWord = this.nodeQueue[uuid][lang][hash]['original']; + //根据hash,判断本地是否有缓存了 + var cache = this.storage.get('hash_'+translate.to+'_'+hash); + //console.log(key+', '+cache); + if(cache != null && cache.length > 0){ + //有缓存了 + //console.log('find cache:'+cache); + //console.log(this.nodeQueue[lang][hash]['nodes']); + //直接将缓存赋予 + //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ + //this.nodeQueue[lang][hash][index].nodeValue = cache; + + for(var node_index = 0; node_index < this.nodeQueue[uuid][lang][hash]['nodes'].length; node_index++){ + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; + //console.log(originalWord); + task.add(this.nodeQueue[uuid][lang][hash]['nodes'][node_index], originalWord, cache); + //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); + } + //} + + continue; //跳出,不用在传入下面的翻译接口了 } - //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 - return; - } - - //进行翻译操作 - - //检索当前是否已经检索过翻译目标了 - if(this.nodeQueue == null || typeof(this.nodeQueue.length) == 'undefined' || this.nodeQueue.length == 0){ - var all; - if(this.documents == null || this.documents.length == 0){ - all = document.all; //如果未设置,那么翻译所有的 - }else{ - //设置了翻译指定的元素,那么赋予 - all = this.documents; + /* + //取出数组 + var queueNodes = this.nodeQueue[lang][hash]; + if(queueNodes.length > 0){ + //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 + var valueStr = queueNodes[0].nodeValue; + valueStr = this.util.charReplace(valueStr); + + translateTextArray[lang].push(valueStr); + translateHashArray[lang].push(hash); } + */ - for(var i = 0; i< all.length & i < 20; i++){ - var node = all[i]; - this.whileNodes(node); - } + //加入待翻译数组 + translateTextArray[lang].push(originalWord); + translateHashArray[lang].push(hash); + } + task.execute(); //执行渲染任务 + } + + + //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english + var fanyiLangs = []; + for(var lang in this.nodeQueue[uuid]){ //一维数组,取语言 + if(translateTextArray[lang].length < 1){ + continue; + } + fanyiLangs.push(lang); + } + + /******* 用以记录当前是否进行完第一次翻译了 *******/ + if(!translate.listener.isExecuteFinish){ + translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 + //判断是否是执行完一次了 + translate.temp_executeFinishInterval = setInterval(function(){ + if(translate.temp_executeFinishNumber == fanyiLangs.length){ + translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 + clearInterval(translate.temp_executeFinishInterval);//停止 + //console.log('translate.execute() Finish!'); + } + }, 50); + } + + if(fanyiLangs.length == 0){ + //没有需要翻译的,直接退出 + return; + } + + //进行掉接口翻译 + for(var lang_index in fanyiLangs){ //一维数组,取语言 + var lang = fanyiLangs[lang_index]; + //console.log(lang) + if(translateTextArray[lang].length < 1){ + return; } - //translateTextArray[lang][0] - var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] - var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 - - for(var lang in this.nodeQueue){ //一维数组,取语言 - //console.log('lang:'+lang); //lang为english这种语言标识 - if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ - //console.log('lang is null : '+lang); - continue; + /*** 翻译开始 ***/ + var url = 'https://api.translate.zvo.cn/translate.json'; + var data = { + from:lang, + to:this.to, + //text:JSON.stringify(translateTextArray[lang]) + text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) + }; + this.request.post(url, data, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('=======ERROR START======='); + console.log(translateTextArray[data.from]); + //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); + + console.log('response : '+data.info); + console.log('=======ERROR END ======='); + translate.temp_executeFinishNumber++; //记录执行完的次数 + return; } - - translateTextArray[lang] = []; - translateHashArray[lang] = []; - + console.log('response:'+uuid); let task = new translate.renderTask(); - //二维数组,取hash、value - for(var hash in this.nodeQueue[lang]){ + //遍历 translateHashArray + for(var i=0; i 0){ - //有缓存了 - //console.log('find cache:'+cache); - //console.log(this.nodeQueue[lang][hash]['nodes']); - //直接将缓存赋予 - //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ - //this.nodeQueue[lang][hash][index].nodeValue = cache; - - for(var node_index = 0; node_index < this.nodeQueue[lang][hash]['nodes'].length; node_index++){ - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; - //console.log(originalWord); - task.add(this.nodeQueue[lang][hash]['nodes'][node_index], originalWord, cache); - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); - } - //} - - continue; //跳出,不用在传入下面的翻译接口了 - } + var originalWord = translate.nodeQueue[uuid][lang][hash]['original']; + //for(var index = 0; index < translate.nodeQueue[lang][hash].length; index++){ + for(var node_index = 0; node_index < translate.nodeQueue[uuid][lang][hash]['nodes'].length; node_index++){ + //translate.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = translate.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), text); + //加入任务 + task.add(translate.nodeQueue[uuid][lang][hash]['nodes'][node_index], originalWord, text); + } + //} /* - //取出数组 - var queueNodes = this.nodeQueue[lang][hash]; - if(queueNodes.length > 0){ - //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 - var valueStr = queueNodes[0].nodeValue; - valueStr = this.util.charReplace(valueStr); - - translateTextArray[lang].push(valueStr); - translateHashArray[lang].push(hash); + for(var index = 0; index < translate.nodeQueue[data.from][hash].length; index++){ + translate.nodeQueue[data.from][hash][index].nodeValue = text; } */ - //加入待翻译数组 - translateTextArray[lang].push(originalWord); - translateHashArray[lang].push(hash); + //将翻译结果以 key:hash value翻译结果的形式缓存 + translate.storage.set('hash_'+data.to+'_'+hash,text); } task.execute(); //执行渲染任务 - } - + translate.temp_executeFinishNumber++; //记录执行完的次数 + + }); + /*** 翻译end ***/ + - //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english - var fanyiLangs = []; - for(var lang in this.nodeQueue){ //一维数组,取语言 - if(translateTextArray[lang].length < 1){ - continue; + } + }, + + //向下遍历node + whileNodes:function(uuid, node){ + if(node == null || typeof(node) == 'undefined'){ + return; + } + var childNodes = node.childNodes; + if(childNodes.length > 0){ + for(var i = 0; i -1){ + //忽略tag + //console.log('忽略tag:'+parentNodeName); + return; + } + + /****** 判断忽略的class ******/ + var ignoreClass = false; //是否是被忽略的class,true是 + var parentNode = node.parentNode; + while(node != parentNode && parentNode != null){ + //console.log('node:'+node+', parentNode:'+parentNode); + if(parentNode.className != null){ + if(this.ignore.class.indexOf(parentNode.className) > -1){ + //发现ignore.class 当前是处于被忽略的 class + ignoreClass = true; } - fanyiLangs.push(lang); } - /******* 用以记录当前是否进行完第一次翻译了 *******/ - if(!translate.listener.isExecuteFinish){ - translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 - //判断是否是执行完一次了 - translate.temp_executeFinishInterval = setInterval(function(){ - if(translate.temp_executeFinishNumber == fanyiLangs.length){ - translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 - clearInterval(translate.temp_executeFinishInterval);//停止 - //console.log('translate.execute() Finish!'); - } - }, 50); - } - - if(fanyiLangs.length == 0){ - //没有需要翻译的,直接退出 + parentNode = parentNode.parentNode; + } + if(ignoreClass){ + //console.log('ignore class : node:'+node.nodeValue); + return; + } + /**** 判断忽略的class结束 ******/ + + //console.log(node.nodeName+', '+node.nodeValue); + if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ + //input 输入框,要对 placeholder 做翻译 + //console.log('input---'+node.attributes); + if(node.attributes == null || typeof(node.attributes) == 'undefined'){ return; } + + if(typeof(node.attributes['placeholder']) != 'undefined'){ + //console.log(node.attributes['placeholder'].nodeValue); + //加入要翻译的node队列 + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; + //加入要翻译的node队列 + //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); + this.addNodeToQueue(uuid, node.attributes['placeholder']); + } - //进行掉接口翻译 - for(var lang_index in fanyiLangs){ //一维数组,取语言 - var lang = fanyiLangs[lang_index]; - //console.log(lang) - if(translateTextArray[lang].length < 1){ - return; - } + //console.log(node.getAttribute("placeholder")); + }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ + + //过滤掉无效的值 + if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ + }else{ + return; + } + + //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); + + //console.log(node.nodeName); + //console.log(node.parentNode.nodeName); + //console.log(node.nodeValue); + //加入要翻译的node队列 + this.addNodeToQueue(uuid, node); + //translate.addNodeToQueue(translate.hash(node.nodeValue), node); + //translate.nodeQueue[translate.hash(node.nodeValue)] = node; + //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; + //node.nodeValue = node.nodeValue+'|'; + + } + }, + //将发现的元素节点加入待翻译队列 + addNodeToQueue:function(uuid, node){ + if(node.nodeValue == null || node.nodeValue.length == 0){ + return; + } + var key = this.util.hash(node.nodeValue); + if(this.util.findTag(node.nodeValue)){ + //console.log('find tag ignore : '+node.nodeValue); + return; + } + + //获取当前是什么语种 + var langs = this.language.get(node.nodeValue); + //console.log('langs'); + //console.log(langs); + + //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 + if(typeof(langs[translate.to]) != 'undefined'){ + delete langs[translate.to]; + } + + /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ + this.nodeQueue[lang] = new Array(); + } + //创建二维数组 + if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ + this.nodeQueue[lang][key] = new Array(); + } + */ + + for(var lang in langs) { + + //创建二维数组, key为语种,如 english + if(this.nodeQueue[uuid][lang] == null || typeof(this.nodeQueue[uuid][lang]) == 'undefined'){ + this.nodeQueue[uuid][lang] = new Array(); + } + + //遍历出该语种下有哪些词需要翻译 + for(var word_index = 0; word_index < langs[lang].length; word_index++){ + var word = langs[lang][word_index]; //要翻译的词 + var hash = this.util.hash(word); //要翻译的词的hash - /*** 翻译开始 ***/ - var url = 'https://api.translate.zvo.cn/translate.json'; - var data = { - from:lang, - to:this.to, - //text:JSON.stringify(translateTextArray[lang]) - text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) - }; - this.request.post(url, data, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('=======ERROR START======='); - console.log(translateTextArray[data.from]); - //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); - - console.log('response : '+data.info); - console.log('=======ERROR END ======='); - translate.temp_executeFinishNumber++; //记录执行完的次数 - return; - } + + //创建三维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) + if(this.nodeQueue[uuid][lang][hash] == null || typeof(this.nodeQueue[uuid][lang][hash]) == 'undefined'){ + this.nodeQueue[uuid][lang][hash] = new Array(); - let task = new translate.renderTask(); - //遍历 translateHashArray - for(var i=0; i 0){ - for(var i = 0; i -1){ + newLangs.splice(index,1); //移除 } - if(node.parentNode == null){ - return; + + //移除特殊字符 + var index = newLangs.indexOf('specialCharacter'); + if(index > -1){ + newLangs.splice(index,1); //移除数组中的特殊字符 } - var parentNodeName = node.parentNode.nodeName; - if(parentNodeName == null){ - return; + + if(newLangs.length > 0){ + //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) + return newLangs[0]; + }else{ + //没找到,直接返回空字符串 + return ''; } - if(this.ignore.tag.indexOf(parentNodeName.toLowerCase()) > -1){ - //忽略tag - //console.log('忽略tag:'+parentNodeName); - return; + */ + + + //去除特殊符号 + //for(var i = 0; i -1){ - //发现ignore.class 当前是处于被忽略的 class - ignoreClass = true; - } - } - - parentNode = parentNode.parentNode; + */ + + if(typeof(langStrs['unidentification']) != 'undefined'){ + delete langStrs['unidentification']; } - if(ignoreClass){ - //console.log('ignore class : node:'+node.nodeValue); - return; + if(typeof(langStrs['specialCharacter']) != 'undefined'){ + delete langStrs['specialCharacter']; } - /**** 判断忽略的class结束 ******/ - //console.log(node.nodeName+', '+node.nodeValue); - if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ - //input 输入框,要对 placeholder 做翻译 - //console.log('input---'+node.attributes); - if(node.attributes == null || typeof(node.attributes) == 'undefined'){ - return; - } - - if(typeof(node.attributes['placeholder']) != 'undefined'){ - //console.log(node.attributes['placeholder'].nodeValue); - //加入要翻译的node队列 - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; - //加入要翻译的node队列 - //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); - this.addNodeToQueue(node.attributes['placeholder']); - } - - //console.log(node.getAttribute("placeholder")); - }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ - - //过滤掉无效的值 - if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ + return langStrs; + }, + // 传入一个char,返回这个char属于什么语种,返回如 chinese_simplified、english 如果返回空字符串,那么表示未获取到是什么语种 + getCharLanguage:function(charstr){ + if(charstr == null || typeof(charstr) == 'undefined'){ + return ''; + } + + if(this.specialCharacter(charstr)){ + return 'specialCharacter'; + }else if(this.chinese_simplified(charstr)){ + return 'chinese_simplified'; + }else if(this.english(charstr)){ + return 'english'; + }else if(this.japanese(charstr)){ + return 'japanese'; + }else if(this.korean(charstr)){ + return 'korean'; + }else{ + console.log('not find is language , char : '+charstr+', unicode: '+charstr.charCodeAt(0).toString(16)); + return ''; + } + }, + //对字符串进行分析,分析字符串是有哪几种语言组成。 language 传入如 english , langStrs 操作的,如 langStrs['english'][0] = '你好' upLangs 上次char替换的,如 english , chatstr char文本 + analyse:function(language, langStrs, upLangs, charstr){ + if(typeof(langStrs[language]) == 'undefined'){ + langStrs[language] = new Array(); + } + var index = 0; //当前要存入的数组下标 + if(upLangs == ''){ + //第一次,那么还没存入值,index肯定为0 + }else{ + if(upLangs == language){ + //跟上次语言一样,那么直接拼接 + index = langStrs[language].length-1; }else{ - return; + //不一样,那么再开个数组存放 + index = langStrs[language].length; } - - //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); - - //console.log(node.nodeName); - //console.log(node.parentNode.nodeName); - //console.log(node.nodeValue); - //加入要翻译的node队列 - this.addNodeToQueue(node); - //translate.addNodeToQueue(translate.hash(node.nodeValue), node); - //translate.nodeQueue[translate.hash(node.nodeValue)] = node; - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; - //node.nodeValue = node.nodeValue+'|'; - } + if(typeof(langStrs[language][index]) == 'undefined'){ + langStrs[language][index] = ''; + } + + langStrs[language][index] = langStrs[language][index] + charstr; + + return langStrs }, - //将发现的元素节点加入待翻译队列 - addNodeToQueue:function(node){ - if(node.nodeValue == null || node.nodeValue.length == 0){ - return; + //是否包含中文,true:包含 + chinese_simplified:function(str){ + if(/.*[\u4e00-\u9fa5]+.*$/.test(str)){ + return true + } else { + return false; } - var key = this.util.hash(node.nodeValue); - if(this.util.findTag(node.nodeValue)){ - //console.log('find tag ignore : '+node.nodeValue); - return; + }, + //是否包含英文,true:包含 + english:function(str){ + if(/.*[\u0041-\u005a]+.*$/.test(str)){ + return true; + } else if(/.*[\u0061-\u007a]+.*$/.test(str)){ + return true; + } else { + return false; + } + }, + //是否包含日语,true:包含 + japanese:function(str){ + if(/.*[\u0800-\u4e00]+.*$/.test(str)){ + return true + } else { + return false; + } + }, + //是否包含韩语,true:包含 + korean:function(str){ + if(/.*[\uAC00-\uD7AF]+.*$/.test(str)){ + return true + } else { + return false; + } + }, + //是否包含特殊字符 + specialCharacter:function(str){ + //如:① ⑴ ⒈ + if(/.*[\u2460-\u24E9]+.*$/.test(str)){ + return true + } + + //如:┊┌┍ ▃ ▄ ▅ + if(/.*[\u2500-\u25FF]+.*$/.test(str)){ + return true + } + + //如:㈠ ㎎ ㎏ ㎡ + if(/.*[\u3200-\u33FF]+.*$/.test(str)){ + return true } - - //获取当前是什么语种 - var langs = this.language.get(node.nodeValue); - //console.log('langs'); - //console.log(langs); - //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 - if(typeof(langs[translate.to]) != 'undefined'){ - delete langs[translate.to]; + //如:与ANSI对应的全角字符 + if(/.*[\uFF00-\uFF5E]+.*$/.test(str)){ + return true + } + + //其它特殊符号 + if(/.*[\u2000-\u22FF]+.*$/.test(str)){ + return true + } + + // 、><等符号 + if(/.*[\u3001-\u3036]+.*$/.test(str)){ + return true; } - /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ - this.nodeQueue[lang] = new Array(); - } - //创建二维数组 - if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ - this.nodeQueue[lang][key] = new Array(); + /* + //阿拉伯数字 0-9 + if(/.*[\u0030-\u0039]+.*$/.test(str)){ + return true; } */ - for(var lang in langs) { - - //创建一维数组, key为语种,如 english - if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ - this.nodeQueue[lang] = new Array(); - } - - //遍历出该语种下有哪些词需要翻译 - for(var word_index = 0; word_index < langs[lang].length; word_index++){ - var word = langs[lang][word_index]; //要翻译的词 - var hash = this.util.hash(word); //要翻译的词的hash - - - //创建二维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) - if(this.nodeQueue[lang][hash] == null || typeof(this.nodeQueue[lang][hash]) == 'undefined'){ - this.nodeQueue[lang][hash] = new Array(); - - /* - * 创建三维数组,存放具体数据 - * key: nodes 包含了这个hash的node元素的数组集合,array 多个 - * key: original 原始的要翻译的词或句子,html加载完成但还没翻译前的文本,用于支持当前页面多次语种翻译切换而无需跳转 - */ - this.nodeQueue[lang][hash]['nodes'] = new Array(); - this.nodeQueue[lang][hash]['original'] = word; - - //其中key: nodes 是第四维数组,里面存放具体的node元素对象 - - } - - //往四维数组nodes中追加node元素 - this.nodeQueue[lang][hash]['nodes'][this.nodeQueue[lang][hash]['nodes'].length]=node; - } - + /* + U+0020 空格 + U+0021 ! 叹号 + U+0022 " 双引号 + U+0023 # 井号 + U+0024 $ 价钱/货币符号 + U+0025 % 百分比符号 + U+0026 & 英文“and”的简写符号 + U+0027 ' 引号 + U+0028 ( 开 左圆括号 + U+0029 ) 关 右圆括号 + U+002A * 星号 + U+002B + 加号 + U+002C , 逗号 + U+002D - 连字号/减号 + U+002E . 句号 + U+002F / 左斜杠 + U+0030 0 数字 0 + U+0031 1 数字 1 + U+0032 2 数字 2 + U+0033 3 数字 3 + U+0034 4 数字 4 + U+0035 5 数字 5 + U+0036 6 数字 6 + U+0037 7 数字 7 + U+0038 8 数字 8 + U+0039 9 数字 9 + U+003A : 冒号 + U+003B ; 分号 + U+003C < 小于符号 + U+003D = 等于号 + U+003E > 大于符号 + U+003F ? 问号 + U+0040 @ 英文“at”的简写符号 + U+0041 A 拉丁字母 A + U+0042 B 拉丁字母 B + U+0043 C 拉丁字母 C + U+0044 D 拉丁字母 D + U+0045 E 拉丁字母 E + U+0046 F 拉丁字母 F + U+0047 G 拉丁字母 G + U+0048 H 拉丁字母 H + U+0049 I 拉丁字母 I + U+004A J 拉丁字母 J + U+004B K 拉丁字母 K + U+004C L 拉丁字母 L + U+004D M 拉丁字母 M + U+004E N 拉丁字母 N + U+004F O 拉丁字母 O + U+0050 P 拉丁字母 P + U+0051 Q 拉丁字母 Q + U+0052 R 拉丁字母 R + U+0053 S 拉丁字母 S + U+0054 T 拉丁字母 T + U+0055 U 拉丁字母 U + U+0056 V 拉丁字母 V + U+0057 W 拉丁字母 W + U+0058 X 拉丁字母 X + U+0059 Y 拉丁字母 Y + U+005A Z 拉丁字母 Z + U+005B [ 开 方括号 + U+005C \ 右斜杠 + U+005D ] 关 方括号 + U+005E ^ 抑扬(重音)符号 + U+005F _ 底线 + U+0060 ` 重音符 + U+0061 a 拉丁字母 a + U+0062 b 拉丁字母 b + U+0063 c 拉丁字母 c + U+0064 d 拉丁字母 d + U+0065 e 拉丁字母 e + U+0066 f 拉丁字母 f + U+0067 g 拉丁字母 g + U+0068 h 拉丁字母 h + U+0069 i 拉丁字母 i + U+006A j 拉丁字母 j + U+006B k 拉丁字母 k + U+006C l 拉丁字母 l(L的小写) + U+006D m 拉丁字母 m + U+006E n 拉丁字母 n + U+006F o 拉丁字母 o + U+0070 p 拉丁字母 p + U+0071 q 拉丁字母 q + U+0072 r 拉丁字母 r + U+0073 s 拉丁字母 s + U+0074 t 拉丁字母 t + U+0075 u 拉丁字母 u + U+0076 v 拉丁字母 v + U+0077 w 拉丁字母 w + U+0078 x 拉丁字母 x + U+0079 y 拉丁字母 y + U+007A z 拉丁字母 z + U+007B { 开 左花括号 + U+007C | 直线 + U+007D } 关 右花括号 + U+007E ~ 波浪纹 + */ + if(/.*[\u0020-\u007e]+.*$/.test(str)){ + return true; } + //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 + if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ + return true; + } + if(/.*[\u2000-\u200B]+.*$/.test(str)){ + return true; + } + /* + 拉丁字母 + 代码 显示 描述 + U+00A1 ¡ 倒转的叹号 + U+00A2 ¢ (货币单位)分钱、毫子 + U+00A3 £ (货币)英镑 + U+00A4 ¤ (货币)当货币未有符号时以此替代 + U+00A5 ¥ (货币)日元 + U+00A6 ¦ 两条断开的直线 + U+00A7 § 文件分不同部分 + U+00A8 ¨ (语言)分音 + U+00A9 © 版权符 + U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 + U+00AB « 双重角形引号 + U+00AC ¬ 逻辑非 + U+00AE ® 商标 + U+00AF ¯ 长音 + U+00B0 ° 角度 + U+00B1 ± 正负号 + U+00B2 ² 二次方 + U+00B3 ³ 三次方 + U+00B4 ´ 锐音符 + U+00B5 µ 百万分之一,10?6 + U+00B6 ¶ 文章分段 + U+00B7 · 间隔号 + U+00B8 ¸ 软音符 + U+00B9 ¹ 一次方 + U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 + U+00BB » 指向右的双箭头 + U+00BC ¼ 四分之一 + U+00BD ½ 二分之一 + U+00BE ¾ 四分之三 + U+00BF ¿ 倒转的问号 + U+00C1 Á 在拉丁字母 A 上加锐音符 + U+00C2 Â 在拉丁字母 A 上加抑扬符“^” + U+00C3 Ã 在拉丁字母 A 上加“~” + U+00C4 Ä 在拉丁字母 A 上加分音符“..” + U+00C5 Å 在拉丁字母 A 上加角度符“°” + U+00C6 Æ 拉丁字母 A、E 的混合 + U+00C7 Ç 在拉丁字母 C 下加软音符 + U+00C8 È 在拉丁字母 E 上加重音符 + U+00C9 É 在拉丁字母 E 上加锐音符 + U+00CA Ê 在拉丁字母 E 上加抑扬符 + U+00CB Ë 在拉丁字母 E 上加分音符 + U+00CC Ì 在拉丁字母 I 上加重音符 + U+00CD Í 在拉丁字母 I 上加锐音符 + U+00CE Î 在拉丁字母 I 上加抑扬符 + U+00CF Ï 在拉丁字母 I 上加分音符 + U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 + U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” + U+00D2 Ò 在拉丁字母 O 上加重音符 + U+00D3 Ó 在拉丁字母 O 上加锐音符 + U+00D4 Ô 在拉丁字母 O 上加抑扬符 + U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” + U+00D6 Ö 在拉丁字母 O 上加分音符 + U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 + U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” + U+00D9 Ù 在拉丁字母 U 上加重音符 + U+00DA Ú 在拉丁字母 U 上加锐音符 + U+00DB Û 在拉丁字母 U 上加抑扬符 + U+00DC Ü 在拉丁字母 U 上加分音符 + U+00DD Ý 在拉丁字母 Y 上加锐音符 + U+00DE Þ 古拉丁字母,现已被“Th”取替 + U+00DF ß 德文字母 + U+00E0 à 在拉丁字母 a 上加重音符 + U+00E1 á 在拉丁字母 a 上加锐音符 + U+00E2 â 在拉丁字母 a 上加抑扬符 + U+00E3 ã 在拉丁字母 a 上加波浪纹“~” + U+00E4 ä 在拉丁字母 a 上加分音符 + U+00E5 å 在拉丁字母 a 上加角度符“°” + U+00E6 æ 拉丁字母 a、e 的混合 + U+00E7 ç 在拉丁字母 c 下加软音符 + U+00E8 è 在拉丁字母 e 上加锐音符 + U+00E9 é 在拉丁字母 e 上加重音符 + U+00EA ê 在拉丁字母 e 上加抑扬符 + U+00EB ë 在拉丁字母 e 上加分音符 + U+00EC ì 在拉丁字母 i 上加重音符 + U+00ED í 在拉丁字母 i 上加锐音符 + U+00EE î 在拉丁字母 i 上加抑扬符 + U+00EF ï 在拉丁字母 i 上加分音符 + U+00F0 ð 古拉丁字母 + U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” + U+00F2 ò 在拉丁字母 o 上加重音符 + U+00F3 ó 在拉丁字母 o 上加锐音符 + U+00F4 ô 在拉丁字母 o 上加抑扬符 + U+00F5 õ 在拉丁字母 o 上加波浪纹“~” + U+00F6 ö 在拉丁字母 o 上加分音符 + U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 + U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” + U+00F9 ù 在拉丁字母 u 上加重音符 + U+00FA ú 在拉丁字母 u 上加锐音符 + U+00FB ? 在拉丁字母 u 上加抑扬符 + U+00FC ü 在拉丁字母 u 上加分音符 + U+00FD ý 在拉丁字母 y 上加锐音符 + U+00FE þ 古拉丁字母,现已被“th”取替 + U+00FF ü 在拉丁字母 u 上加分音符 + 拉丁字母(扩展 A) + 代码 显示 描述 + U+0100 Ā 在拉丁字母 A 上加长音符 + U+0101 ā 在拉丁字母 a 上加长音符 + U+0102 Ă 在拉丁字母 A 上加短音符 + U+0103 ă 在拉丁字母 a 上加短音符 + U+0104 Ą 在拉丁字母 A 上加反尾形符 + U+0105 ą 在拉丁字母 a 上加反尾形符 + 拉丁字母(扩展 C) + 代码 显示 描述 + U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” + U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” + U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” + U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” + U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 + U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” + U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” + U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 + U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 + U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 + U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 + U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 + U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 + U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 + U+2C75 Ⱶ 拉丁字母“H”的左半部 + U+2C76 ⱶ 拉丁字母“h”的左半部 + U+2C77 ⱷ 希腊字母“φ”的上半部 + */ + if(/.*[\u00A1-\u0105]+.*$/.test(str)){ + return true; + } + if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ + return true; + } - //this.nodeQueue[lang][key][this.nodeQueue[lang][key].length]=node; //往数组中追加 - }, - - language:{ - //获取当前字符是什么语种。返回值是一个语言标识,有 chinese_simplified简体中文、japanese日语、korean韩语、 - // //会自动将特殊字符、要翻译的目标语种给过滤掉 - get:function(str){ - //将str拆分为单个char进行判断 - - var langs = new Array(); //当前字符串包含哪些语言的数组,其内如 english - var langStrs = new Array(); //存放不同语言的文本,格式如 ['english'][0] = 'hello' - - var upLangs = ''; //上一个字符的语种是什么,格式如 english - for(var i=0; i -1){ - newLangs.splice(index,1); //移除 - } - - //移除特殊字符 - var index = newLangs.indexOf('specialCharacter'); - if(index > -1){ - newLangs.splice(index,1); //移除数组中的特殊字符 - } - - if(newLangs.length > 0){ - //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) - return newLangs[0]; - }else{ - //没找到,直接返回空字符串 - return ''; - } - */ - - - //去除特殊符号 - //for(var i = 0; i<等符号 - if(/.*[\u3001-\u3036]+.*$/.test(str)){ - return true; - } - - /* - //阿拉伯数字 0-9 - if(/.*[\u0030-\u0039]+.*$/.test(str)){ - return true; - } - */ - - /* - U+0020 空格 - U+0021 ! 叹号 - U+0022 " 双引号 - U+0023 # 井号 - U+0024 $ 价钱/货币符号 - U+0025 % 百分比符号 - U+0026 & 英文“and”的简写符号 - U+0027 ' 引号 - U+0028 ( 开 左圆括号 - U+0029 ) 关 右圆括号 - U+002A * 星号 - U+002B + 加号 - U+002C , 逗号 - U+002D - 连字号/减号 - U+002E . 句号 - U+002F / 左斜杠 - U+0030 0 数字 0 - U+0031 1 数字 1 - U+0032 2 数字 2 - U+0033 3 数字 3 - U+0034 4 数字 4 - U+0035 5 数字 5 - U+0036 6 数字 6 - U+0037 7 数字 7 - U+0038 8 数字 8 - U+0039 9 数字 9 - U+003A : 冒号 - U+003B ; 分号 - U+003C < 小于符号 - U+003D = 等于号 - U+003E > 大于符号 - U+003F ? 问号 - U+0040 @ 英文“at”的简写符号 - U+0041 A 拉丁字母 A - U+0042 B 拉丁字母 B - U+0043 C 拉丁字母 C - U+0044 D 拉丁字母 D - U+0045 E 拉丁字母 E - U+0046 F 拉丁字母 F - U+0047 G 拉丁字母 G - U+0048 H 拉丁字母 H - U+0049 I 拉丁字母 I - U+004A J 拉丁字母 J - U+004B K 拉丁字母 K - U+004C L 拉丁字母 L - U+004D M 拉丁字母 M - U+004E N 拉丁字母 N - U+004F O 拉丁字母 O - U+0050 P 拉丁字母 P - U+0051 Q 拉丁字母 Q - U+0052 R 拉丁字母 R - U+0053 S 拉丁字母 S - U+0054 T 拉丁字母 T - U+0055 U 拉丁字母 U - U+0056 V 拉丁字母 V - U+0057 W 拉丁字母 W - U+0058 X 拉丁字母 X - U+0059 Y 拉丁字母 Y - U+005A Z 拉丁字母 Z - U+005B [ 开 方括号 - U+005C \ 右斜杠 - U+005D ] 关 方括号 - U+005E ^ 抑扬(重音)符号 - U+005F _ 底线 - U+0060 ` 重音符 - U+0061 a 拉丁字母 a - U+0062 b 拉丁字母 b - U+0063 c 拉丁字母 c - U+0064 d 拉丁字母 d - U+0065 e 拉丁字母 e - U+0066 f 拉丁字母 f - U+0067 g 拉丁字母 g - U+0068 h 拉丁字母 h - U+0069 i 拉丁字母 i - U+006A j 拉丁字母 j - U+006B k 拉丁字母 k - U+006C l 拉丁字母 l(L的小写) - U+006D m 拉丁字母 m - U+006E n 拉丁字母 n - U+006F o 拉丁字母 o - U+0070 p 拉丁字母 p - U+0071 q 拉丁字母 q - U+0072 r 拉丁字母 r - U+0073 s 拉丁字母 s - U+0074 t 拉丁字母 t - U+0075 u 拉丁字母 u - U+0076 v 拉丁字母 v - U+0077 w 拉丁字母 w - U+0078 x 拉丁字母 x - U+0079 y 拉丁字母 y - U+007A z 拉丁字母 z - U+007B { 开 左花括号 - U+007C | 直线 - U+007D } 关 右花括号 - U+007E ~ 波浪纹 - */ - if(/.*[\u0020-\u007e]+.*$/.test(str)){ - return true; - } - - //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 - if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ - return true; - } - if(/.*[\u2000-\u200B]+.*$/.test(str)){ - return true; - } - - /* - 拉丁字母 - 代码 显示 描述 - U+00A1 ¡ 倒转的叹号 - U+00A2 ¢ (货币单位)分钱、毫子 - U+00A3 £ (货币)英镑 - U+00A4 ¤ (货币)当货币未有符号时以此替代 - U+00A5 ¥ (货币)日元 - U+00A6 ¦ 两条断开的直线 - U+00A7 § 文件分不同部分 - U+00A8 ¨ (语言)分音 - U+00A9 © 版权符 - U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 - U+00AB « 双重角形引号 - U+00AC ¬ 逻辑非 - U+00AE ® 商标 - U+00AF ¯ 长音 - U+00B0 ° 角度 - U+00B1 ± 正负号 - U+00B2 ² 二次方 - U+00B3 ³ 三次方 - U+00B4 ´ 锐音符 - U+00B5 µ 百万分之一,10?6 - U+00B6 ¶ 文章分段 - U+00B7 · 间隔号 - U+00B8 ¸ 软音符 - U+00B9 ¹ 一次方 - U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 - U+00BB » 指向右的双箭头 - U+00BC ¼ 四分之一 - U+00BD ½ 二分之一 - U+00BE ¾ 四分之三 - U+00BF ¿ 倒转的问号 - U+00C1 Á 在拉丁字母 A 上加锐音符 - U+00C2 Â 在拉丁字母 A 上加抑扬符“^” - U+00C3 Ã 在拉丁字母 A 上加“~” - U+00C4 Ä 在拉丁字母 A 上加分音符“..” - U+00C5 Å 在拉丁字母 A 上加角度符“°” - U+00C6 Æ 拉丁字母 A、E 的混合 - U+00C7 Ç 在拉丁字母 C 下加软音符 - U+00C8 È 在拉丁字母 E 上加重音符 - U+00C9 É 在拉丁字母 E 上加锐音符 - U+00CA Ê 在拉丁字母 E 上加抑扬符 - U+00CB Ë 在拉丁字母 E 上加分音符 - U+00CC Ì 在拉丁字母 I 上加重音符 - U+00CD Í 在拉丁字母 I 上加锐音符 - U+00CE Î 在拉丁字母 I 上加抑扬符 - U+00CF Ï 在拉丁字母 I 上加分音符 - U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 - U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” - U+00D2 Ò 在拉丁字母 O 上加重音符 - U+00D3 Ó 在拉丁字母 O 上加锐音符 - U+00D4 Ô 在拉丁字母 O 上加抑扬符 - U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” - U+00D6 Ö 在拉丁字母 O 上加分音符 - U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 - U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” - U+00D9 Ù 在拉丁字母 U 上加重音符 - U+00DA Ú 在拉丁字母 U 上加锐音符 - U+00DB Û 在拉丁字母 U 上加抑扬符 - U+00DC Ü 在拉丁字母 U 上加分音符 - U+00DD Ý 在拉丁字母 Y 上加锐音符 - U+00DE Þ 古拉丁字母,现已被“Th”取替 - U+00DF ß 德文字母 - U+00E0 à 在拉丁字母 a 上加重音符 - U+00E1 á 在拉丁字母 a 上加锐音符 - U+00E2 â 在拉丁字母 a 上加抑扬符 - U+00E3 ã 在拉丁字母 a 上加波浪纹“~” - U+00E4 ä 在拉丁字母 a 上加分音符 - U+00E5 å 在拉丁字母 a 上加角度符“°” - U+00E6 æ 拉丁字母 a、e 的混合 - U+00E7 ç 在拉丁字母 c 下加软音符 - U+00E8 è 在拉丁字母 e 上加锐音符 - U+00E9 é 在拉丁字母 e 上加重音符 - U+00EA ê 在拉丁字母 e 上加抑扬符 - U+00EB ë 在拉丁字母 e 上加分音符 - U+00EC ì 在拉丁字母 i 上加重音符 - U+00ED í 在拉丁字母 i 上加锐音符 - U+00EE î 在拉丁字母 i 上加抑扬符 - U+00EF ï 在拉丁字母 i 上加分音符 - U+00F0 ð 古拉丁字母 - U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” - U+00F2 ò 在拉丁字母 o 上加重音符 - U+00F3 ó 在拉丁字母 o 上加锐音符 - U+00F4 ô 在拉丁字母 o 上加抑扬符 - U+00F5 õ 在拉丁字母 o 上加波浪纹“~” - U+00F6 ö 在拉丁字母 o 上加分音符 - U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 - U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” - U+00F9 ù 在拉丁字母 u 上加重音符 - U+00FA ú 在拉丁字母 u 上加锐音符 - U+00FB ? 在拉丁字母 u 上加抑扬符 - U+00FC ü 在拉丁字母 u 上加分音符 - U+00FD ý 在拉丁字母 y 上加锐音符 - U+00FE þ 古拉丁字母,现已被“th”取替 - U+00FF ü 在拉丁字母 u 上加分音符 - 拉丁字母(扩展 A) - 代码 显示 描述 - U+0100 Ā 在拉丁字母 A 上加长音符 - U+0101 ā 在拉丁字母 a 上加长音符 - U+0102 Ă 在拉丁字母 A 上加短音符 - U+0103 ă 在拉丁字母 a 上加短音符 - U+0104 Ą 在拉丁字母 A 上加反尾形符 - U+0105 ą 在拉丁字母 a 上加反尾形符 - 拉丁字母(扩展 C) - 代码 显示 描述 - U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” - U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” - U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” - U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” - U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 - U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” - U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” - U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 - U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 - U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 - U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 - U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 - U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 - U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 - U+2C75 Ⱶ 拉丁字母“H”的左半部 - U+2C76 ⱶ 拉丁字母“h”的左半部 - U+2C77 ⱷ 希腊字母“φ”的上半部 - */ - if(/.*[\u00A1-\u0105]+.*$/.test(str)){ - return true; - } - if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ - return true; - } - - - return false; + + return false; + } + }, + //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 + //如果使用后,第二次在用,那就优先以用户所选择的为主 + executeByLocalLanguage:function(){ + this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ + //console.log(data); + if(data.result == 0){ + console.log('==== ERROR 获取当前用户所在区域异常 ===='); + console.log(data.info); + console.log('==== ERROR END ===='); + }else{ + translate.setUseVersion2(); + translate.storage.set('to',data.language); //设置目标翻译语言 + translate.to = data.language; //设置目标语言 + translate.selectLanguageTag + translate.execute(); //执行翻译 } + }); + }, + + util:{ + /* 生成一个随机UUID,复制于 https://gitee.com/mail_osc/kefu.js */ + uuid:function() { + var d = new Date().getTime(); + if (window.performance && typeof window.performance.now === "function") { + d += performance.now(); //use high-precision timer if available + } + var uuid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); + }); + return uuid; }, - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主 - executeByLocalLanguage:function(){ - this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('==== ERROR 获取当前用户所在区域异常 ===='); - console.log(data.info); - console.log('==== ERROR END ===='); - }else{ - translate.setUseVersion2(); - translate.storage.set('to',data.language); //设置目标翻译语言 - translate.to = data.language; //设置目标语言 - translate.selectLanguageTag - translate.execute(); //执行翻译 - } - }); + + //判断字符串中是否存在tag标签。 true存在 + findTag:function(str) { + var reg = /<[^>]+>/g; + return reg.test(str); }, - - util:{ - //判断字符串中是否存在tag标签。 true存在 - findTag:function(str) { - var reg = /<[^>]+>/g; - return reg.test(str); - }, - //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 - arrayFindMaxNumber:function(arr){ - - // 储存每个元素出现的次数 - var numbers = {} - - // 储存出现最多次的元素 - var maxStr = [] - - // 储存最多出现的元素次数 - var maxNum = 0 - - for(var i =0,len=arr.length;imaxNum){ - maxNum = numbers[arr[i]] - } - } - - for(var item in numbers){ - if(numbers[item]===maxNum){ - maxStr.push(item) - } - } - - return maxStr; - }, - //对字符串进行hash化,目的取唯一值进行标识 - hash:function(str){ - if(str == null || typeof(str) == 'undefined'){ - return str; - } - var hash = 0, i, chr; - if (str.length === 0){ - return hash; - } - - for (i = 0; i < str.length; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer - } - return hash+''; - }, - //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 - charReplace:function(str){ - - if(str == null){ - return ''; - } - str = str.trim(); - str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 - //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 + //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 + arrayFindMaxNumber:function(arr){ + + // 储存每个元素出现的次数 + var numbers = {} + + // 储存出现最多次的元素 + var maxStr = [] + + // 储存最多出现的元素次数 + var maxNum = 0 + + for(var i =0,len=arr.length;imaxNum){ + maxNum = numbers[arr[i]] + } + } + + for(var item in numbers){ + if(numbers[item]===maxNum){ + maxStr.push(item) + } + } + + return maxStr; + }, + //对字符串进行hash化,目的取唯一值进行标识 + hash:function(str){ + if(str == null || typeof(str) == 'undefined'){ return str; - }, + } + var hash = 0, i, chr; + if (str.length === 0){ + return hash; + } + + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash+''; }, - //request请求来源于 https://github.com/xnx3/request - request:{ - /** - * post请求 - * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php - * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} - * @param func 请求完成的回调,传入如 function(data){ console.log(data); } - */ - post:function(url, data, func){ - var headers = { - 'content-type':'application/x-www-form-urlencoded' - }; - this.send(url, data, func, 'post', true, headers, null); - }, - /** - * 发送请求 - * url 请求的url - * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} - * func 请求完成的回调,传入如 function(data){} - * method 请求方式,可传入 post、get - * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 - * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; - * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} - */ - send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ - //post提交的参数 - var params = ''; - if(data != null){ - for(var index in data){ - if(params.length > 0){ - params = params + '&'; - } - params = params + index + '=' + data[index]; - } - } - - var xhr=null; - try{ - xhr=new XMLHttpRequest(); - }catch(e){ - xhr=new ActiveXObject("Microsoft.XMLHTTP"); - } - //2.调用open方法(true----异步) - xhr.open(method,url,isAsynchronize); - //设置headers - if(headers != null){ - for(var index in headers){ - xhr.setRequestHeader(index,headers[index]); + //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 + charReplace:function(str){ + + if(str == null){ + return ''; + } + str = str.trim(); + str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 + //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 + return str; + }, + }, + //request请求来源于 https://github.com/xnx3/request + request:{ + /** + * post请求 + * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php + * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} + * @param func 请求完成的回调,传入如 function(data){ console.log(data); } + */ + post:function(url, data, func){ + var headers = { + 'content-type':'application/x-www-form-urlencoded' + }; + this.send(url, data, func, 'post', true, headers, null); + }, + /** + * 发送请求 + * url 请求的url + * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} + * func 请求完成的回调,传入如 function(data){} + * method 请求方式,可传入 post、get + * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 + * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; + * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} + */ + send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ + //post提交的参数 + var params = ''; + if(data != null){ + for(var index in data){ + if(params.length > 0){ + params = params + '&'; } + params = params + index + '=' + data[index]; } - xhr.send(params); - //4.请求状态改变事件 - xhr.onreadystatechange=function(){ - if(xhr.readyState==4){ - if(xhr.status==200){ - //请求正常,响应码 200 - var json = null; - try{ - json = JSON.parse(xhr.responseText); - }catch(e){ - console.log(e); - } - if(json == null){ - func(xhr.responseText); - }else{ - func(json); - } - }else{ - if(abnormalFunc != null){ - abnormalFunc(xhr); - } - } - } + } + + var xhr=null; + try{ + xhr=new XMLHttpRequest(); + }catch(e){ + xhr=new ActiveXObject("Microsoft.XMLHTTP"); + } + //2.调用open方法(true----异步) + xhr.open(method,url,isAsynchronize); + //设置headers + if(headers != null){ + for(var index in headers){ + xhr.setRequestHeader(index,headers[index]); } } - }, - //存储,本地缓存 - storage:{ - set:function(key,value){ - localStorage.setItem(key,value); - }, - get:function(key){ - return localStorage.getItem(key); + xhr.send(params); + //4.请求状态改变事件 + xhr.onreadystatechange=function(){ + if(xhr.readyState==4){ + if(xhr.status==200){ + //请求正常,响应码 200 + var json = null; + try{ + json = JSON.parse(xhr.responseText); + }catch(e){ + console.log(e); + } + if(json == null){ + func(xhr.responseText); + }else{ + func(json); + } + }else{ + if(abnormalFunc != null){ + abnormalFunc(xhr); + } + } + } } } - - - - /**************************** v2.0 end */ - + }, + //存储,本地缓存 + storage:{ + set:function(key,value){ + localStorage.setItem(key,value); + }, + get:function(key){ + return localStorage.getItem(key); + } } + + + /**************************** v2.0 end */ - //这个只是v1使用到 - try{ - translate.init(); - //translate.execute(); - }catch(e){ console.log(e); } - - - //默认就是用新的v2版本 - translate.setUseVersion2(); - //输出 translate 接口 - exports('translate', translate); -}); \ No newline at end of file +} + + +//这个只是v1使用到 +try{ + translate.init(); + //translate.execute(); +}catch(e){ console.log(e); } \ No newline at end of file -- Gitee From 8843d7b2182a615d655b91c59d5d7d1c33b84007 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 14:37:50 +0800 Subject: [PATCH 07/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 81 +++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 6eb445b..09876dd 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -1,4 +1,9 @@ -/** +/* + * 多语言翻译,作者:管雷鸣 + */ +layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('mod1', callback); + //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 + /** * 国际化,网页自动翻译。 * 整理人:管雷鸣 */ @@ -320,31 +325,51 @@ var translate = { isStart:false, //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 start:function(){ - window.onload = function(){ + + translate.temp_linstenerStartInterval = setInterval(function(){ + if(document.readyState == 'complete'){ + //dom加载完成,进行启动 + clearInterval(translate.temp_linstenerStartInterval);//停止 + translate.listener.addListener(); + } + + //if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + /*if(translate.listener.isStart){ + //已开启了 + return; + }*/ + + //console.log('translate.temp_linstenerStartInterval Finish!'); + //} + }, 50); + + + // window.onload = function(){ /* if(translate.listener.isStart){ //已开启了 return; } */ //判断是否是执行完一次了 - translate.temp_linstenerStartInterval = setInterval(function(){ - if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 + // translate.temp_linstenerStartInterval = setInterval(function(){ + //if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 /*if(translate.listener.isStart){ //已开启了 return; }*/ - clearInterval(translate.temp_linstenerStartInterval);//停止 - translate.listener.isStart = true; - translate.listener.addListener(); + // clearInterval(translate.temp_linstenerStartInterval);//停止 + // translate.listener.addListener(); //console.log('translate.temp_linstenerStartInterval Finish!'); - } - }, 50); - } + //} + // }, 50); + // } }, //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 addListener:function(){ + translate.listener.isStart = true; //记录已执行过启动方法了 + //选择需要观察变动的节点 //const targetNode = document.getElementById('some-id'); const targetNode = document; @@ -359,11 +384,10 @@ var translate = { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { //多了个组件 documents.push.apply(documents,mutation.addedNodes); - //console.log(mutation.addedNodes.nodeValue); + console.log(mutation.addedNodes); + //}else if (mutation.type === 'attributes') { + // console.log('The ' + mutation.attributeName + ' attribute was modified.'); } - //else if (mutation.type === 'attributes') { - // console.log('The ' + mutation.attributeName + ' attribute was modified.'); - //} } //console.log(documents); @@ -476,7 +500,7 @@ var translate = { //每次执行execute,都会生成一个唯一uuid,也可以叫做队列的唯一标识,每一次执行execute都会创建一个独立的翻译执行队列 var uuid = translate.util.uuid(); this.nodeQueue[uuid] = new Array(); //创建 - console.log(uuid); + //console.log(uuid); //如果页面打开第一次使用,先判断缓存中有没有上次使用的语种,从缓存中取出 if(this.to == null || this.to == ''){ @@ -513,6 +537,22 @@ var translate = { var all; if(typeof(docs) != 'undefined'){ //1. 这个方法已经指定的翻译 nodes + + if(docs == null){ + //要翻译的目标区域不存在 + cnosole.log('translate.execute(...) 中传入的要翻译的目标区域不存在。'); + return; + } + + if(typeof(docs.length) == 'undefined'){ + //不是数组,是单个元素 + all = new Array(); + all[0] = docs; + }else{ + //是数组,直接赋予 + all = documents; + } + }else if(this.documents != null && typeof(this.documents) != 'undefined' && this.documents.length > 0){ //2. setDocuments 指定的 all = this.documents; @@ -1397,7 +1437,7 @@ var translate = { */ post:function(url, data, func){ var headers = { - 'content-type':'application/x-www-form-urlencoded' + 'content-type':'application/x-www-form-urlencoded', }; this.send(url, data, func, 'post', true, headers, null); }, @@ -1484,4 +1524,11 @@ var translate = { try{ translate.init(); //translate.execute(); -}catch(e){ console.log(e); } \ No newline at end of file +}catch(e){ console.log(e); } + + + //默认就是用新的v2版本 + translate.setUseVersion2(); + //输出 translate 接口 + exports('translate', translate); +}); \ No newline at end of file -- Gitee From e588706d2db9b8223cb71a2f3942c6fb9790760d Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 15:23:35 +0800 Subject: [PATCH 08/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 1527 +--------------------------- 1 file changed, 3 insertions(+), 1524 deletions(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 09876dd..48c73c1 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -1,1534 +1,13 @@ /* * 多语言翻译,作者:管雷鸣 */ -layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('mod1', callback); +layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - /** - * 国际化,网页自动翻译。 - * 整理人:管雷鸣 - */ -var translate = { - /* - * 当前的版本 - */ - version:'2.1.6.20230108', - useVersion:'v1', //当前使用的版本,默认使用v1. 可使用 setUseVersion2(); //来设置使用v2 - setUseVersion2:function(){ - this.useVersion = 'v2'; - }, - /* - * 翻译的对象,也就是 new google.translate.TranslateElement(...) - */ - translate:null, - /* - * 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr - * 已废弃,请使用 translate.selectLanguageTag.languages - */ - includedLanguages:'zh-CN,zh-TW,en', - /* - * 资源文件url的路径 - */ - resourcesUrl:'//res.zvo.cn/translate', - - /** - * 默认出现的选择语言的 select 选择框,可以通过这个选择切换语言。 - */ - selectLanguageTag:{ - /* 是否显示 select选择语言的选择框,true显示; false不显示。默认为true */ - show:true, - /* 支持哪些语言切换,包括:de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr */ - languages:'zh-CN,zh-TW,en', - alreadyRender:false, //当前是否已渲染过了 true为是 v2.2增加 - render:function(){ //v2增加 - if(translate.selectLanguageTag.alreadyRender){ - return; - } - translate.selectLanguageTag.alreadyRender = true; - - //判断如果不显示select选择语言,直接就隐藏掉 - if(!translate.selectLanguageTag.show){ - return; - } - - //判断translate 的id是否存在,不存在就创建一个 - if(document.getElementById('translate') == null){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - }else{ - //存在,那么判断一下 select是否存在,要是存在就不重复创建了 - if(document.getElementById('translateSelectLanguage') != null){ - //select存在了,就不重复创建了 - return; - } - } - - //从服务器加载支持的语言库 - translate.request.post('https://api.translate.zvo.cn/language.json', {}, function(data){ - if(data.result == 0){ - console.log('load language list error : '+data.info); - return; - } - - //select的onchange事件 - var onchange = function(event){ - var language = event.target.value; - translate.changeLanguage(language); - } - - //创建 select 标签 - var selectLanguage = document.createElement("select"); - selectLanguage.id = 'translateSelectLanguage'; - selectLanguage.className = 'translateSelectLanguage'; - for(var i = 0; i 0 - //已经创建过了,存在 - selectId = 'translate'; - } - - translate.translate = new google.translate.TranslateElement( - { - //这参数没用,请忽略 - pageLanguage: 'zh-CN', - //一共80种语言选择,这个是你需要翻译的语言,比如你只需要翻译成越南和英语,这里就只写en,vi - //includedLanguages: 'de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr', - includedLanguages: translate.selectLanguageTag.languages, - //选择语言的样式,这个是面板,还有下拉框的样式,具体的记不到了,找不到api~~ - layout: 0, - //自动显示翻译横幅,就是翻译后顶部出现的那个,有点丑,设置这个属性不起作用的话,请看文章底部的其他方法 - //autoDisplay: false, - //disableAutoTranslation:false, - //还有些其他参数,由于原插件不再维护,找不到详细api了,将就了,实在不行直接上dom操作 - }, - selectId //触发按钮的id - ); - }, - - /** - * 初始化,如加载js、css资源 - */ - init:function(){ - /****** 先判断当前协议,定义资源路径 ******/ - var protocol = window.location.protocol; - if(window.location.protocol == 'file:'){ - //本地的,那就用http - protocol = 'http:'; - } - if(this.resourcesUrl.indexOf('://') == -1){ - //还没设置过,进行设置 - this.resourcesUrl = protocol + this.resourcesUrl; - } - - //this.resourcesUrl = 'file://G:/git/translate'; - - }, - /** - * 执行翻译操作 - */ - execute_v1:function(){ - /*********** 判断translate 的id是否存在,不存在就创建一个 */ - if(document.getElementById('translate') == null){ - if(translate.selectLanguageTag.show){ - var body_trans = document.getElementsByTagName('body')[0]; - var div = document.createElement("div"); //创建一个script标签 - div.id="translate"; - body_trans.appendChild(div); - } - } - - /* 处理1.0 - 1.1 升级的 */ - if(translate.includedLanguages != 'zh-CN,zh-TW,en'){ - /* 用户1.0版本设置过这个,那么就以这个为主 */ - translate.selectLanguageTag.languages = translate.includedLanguages; - console.log('translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set'); - } - - - /****** 先加载资源 ******/ - var head0 = document.getElementsByTagName('head')[0]; - var script = document.createElement("script"); //创建一个script标签 - script.type = "text/javascript"; - //script.async = true; - script.src = this.resourcesUrl+'/js/element.js'; - head0.appendChild(script); - }, - - /** - * 设置Cookie,失效时间一年。 - * @param name - * @param value - */ - setCookie:function (name,value){ - var cookieString=name+"="+escape(value); - document.cookie=cookieString; - }, - - //获取Cookie。若是不存再,返回空字符串 - getCookie:function (name){ - var strCookie=document.cookie; - var arrCookie=strCookie.split("; "); - for(var i=0;i 0){ - return cookieValue.substr(cookieValue.lastIndexOf('/')+1,cookieValue.length-1); - }else{ - return translate.localLanguage; - } - }, - - /** - * 切换语言,比如切换为英语、法语 - * @param languageName 要切换的语言语种。传入如 en、zh-CN - * 会自动根据传入的语言来判断使用哪种版本。比如传入 en、zh-CN 等,则会使用v1.x版本 - * 传入 chinese_simplified 、english 等,则会使用 v2.x版本 - */ - changeLanguage:function(languageName){ - //判断使用的是否是v1.x - var v1 = ',en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,'; - if(v1.indexOf(','+languageName+',') > -1){ - //用的是v1.x - - translate.check(); - - var googtrans = '/'+translate.localLanguage+'/'+languageName; - - //先清空泛解析域名的设置 - var s = document.location.host.split('.'); - if(s.length > 2){ - var fanDomain = s[s.length-2]+'.'+s[s.length-1]; - document.cookie = 'googtrans=;expires='+(new Date(1))+';domain='+fanDomain+';path=/'; - document.cookie = 'googtrans='+googtrans+';domain='+fanDomain+';path=/'; - } - - translate.setCookie('googtrans', ''+googtrans); - location.reload(); - return; - } - - //用的是v2.x或更高 - this.setUseVersion2(); - this.to = languageName; - translate.storage.set('to',languageName); //设置目标翻译语言 - location.reload(); //刷新页面 - }, - - /** - * 自检提示,适用于 v1.x, 在 v2.x中已废弃 - */ - check:function(){ - if(window.location.protocol == 'file:'){ - console.log('\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------'); - } - }, - - - /**************************** v2.0 */ - to:'', //翻译为的目标语言,如 english 、chinese_simplified - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主,这个就不管用了 - //默认是false,不使用,可设置true:使用 - //使用 setAutoDiscriminateLocalLanguage 进行设置 - autoDiscriminateLocalLanguage:false, - documents:[], //指定要翻译的元素的集合,可设置多个,如设置: document.getElementsByTagName('DIV') - //翻译时忽略的一些东西,比如忽略某个tag、某个class等 - ignore:{ - tag:['style', 'script', 'img', 'head', 'link', 'i', 'pre', 'code'], - class:['ignore','translateSelectLanguage'] - }, - setAutoDiscriminateLocalLanguage:function(){ - this.autoDiscriminateLocalLanguage = true; - }, - /* - 待翻译的页面的node队列 - 一维:key:uuid,也就是execute每次执行都会创建一个翻译队列,这个是翻译队列的唯一标识。 value:待翻译的页面的node队列 - 二维:针对一维的value, key:english、chinese_simplified等语种 value: k/v - 三维:针对二维的value, key:要翻译的词(经过语种分割的)的hash, value: node数组 - 四维:针对三维的value, 这是个对象, 其中 - original: 是三维的key的hash的原始文字,也就是翻译前的文本词 - nodes: 有哪些node元素中包含了这个词,都会在这里记录 - 五维:针对四维的 nodes,将各个 node 列出来,如 [node,node,....] - - 生命周期: 当execute()执行时创建, 当execute结束(其中的所有request接收到响应并渲染完毕)时销毁(当前暂时不销毁,以方便调试) - */ - nodeQueue:{}, - //指定要翻译的元素的集合,可传入一个元素或多个元素 - //如设置一个元素,可传入如: document.getElementsById('test') - //如设置多个元素,可传入如: document.getElementsByTagName('DIV') - setDocuments:function(documents){ - if (documents == null || typeof(documents) == 'undefined') { - return; - } - - if(typeof(documents.length) == 'undefined'){ - //不是数组,是单个元素 - this.documents[0] = documents; - }else{ - //是数组,直接赋予 - this.documents = documents; - } - //清空翻译队列,下次翻译时重新检索 - this.nodeQueue = {}; - }, - listener:{ - //当前页面打开后,是否已经执行完execute() 方法进行翻译了,只要执行完一次,这里便是true。 (多种语言的API请求完毕并已渲染html) - isExecuteFinish:false, - //是否已经使用了 translate.listener.start() 了,如果使用了,那这里为true,多次调用 translate.listener.start() 只有第一次有效 - isStart:false, - //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - start:function(){ - - translate.temp_linstenerStartInterval = setInterval(function(){ - if(document.readyState == 'complete'){ - //dom加载完成,进行启动 - clearInterval(translate.temp_linstenerStartInterval);//停止 - translate.listener.addListener(); - } - - //if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 - /*if(translate.listener.isStart){ - //已开启了 - return; - }*/ - - //console.log('translate.temp_linstenerStartInterval Finish!'); - //} - }, 50); - - - // window.onload = function(){ - /* if(translate.listener.isStart){ - //已开启了 - return; - } */ - - //判断是否是执行完一次了 - // translate.temp_linstenerStartInterval = setInterval(function(){ - //if(translate.listener.isExecuteFinish){ //执行完过一次,那才能使用 - /*if(translate.listener.isStart){ - //已开启了 - return; - }*/ - // clearInterval(translate.temp_linstenerStartInterval);//停止 - // translate.listener.addListener(); - //console.log('translate.temp_linstenerStartInterval Finish!'); - //} - // }, 50); - // } - - - }, - //增加监听,开始监听。这个不要直接调用,需要使用上面的 start() 开启 - addListener:function(){ - translate.listener.isStart = true; //记录已执行过启动方法了 - - //选择需要观察变动的节点 - //const targetNode = document.getElementById('some-id'); - const targetNode = document; - // 观察器的配置(需要观察什么变动) - const config = { attributes: true, childList: true, subtree: true }; - // 当观察到变动时执行的回调函数 - const callback = function(mutationsList, observer) { - var documents = []; //有变动的元素 - - // Use traditional 'for loops' for IE 11 - for(let mutation of mutationsList) { - if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { - //多了个组件 - documents.push.apply(documents,mutation.addedNodes); - console.log(mutation.addedNodes); - //}else if (mutation.type === 'attributes') { - // console.log('The ' + mutation.attributeName + ' attribute was modified.'); - } - } - - //console.log(documents); - if(documents.length > 0){ - //有变动,需要看看是否需要翻译 - translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页 - translate.execute(); - } - }; - // 创建一个观察器实例并传入回调函数 - const observer = new MutationObserver(callback); - // 以上述配置开始观察目标节点 - observer.observe(targetNode, config); - } - }, - //对翻译结果进行替换渲染的任务,将待翻译内容替换为翻译内容的过程 - renderTask:class{ - constructor(){ - /* - * 任务列表 - * 一维数组 [hash] = tasks; tasks 是多个task的数组集合 - * 二维数组 [task,task,...],存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - * 三维数组 task['originalText'] 、 task['resultText'] 存放要替换的字符串 - */ - this.taskQueue = []; - - /* - * 要进行翻译的node元素, - * 一维数组 key:node.nodeValue 的 hash , value:node的元素数组 - * 二维数组,也就是value中包含的node集合 [node,node,...] - */ - this.nodeQueue = []; - } - - /** - * 向替换队列中增加替换任务 - * node:要替换的字符属于那个node元素 - * originalText:待翻译的字符 - * resultText:翻译后的结果字符 - */ - add(node, originalText, resultText){ - var hash = translate.util.hash(node.nodeValue); //node中内容的hash - - /****** 加入翻译的元素队列 */ - if(typeof(this.nodeQueue[hash]) == 'undefined'){ - this.nodeQueue[hash] = new Array(); - } - this.nodeQueue[hash].push(node); - //console.log(node) - - /****** 加入翻译的任务队列 */ - var tasks = this.taskQueue[hash]; - if(tasks == null || typeof(tasks) == 'undefined'){ - //console.log(node.nodeValue); - tasks = new Array(); //任务列表,存放多个 task,每个task是一个替换。这里的数组是同一个nodeValue的多个task替换 - } - var task = new Array(); - task['originalText'] = originalText; - task['resultText'] = resultText; - tasks.push(task); - this.taskQueue[hash] = tasks; - /****** 加入翻译的任务队列 end */ - } - //进行替换渲染任务,对页面进行渲染替换翻译 - execute(){ - - //先对tasks任务队列的替换词进行排序,将同一个node的替换词有大到小排列,避免先替换了小的,大的替换时找不到 - for(var hash in this.taskQueue){ - var tasks = this.taskQueue[hash]; - tasks.sort(function(a,b){ - return b.originalText.length - a.originalText.length; - }); - this.taskQueue[hash] = tasks; - } - - //console.log(this.taskQueue); - //console.log(this.nodeQueue); - - //对nodeQueue进行翻译 - for(var hash in this.nodeQueue){ - var tasks = this.taskQueue[hash]; //取出当前node元素对应的替换任务 - for(var node_index = 0; node_index < this.nodeQueue[hash].length; node_index++){ - //对这个node元素进行替换翻译字符 - for(var task_index=0; task_index 0){ - this.to = to_storage; - } - } - - //渲染select选择语言 - try{ - this.selectLanguageTag.render(); - }catch(e){ - console.log(e); - } - - //判断是否还未指定翻译的目标语言 - if(this.to == null || typeof(this.to) == 'undefined' || this.to.length == 0){ - //未指定,判断如果指定了自动获取用户本国语种了,那么进行获取 - if(this.autoDiscriminateLocalLanguage){ - this.executeByLocalLanguage(); - } - - //没有指定翻译目标语言、又没自动获取用户本国语种,则不翻译 - return; - } - - /* - 进行翻译指定的node操作。优先级为: - 1. 这个方法已经指定的翻译 nodes - 2. setDocuments 指定的 - 3. 整个网页 - */ - var all; - if(typeof(docs) != 'undefined'){ - //1. 这个方法已经指定的翻译 nodes - - if(docs == null){ - //要翻译的目标区域不存在 - cnosole.log('translate.execute(...) 中传入的要翻译的目标区域不存在。'); - return; - } - - if(typeof(docs.length) == 'undefined'){ - //不是数组,是单个元素 - all = new Array(); - all[0] = docs; - }else{ - //是数组,直接赋予 - all = documents; - } - - }else if(this.documents != null && typeof(this.documents) != 'undefined' && this.documents.length > 0){ - //2. setDocuments 指定的 - all = this.documents; - }else{ - //3. 整个网页 - all = document.all; //翻译所有的 - } - - //检索目标内的node元素 - for(var i = 0; i< all.length & i < 20; i++){ - var node = all[i]; - this.whileNodes(uuid, node); - } - - //translateTextArray[lang][0] - var translateTextArray = {}; //要翻译的文本的数组,格式如 ["你好","欢迎"] - var translateHashArray = {}; //要翻译的文本的hash,跟上面的index是一致的,只不过上面是存要翻译的文本,这个存hash值 - - for(var lang in this.nodeQueue[uuid]){ //一维数组,取语言 - //console.log('lang:'+lang); //lang为english这种语言标识 - if(lang == null || typeof(lang) == 'undefined' || lang.length == 0 || lang == 'undefined'){ - //console.log('lang is null : '+lang); - continue; - } - - translateTextArray[lang] = []; - translateHashArray[lang] = []; - - let task = new translate.renderTask(); - //二维数组,取hash、value - for(var hash in this.nodeQueue[uuid][lang]){ - //取原始的词,还未经过翻译的,需要进行翻译的词 - var originalWord = this.nodeQueue[uuid][lang][hash]['original']; - //根据hash,判断本地是否有缓存了 - var cache = this.storage.get('hash_'+translate.to+'_'+hash); - //console.log(key+', '+cache); - if(cache != null && cache.length > 0){ - //有缓存了 - //console.log('find cache:'+cache); - //console.log(this.nodeQueue[lang][hash]['nodes']); - //直接将缓存赋予 - //for(var index = 0; index < this.nodeQueue[lang][hash].length; index++){ - //this.nodeQueue[lang][hash][index].nodeValue = cache; - - for(var node_index = 0; node_index < this.nodeQueue[uuid][lang][hash]['nodes'].length; node_index++){ - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = cache; - //console.log(originalWord); - task.add(this.nodeQueue[uuid][lang][hash]['nodes'][node_index], originalWord, cache); - //this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue = this.nodeQueue[lang][hash]['nodes'][node_index].nodeValue.replace(new RegExp(originalWord,'g'), cache); - } - //} - - continue; //跳出,不用在传入下面的翻译接口了 - } - - /* - //取出数组 - var queueNodes = this.nodeQueue[lang][hash]; - if(queueNodes.length > 0){ - //因为在这个数组中的值都是一样的,那么只需要取出第一个就行了 - var valueStr = queueNodes[0].nodeValue; - valueStr = this.util.charReplace(valueStr); - - translateTextArray[lang].push(valueStr); - translateHashArray[lang].push(hash); - } - */ - - //加入待翻译数组 - translateTextArray[lang].push(originalWord); - translateHashArray[lang].push(hash); - } - task.execute(); //执行渲染任务 - } - - - //统计出要翻译哪些语种 ,这里面的语种会调用接口进行翻译。其内格式如 english - var fanyiLangs = []; - for(var lang in this.nodeQueue[uuid]){ //一维数组,取语言 - if(translateTextArray[lang].length < 1){ - continue; - } - fanyiLangs.push(lang); - } - - /******* 用以记录当前是否进行完第一次翻译了 *******/ - if(!translate.listener.isExecuteFinish){ - translate.temp_executeFinishNumber = 0; //下面请求接口渲染,翻译执行完成的次数 - //判断是否是执行完一次了 - translate.temp_executeFinishInterval = setInterval(function(){ - if(translate.temp_executeFinishNumber == fanyiLangs.length){ - translate.listener.isExecuteFinish = true; //记录当前已执行完第一次了 - clearInterval(translate.temp_executeFinishInterval);//停止 - //console.log('translate.execute() Finish!'); - } - }, 50); - } - - if(fanyiLangs.length == 0){ - //没有需要翻译的,直接退出 - return; - } - - //进行掉接口翻译 - for(var lang_index in fanyiLangs){ //一维数组,取语言 - var lang = fanyiLangs[lang_index]; - //console.log(lang) - if(translateTextArray[lang].length < 1){ - return; - } - - /*** 翻译开始 ***/ - var url = 'https://api.translate.zvo.cn/translate.json'; - var data = { - from:lang, - to:this.to, - //text:JSON.stringify(translateTextArray[lang]) - text:encodeURIComponent(JSON.stringify(translateTextArray[lang])) - }; - this.request.post(url, data, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('=======ERROR START======='); - console.log(translateTextArray[data.from]); - //console.log(encodeURIComponent(JSON.stringify(translateTextArray[data.from]))); - - console.log('response : '+data.info); - console.log('=======ERROR END ======='); - translate.temp_executeFinishNumber++; //记录执行完的次数 - return; - } - console.log('response:'+uuid); - let task = new translate.renderTask(); - //遍历 translateHashArray - for(var i=0; i 0){ - for(var i = 0; i -1){ - //忽略tag - //console.log('忽略tag:'+parentNodeName); - return; - } - - /****** 判断忽略的class ******/ - var ignoreClass = false; //是否是被忽略的class,true是 - var parentNode = node.parentNode; - while(node != parentNode && parentNode != null){ - //console.log('node:'+node+', parentNode:'+parentNode); - if(parentNode.className != null){ - if(this.ignore.class.indexOf(parentNode.className) > -1){ - //发现ignore.class 当前是处于被忽略的 class - ignoreClass = true; - } - } - - parentNode = parentNode.parentNode; - } - if(ignoreClass){ - //console.log('ignore class : node:'+node.nodeValue); - return; - } - /**** 判断忽略的class结束 ******/ - - //console.log(node.nodeName+', '+node.nodeValue); - if(node.nodeName == 'INPUT' || node.nodeName == 'TEXTAREA'){ - //input 输入框,要对 placeholder 做翻译 - //console.log('input---'+node.attributes); - if(node.attributes == null || typeof(node.attributes) == 'undefined'){ - return; - } - - if(typeof(node.attributes['placeholder']) != 'undefined'){ - //console.log(node.attributes['placeholder'].nodeValue); - //加入要翻译的node队列 - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.attributes['placeholder']; - //加入要翻译的node队列 - //translate.addNodeToQueue(translate.hash(node.attributes['placeholder'].nodeValue), node.attributes['placeholder']); - this.addNodeToQueue(uuid, node.attributes['placeholder']); - } - - //console.log(node.getAttribute("placeholder")); - }else if(node.nodeValue != null && node.nodeValue.trim().length > 0){ - - //过滤掉无效的值 - if(node.nodeValue != null && typeof(node.nodeValue) == 'string' && node.nodeValue.length > 0){ - }else{ - return; - } - - //console.log(node.nodeValue+' --- ' + translate.language.get(node.nodeValue)); - - //console.log(node.nodeName); - //console.log(node.parentNode.nodeName); - //console.log(node.nodeValue); - //加入要翻译的node队列 - this.addNodeToQueue(uuid, node); - //translate.addNodeToQueue(translate.hash(node.nodeValue), node); - //translate.nodeQueue[translate.hash(node.nodeValue)] = node; - //translate.nodeQueue[translate.hash(node.nodeValue)] = node.nodeValue; - //node.nodeValue = node.nodeValue+'|'; - - } - }, - //将发现的元素节点加入待翻译队列 - addNodeToQueue:function(uuid, node){ - if(node.nodeValue == null || node.nodeValue.length == 0){ - return; - } - var key = this.util.hash(node.nodeValue); - if(this.util.findTag(node.nodeValue)){ - //console.log('find tag ignore : '+node.nodeValue); - return; - } - - //获取当前是什么语种 - var langs = this.language.get(node.nodeValue); - //console.log('langs'); - //console.log(langs); - - //过滤掉要转换为的目标语种,比如要转为英语,那就将本来是英语的部分过滤掉,不用再翻译了 - if(typeof(langs[translate.to]) != 'undefined'){ - delete langs[translate.to]; - } - - /* if(this.nodeQueue[lang] == null || typeof(this.nodeQueue[lang]) == 'undefined'){ - this.nodeQueue[lang] = new Array(); - } - //创建二维数组 - if(this.nodeQueue[lang][key] == null || typeof(this.nodeQueue[lang][key]) == 'undefined'){ - this.nodeQueue[lang][key] = new Array(); - } - */ - - for(var lang in langs) { - - //创建二维数组, key为语种,如 english - if(this.nodeQueue[uuid][lang] == null || typeof(this.nodeQueue[uuid][lang]) == 'undefined'){ - this.nodeQueue[uuid][lang] = new Array(); - } - - //遍历出该语种下有哪些词需要翻译 - for(var word_index = 0; word_index < langs[lang].length; word_index++){ - var word = langs[lang][word_index]; //要翻译的词 - var hash = this.util.hash(word); //要翻译的词的hash - - - //创建三维数组, key为要通过接口翻译的文本词或句子的 hash (注意并不是node的文本,而是node拆分后的文本) - if(this.nodeQueue[uuid][lang][hash] == null || typeof(this.nodeQueue[uuid][lang][hash]) == 'undefined'){ - this.nodeQueue[uuid][lang][hash] = new Array(); - - /* - * 创建四维数组,存放具体数据 - * key: nodes 包含了这个hash的node元素的数组集合,array 多个 - * key: original 原始的要翻译的词或句子,html加载完成但还没翻译前的文本,用于支持当前页面多次语种翻译切换而无需跳转 - */ - this.nodeQueue[uuid][lang][hash]['nodes'] = new Array(); - this.nodeQueue[uuid][lang][hash]['original'] = word; - - //其中key: nodes 是第四维数组,里面存放具体的node元素对象 - - } - - //往五维数组nodes中追加node元素 - this.nodeQueue[uuid][lang][hash]['nodes'][this.nodeQueue[uuid][lang][hash]['nodes'].length]=node; - } - - } - - - - //this.nodeQueue[lang][key][this.nodeQueue[lang][key].length]=node; //往数组中追加 - }, - - language:{ - //获取当前字符是什么语种。返回值是一个语言标识,有 chinese_simplified简体中文、japanese日语、korean韩语、 - // //会自动将特殊字符、要翻译的目标语种给过滤掉 - get:function(str){ - //将str拆分为单个char进行判断 - - var langs = new Array(); //当前字符串包含哪些语言的数组,其内如 english - var langStrs = new Array(); //存放不同语言的文本,格式如 ['english'][0] = 'hello' - - var upLangs = ''; //上一个字符的语种是什么,格式如 english - for(var i=0; i -1){ - newLangs.splice(index,1); //移除 - } - - //移除特殊字符 - var index = newLangs.indexOf('specialCharacter'); - if(index > -1){ - newLangs.splice(index,1); //移除数组中的特殊字符 - } - - if(newLangs.length > 0){ - //还剩一个或多个,(如果是多个,那应该是这几个出现的频率一样,所以取频率最高的时返回了多个) - return newLangs[0]; - }else{ - //没找到,直接返回空字符串 - return ''; - } - */ - - - //去除特殊符号 - //for(var i = 0; i<等符号 - if(/.*[\u3001-\u3036]+.*$/.test(str)){ - return true; - } - - /* - //阿拉伯数字 0-9 - if(/.*[\u0030-\u0039]+.*$/.test(str)){ - return true; - } - */ - - /* - U+0020 空格 - U+0021 ! 叹号 - U+0022 " 双引号 - U+0023 # 井号 - U+0024 $ 价钱/货币符号 - U+0025 % 百分比符号 - U+0026 & 英文“and”的简写符号 - U+0027 ' 引号 - U+0028 ( 开 左圆括号 - U+0029 ) 关 右圆括号 - U+002A * 星号 - U+002B + 加号 - U+002C , 逗号 - U+002D - 连字号/减号 - U+002E . 句号 - U+002F / 左斜杠 - U+0030 0 数字 0 - U+0031 1 数字 1 - U+0032 2 数字 2 - U+0033 3 数字 3 - U+0034 4 数字 4 - U+0035 5 数字 5 - U+0036 6 数字 6 - U+0037 7 数字 7 - U+0038 8 数字 8 - U+0039 9 数字 9 - U+003A : 冒号 - U+003B ; 分号 - U+003C < 小于符号 - U+003D = 等于号 - U+003E > 大于符号 - U+003F ? 问号 - U+0040 @ 英文“at”的简写符号 - U+0041 A 拉丁字母 A - U+0042 B 拉丁字母 B - U+0043 C 拉丁字母 C - U+0044 D 拉丁字母 D - U+0045 E 拉丁字母 E - U+0046 F 拉丁字母 F - U+0047 G 拉丁字母 G - U+0048 H 拉丁字母 H - U+0049 I 拉丁字母 I - U+004A J 拉丁字母 J - U+004B K 拉丁字母 K - U+004C L 拉丁字母 L - U+004D M 拉丁字母 M - U+004E N 拉丁字母 N - U+004F O 拉丁字母 O - U+0050 P 拉丁字母 P - U+0051 Q 拉丁字母 Q - U+0052 R 拉丁字母 R - U+0053 S 拉丁字母 S - U+0054 T 拉丁字母 T - U+0055 U 拉丁字母 U - U+0056 V 拉丁字母 V - U+0057 W 拉丁字母 W - U+0058 X 拉丁字母 X - U+0059 Y 拉丁字母 Y - U+005A Z 拉丁字母 Z - U+005B [ 开 方括号 - U+005C \ 右斜杠 - U+005D ] 关 方括号 - U+005E ^ 抑扬(重音)符号 - U+005F _ 底线 - U+0060 ` 重音符 - U+0061 a 拉丁字母 a - U+0062 b 拉丁字母 b - U+0063 c 拉丁字母 c - U+0064 d 拉丁字母 d - U+0065 e 拉丁字母 e - U+0066 f 拉丁字母 f - U+0067 g 拉丁字母 g - U+0068 h 拉丁字母 h - U+0069 i 拉丁字母 i - U+006A j 拉丁字母 j - U+006B k 拉丁字母 k - U+006C l 拉丁字母 l(L的小写) - U+006D m 拉丁字母 m - U+006E n 拉丁字母 n - U+006F o 拉丁字母 o - U+0070 p 拉丁字母 p - U+0071 q 拉丁字母 q - U+0072 r 拉丁字母 r - U+0073 s 拉丁字母 s - U+0074 t 拉丁字母 t - U+0075 u 拉丁字母 u - U+0076 v 拉丁字母 v - U+0077 w 拉丁字母 w - U+0078 x 拉丁字母 x - U+0079 y 拉丁字母 y - U+007A z 拉丁字母 z - U+007B { 开 左花括号 - U+007C | 直线 - U+007D } 关 右花括号 - U+007E ~ 波浪纹 - */ - if(/.*[\u0020-\u007e]+.*$/.test(str)){ - return true; - } - - //空白字符,\u0009\u000a + https://cloud.tencent.com/developer/article/2128593 - if(/.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/.test(str)){ - return true; - } - if(/.*[\u2000-\u200B]+.*$/.test(str)){ - return true; - } - - /* - 拉丁字母 - 代码 显示 描述 - U+00A1 ¡ 倒转的叹号 - U+00A2 ¢ (货币单位)分钱、毫子 - U+00A3 £ (货币)英镑 - U+00A4 ¤ (货币)当货币未有符号时以此替代 - U+00A5 ¥ (货币)日元 - U+00A6 ¦ 两条断开的直线 - U+00A7 § 文件分不同部分 - U+00A8 ¨ (语言)分音 - U+00A9 © 版权符 - U+00AA ª (意大利文、葡萄牙文、西班牙文)阴性序数 - U+00AB « 双重角形引号 - U+00AC ¬ 逻辑非 - U+00AE ® 商标 - U+00AF ¯ 长音 - U+00B0 ° 角度 - U+00B1 ± 正负号 - U+00B2 ² 二次方 - U+00B3 ³ 三次方 - U+00B4 ´ 锐音符 - U+00B5 µ 百万分之一,10?6 - U+00B6 ¶ 文章分段 - U+00B7 · 间隔号 - U+00B8 ¸ 软音符 - U+00B9 ¹ 一次方 - U+00BA º (意大利文、葡萄牙文、西班牙文)阳性序数 - U+00BB » 指向右的双箭头 - U+00BC ¼ 四分之一 - U+00BD ½ 二分之一 - U+00BE ¾ 四分之三 - U+00BF ¿ 倒转的问号 - U+00C1 Á 在拉丁字母 A 上加锐音符 - U+00C2 Â 在拉丁字母 A 上加抑扬符“^” - U+00C3 Ã 在拉丁字母 A 上加“~” - U+00C4 Ä 在拉丁字母 A 上加分音符“..” - U+00C5 Å 在拉丁字母 A 上加角度符“°” - U+00C6 Æ 拉丁字母 A、E 的混合 - U+00C7 Ç 在拉丁字母 C 下加软音符 - U+00C8 È 在拉丁字母 E 上加重音符 - U+00C9 É 在拉丁字母 E 上加锐音符 - U+00CA Ê 在拉丁字母 E 上加抑扬符 - U+00CB Ë 在拉丁字母 E 上加分音符 - U+00CC Ì 在拉丁字母 I 上加重音符 - U+00CD Í 在拉丁字母 I 上加锐音符 - U+00CE Î 在拉丁字母 I 上加抑扬符 - U+00CF Ï 在拉丁字母 I 上加分音符 - U+00D0 Ð 古拉丁字母,现只有法罗文和冰岛文和越南语使用 - U+00D1 Ñ 在拉丁字母 N 上加波浪纹“~” - U+00D2 Ò 在拉丁字母 O 上加重音符 - U+00D3 Ó 在拉丁字母 O 上加锐音符 - U+00D4 Ô 在拉丁字母 O 上加抑扬符 - U+00D5 Õ 在拉丁字母 O 上加波浪纹“~” - U+00D6 Ö 在拉丁字母 O 上加分音符 - U+00D7 × 乘号,亦可拖按“Alt”键,同时按“41425”五键 - U+00D8 Ø 在拉丁字母 O 由右上至左下加对角斜线“/” - U+00D9 Ù 在拉丁字母 U 上加重音符 - U+00DA Ú 在拉丁字母 U 上加锐音符 - U+00DB Û 在拉丁字母 U 上加抑扬符 - U+00DC Ü 在拉丁字母 U 上加分音符 - U+00DD Ý 在拉丁字母 Y 上加锐音符 - U+00DE Þ 古拉丁字母,现已被“Th”取替 - U+00DF ß 德文字母 - U+00E0 à 在拉丁字母 a 上加重音符 - U+00E1 á 在拉丁字母 a 上加锐音符 - U+00E2 â 在拉丁字母 a 上加抑扬符 - U+00E3 ã 在拉丁字母 a 上加波浪纹“~” - U+00E4 ä 在拉丁字母 a 上加分音符 - U+00E5 å 在拉丁字母 a 上加角度符“°” - U+00E6 æ 拉丁字母 a、e 的混合 - U+00E7 ç 在拉丁字母 c 下加软音符 - U+00E8 è 在拉丁字母 e 上加锐音符 - U+00E9 é 在拉丁字母 e 上加重音符 - U+00EA ê 在拉丁字母 e 上加抑扬符 - U+00EB ë 在拉丁字母 e 上加分音符 - U+00EC ì 在拉丁字母 i 上加重音符 - U+00ED í 在拉丁字母 i 上加锐音符 - U+00EE î 在拉丁字母 i 上加抑扬符 - U+00EF ï 在拉丁字母 i 上加分音符 - U+00F0 ð 古拉丁字母 - U+00F1 ñ 在拉丁字母 n 上加波浪纹“~” - U+00F2 ò 在拉丁字母 o 上加重音符 - U+00F3 ó 在拉丁字母 o 上加锐音符 - U+00F4 ô 在拉丁字母 o 上加抑扬符 - U+00F5 õ 在拉丁字母 o 上加波浪纹“~” - U+00F6 ö 在拉丁字母 o 上加分音符 - U+00F7 ÷ 除号,亦可拖按“Alt”键,同时按“41426”五键 - U+00F8 ø 在拉丁字母 o 由右上至左下加对角斜线“/” - U+00F9 ù 在拉丁字母 u 上加重音符 - U+00FA ú 在拉丁字母 u 上加锐音符 - U+00FB ? 在拉丁字母 u 上加抑扬符 - U+00FC ü 在拉丁字母 u 上加分音符 - U+00FD ý 在拉丁字母 y 上加锐音符 - U+00FE þ 古拉丁字母,现已被“th”取替 - U+00FF ü 在拉丁字母 u 上加分音符 - 拉丁字母(扩展 A) - 代码 显示 描述 - U+0100 Ā 在拉丁字母 A 上加长音符 - U+0101 ā 在拉丁字母 a 上加长音符 - U+0102 Ă 在拉丁字母 A 上加短音符 - U+0103 ă 在拉丁字母 a 上加短音符 - U+0104 Ą 在拉丁字母 A 上加反尾形符 - U+0105 ą 在拉丁字母 a 上加反尾形符 - 拉丁字母(扩展 C) - 代码 显示 描述 - U+2C60 Ⱡ 在拉丁字母“L”中间加两条横线“=” - U+2C61 ⱡ 在拉丁字母“l”(L 的小写)中间加两条横线“=” - U+2C62 Ɫ 在拉丁字母“L”(大写)中间加一条波浪线“~” - U+2C63 Ᵽ 在拉丁字母“P”中间加一条横线“-” - U+2C64 Ɽ 在拉丁字母“R”下加一条尾巴 - U+2C65 ⱥ 在拉丁字母“a”上加一条对角斜线“/” - U+2C66 ⱦ 在拉丁字母“t”上加一条对角斜线“/” - U+2C67 Ⱨ 在拉丁字母“H”下加一条尾巴 - U+2C68 ⱨ 在拉丁字母“h”下加一条尾巴 - U+2C69 Ⱪ 在拉丁字母“K”下加一条尾巴 - U+2C6A ⱪ 在拉丁字母“k”下加一条尾巴 - U+2C6B Ⱬ 在拉丁字母“Z”下加一条尾巴 - U+2C6C ⱬ 在拉丁字母“z”下加一条尾巴 - U+2C74 ⱴ 在拉丁字母“v”的起笔加一个弯勾 - U+2C75 Ⱶ 拉丁字母“H”的左半部 - U+2C76 ⱶ 拉丁字母“h”的左半部 - U+2C77 ⱷ 希腊字母“φ”的上半部 - */ - if(/.*[\u00A1-\u0105]+.*$/.test(str)){ - return true; - } - if(/.*[\u2C60-\u2C77]+.*$/.test(str)){ - return true; - } - - - return false; - } - }, - //用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。 - //如果使用后,第二次在用,那就优先以用户所选择的为主 - executeByLocalLanguage:function(){ - this.request.post('https://api.translate.zvo.cn/ip.json', {}, function(data){ - //console.log(data); - if(data.result == 0){ - console.log('==== ERROR 获取当前用户所在区域异常 ===='); - console.log(data.info); - console.log('==== ERROR END ===='); - }else{ - translate.setUseVersion2(); - translate.storage.set('to',data.language); //设置目标翻译语言 - translate.to = data.language; //设置目标语言 - translate.selectLanguageTag - translate.execute(); //执行翻译 - } - }); - }, - - util:{ - /* 生成一个随机UUID,复制于 https://gitee.com/mail_osc/kefu.js */ - uuid:function() { - var d = new Date().getTime(); - if (window.performance && typeof window.performance.now === "function") { - d += performance.now(); //use high-precision timer if available - } - var uuid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = (d + Math.random() * 16) % 16 | 0; - d = Math.floor(d / 16); - return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); - }); - return uuid; - }, - - //判断字符串中是否存在tag标签。 true存在 - findTag:function(str) { - var reg = /<[^>]+>/g; - return reg.test(str); - }, - //传入一个数组,从数组中找出现频率最多的一个返回。 如果多个频率出现的次数一样,那会返回多个 - arrayFindMaxNumber:function(arr){ - - // 储存每个元素出现的次数 - var numbers = {} - - // 储存出现最多次的元素 - var maxStr = [] - - // 储存最多出现的元素次数 - var maxNum = 0 - - for(var i =0,len=arr.length;imaxNum){ - maxNum = numbers[arr[i]] - } - } - - for(var item in numbers){ - if(numbers[item]===maxNum){ - maxStr.push(item) - } - } - - return maxStr; - }, - //对字符串进行hash化,目的取唯一值进行标识 - hash:function(str){ - if(str == null || typeof(str) == 'undefined'){ - return str; - } - var hash = 0, i, chr; - if (str.length === 0){ - return hash; - } - - for (i = 0; i < str.length; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer - } - return hash+''; - }, - //去除一些指定字符,如换行符。 如果传入的是null,则返回空字符串 - charReplace:function(str){ - - if(str == null){ - return ''; - } - str = str.trim(); - str = str.replace(/\t|\n|\v|\r|\f/g,''); //去除换行符等 - //str = str.replace(/&/g, "%26"); //因为在提交时已经进行了url编码了 - return str; - }, - }, - //request请求来源于 https://github.com/xnx3/request - request:{ - /** - * post请求 - * @param url 请求的接口URL,传入如 http://www.xxx.com/a.php - * @param data 请求的参数数据,传入如 {"goodsid":"1", "author":"管雷鸣"} - * @param func 请求完成的回调,传入如 function(data){ console.log(data); } - */ - post:function(url, data, func){ - var headers = { - 'content-type':'application/x-www-form-urlencoded', - }; - this.send(url, data, func, 'post', true, headers, null); - }, - /** - * 发送请求 - * url 请求的url - * data 请求的数据,如 {"author":"管雷鸣",'site':'www.guanleiming.com'} - * func 请求完成的回调,传入如 function(data){} - * method 请求方式,可传入 post、get - * isAsynchronize 是否是异步请求, 传入 true 是异步请求,传入false 是同步请求 - * headers 设置请求的header,传入如 {'content-type':'application/x-www-form-urlencoded'}; - * abnormalFunc 响应异常所执行的方法,响应码不是200就会执行这个方法 ,传入如 function(xhr){} - */ - send:function(url, data, func, method, isAsynchronize, headers, abnormalFunc){ - //post提交的参数 - var params = ''; - if(data != null){ - for(var index in data){ - if(params.length > 0){ - params = params + '&'; - } - params = params + index + '=' + data[index]; - } - } - - var xhr=null; - try{ - xhr=new XMLHttpRequest(); - }catch(e){ - xhr=new ActiveXObject("Microsoft.XMLHTTP"); - } - //2.调用open方法(true----异步) - xhr.open(method,url,isAsynchronize); - //设置headers - if(headers != null){ - for(var index in headers){ - xhr.setRequestHeader(index,headers[index]); - } - } - xhr.send(params); - //4.请求状态改变事件 - xhr.onreadystatechange=function(){ - if(xhr.readyState==4){ - if(xhr.status==200){ - //请求正常,响应码 200 - var json = null; - try{ - json = JSON.parse(xhr.responseText); - }catch(e){ - console.log(e); - } - if(json == null){ - func(xhr.responseText); - }else{ - func(json); - } - }else{ - if(abnormalFunc != null){ - abnormalFunc(xhr); - } - } - } - } - } - }, - //存储,本地缓存 - storage:{ - set:function(key,value){ - localStorage.setItem(key,value); - }, - get:function(key){ - return localStorage.getItem(key); - } - } - - - - /**************************** v2.0 end */ - -} - - -//这个只是v1使用到 -try{ - translate.init(); - //translate.execute(); -}catch(e){ console.log(e); } - + var translate={version:"2.1.6.20230108",useVersion:"v1",setUseVersion2:function(){this.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}this.setUseVersion2(),this.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){this.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?this.documents[0]=e:this.documents=e,this.nodeQueue={})},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&(n.push.apply(n,t.addedNodes),console.log(t.addedNodes));n.length>0&&(translate.setDocuments(n),translate.execute())}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodeQueue=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodeQueue[a]&&(this.nodeQueue[a]=new Array),this.nodeQueue[a].push(e);var s=this.taskQueue[a];null!=s&&void 0!==s||(s=new Array);var o=new Array;o.originalText=t,o.resultText=n,s.push(o),this.taskQueue[a]=s}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodeQueue)for(var t=this.taskQueue[e],n=0;n0&&(this.to=n)}try{this.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=this.to&&void 0!==this.to&&0!=this.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=documents}else a=null!=this.documents&&void 0!==this.documents&&this.documents.length>0?this.documents:document.all;for(var s=0;s0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,s=t.parentNode;t!=s&&null!=s;)null!=s.className&&this.ignore.class.indexOf(s.className)>-1&&(a=!0),s=s.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&this.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;this.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){this.util.hash(t.nodeValue);if(!this.util.findTag(t.nodeValue)){var n=this.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=this.nodeQueue[e][a]&&void 0!==this.nodeQueue[e][a]||(this.nodeQueue[e][a]=new Array);for(var s=0;s]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,s=0,o=e.length;sa&&(a=t[e[s]]);for(var r in t)t[r]===a&&n.push(r);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(l+="&"),l=l+i+"="+t[i];var u=null;try{u=new XMLHttpRequest}catch(e){u=new ActiveXObject("Microsoft.XMLHTTP")}if(u.open(a,e,s),null!=o)for(var i in o)u.setRequestHeader(i,o[i]);u.send(l),u.onreadystatechange=function(){if(4==u.readyState)if(200==u.status){var e=null;try{e=JSON.parse(u.responseText)}catch(e){console.log(e)}n(null==e?u.responseText:e)}else null!=r&&r(u)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); + window.translate = translate; //输出 translate 接口 exports('translate', translate); }); \ No newline at end of file -- Gitee From 8f6bb8892791db4e3bb1d194ea92b9e144d094a1 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 15:29:06 +0800 Subject: [PATCH 09/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index 71fdd1b..0d3607d 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -51,8 +51,8 @@ layui.config({ var translate = layui.translate; //当页面加载完后执行翻译操作 - window.onload = function () { + //window.onload = function () { translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 translate.execute(); - }; + //}; }); \ No newline at end of file -- Gitee From ab71512fd6c6a35902c47620a328d957a36fbf86 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Mon, 9 Jan 2023 17:01:32 +0800 Subject: [PATCH 10/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 48c73c1..fec5b09 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,7 +3,7 @@ */ layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.6.20230108",useVersion:"v1",setUseVersion2:function(){this.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}this.setUseVersion2(),this.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){this.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?this.documents[0]=e:this.documents=e,this.nodeQueue={})},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&(n.push.apply(n,t.addedNodes),console.log(t.addedNodes));n.length>0&&(translate.setDocuments(n),translate.execute())}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodeQueue=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodeQueue[a]&&(this.nodeQueue[a]=new Array),this.nodeQueue[a].push(e);var s=this.taskQueue[a];null!=s&&void 0!==s||(s=new Array);var o=new Array;o.originalText=t,o.resultText=n,s.push(o),this.taskQueue[a]=s}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodeQueue)for(var t=this.taskQueue[e],n=0;n0&&(this.to=n)}try{this.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=this.to&&void 0!==this.to&&0!=this.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=documents}else a=null!=this.documents&&void 0!==this.documents&&this.documents.length>0?this.documents:document.all;for(var s=0;s0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,s=t.parentNode;t!=s&&null!=s;)null!=s.className&&this.ignore.class.indexOf(s.className)>-1&&(a=!0),s=s.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&this.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;this.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){this.util.hash(t.nodeValue);if(!this.util.findTag(t.nodeValue)){var n=this.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=this.nodeQueue[e][a]&&void 0!==this.nodeQueue[e][a]||(this.nodeQueue[e][a]=new Array);for(var s=0;s]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,s=0,o=e.length;sa&&(a=t[e[s]]);for(var r in t)t[r]===a&&n.push(r);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(l+="&"),l=l+i+"="+t[i];var u=null;try{u=new XMLHttpRequest}catch(e){u=new ActiveXObject("Microsoft.XMLHTTP")}if(u.open(a,e,s),null!=o)for(var i in o)u.setRequestHeader(i,o[i]);u.send(l),u.onreadystatechange=function(){if(4==u.readyState)if(200==u.status){var e=null;try{e=JSON.parse(u.responseText)}catch(e){console.log(e)}n(null==e?u.responseText:e)}else null!=r&&r(u)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} + var translate={version:"2.1.6.20230108",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodes=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodes[a]&&(this.nodes[a]=new Array),this.nodes[a].push(e);var r=this.taskQueue[a];null!=r&&void 0!==r||(r=new Array);var l=new Array;l.originalText=t,l.resultText=n,r.push(l),this.taskQueue[a]=r}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodes)for(var t=this.taskQueue[e],n=0;n0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all;for(var r=0;r0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,r=t.parentNode;t!=r&&null!=r;)null!=r.className&&translate.ignore.class.indexOf(r.className)>-1&&(a=!0),r=r.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e][a]&&void 0!==translate.nodeQueue[e][a]||(translate.nodeQueue[e][a]=new Array);for(var r=0;r]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,r=0,l=e.length;ra&&(a=t[e[r]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,r),null!=l)for(var u in l)i.setRequestHeader(u,l[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); -- Gitee From 8c5e008f1c505127b109cca20b4c261f92e765b9 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 14:20:23 +0800 Subject: [PATCH 11/37] =?UTF-8?q?admin.js=20=E5=A2=9E=E5=8A=A0=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 48 ++++++++++++++++++++++++++++-- component/pear/module/translate.js | 4 +-- component/pear/pear.js | 9 +----- config/pear.config.yml | 12 +++++++- 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index b829933..89146dd 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -1,4 +1,4 @@ -layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'menu', 'frame', 'theme', 'convert','fullscreen'], +layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'menu', 'frame', 'theme', 'convert','fullscreen', 'translate'], function(exports) { "use strict"; @@ -12,7 +12,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm pearFrame = layui.frame, pearTheme = layui.theme, message = layui.message, - fullscreen=layui.fullscreen; + fullscreen=layui.fullscreen, + translate = layui.translate; var bodyFrame; var sideMenu; @@ -413,6 +414,49 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm $(".fullScreen").eq(0).addClass("layui-icon-screen-restore"); }); } + }, + this.translate = function(option){ + if(typeof(option.translate) == 'undefined'){ + return; + } + window.translate = translate; + if(typeof(option.translate.autoDiscriminateLocalLanguage) != 'undefined' && option.translate.autoDiscriminateLocalLanguage == true){ + translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 + } + if(typeof(option.translate.currentLanguage) != 'undefined' && option.translate.currentLanguage.length > 0){ + translate.language.setLocal(option.translate.currentLanguage); + } + if(typeof(option.translate.ignoreClass) != 'undefined' && option.translate.ignoreClass.length > 0){ + var classs = option.translate.ignoreClass.split(','); + for(var ci = 0; ci < classs.length; ci++){ + var className = classs[i].trim(); + if(className.length > 0){ + if(translate.ignore.class.indexOf(className.toLowerCase()) > -1){ + //已经有了,忽略 + }else{ + //还没有,加入 + translate.ignore.class.push(className); + } + } + } + } + if(typeof(option.translate.ignoreTag) != 'undefined' && option.translate.ignoreTag.length > 0){ + var classs = option.translate.ignoreTag.split(','); + for(var ci = 0; ci < classs.length; ci++){ + var className = classs[i].trim(); + if(className.length > 0){ + if(translate.ignore.tag.indexOf(className.toLowerCase()) > -1){ + //已经有了,忽略 + }else{ + //还没有,加入 + translate.ignore.tag.push(className); + } + } + } + } + + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.execute(); } }; diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index fec5b09..a67eeae 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,8 +3,8 @@ */ layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.6.20230108",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e=document;new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)}).observe(e,{attributes:!0,childList:!0,subtree:!0})}},renderTask:class{constructor(){this.taskQueue=[],this.nodes=[]}add(e,t,n){var a=translate.util.hash(e.nodeValue);void 0===this.nodes[a]&&(this.nodes[a]=new Array),this.nodes[a].push(e);var r=this.taskQueue[a];null!=r&&void 0!==r||(r=new Array);var l=new Array;l.originalText=t,l.resultText=n,r.push(l),this.taskQueue[a]=r}execute(){for(var e in this.taskQueue){(t=this.taskQueue[e]).sort(function(e,t){return t.originalText.length-e.originalText.length}),this.taskQueue[e]=t}for(var e in this.nodes)for(var t=this.taskQueue[e],n=0;n0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all;for(var r=0;r0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,r=t.parentNode;t!=r&&null!=r;)null!=r.className&&translate.ignore.class.indexOf(r.className)>-1&&(a=!0),r=r.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e][a]&&void 0!==translate.nodeQueue[e][a]||(translate.nodeQueue[e][a]=new Array);for(var r=0;r]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,r=0,l=e.length;ra&&(a=t[e[r]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,r),null!=l)for(var u in l)i.setRequestHeader(u,l[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} - + var translate={version:"2.1.7.20230109",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} + //默认就是用新的v2版本 translate.setUseVersion2(); window.translate = translate; diff --git a/component/pear/pear.js b/component/pear/pear.js index 0d3607d..3255b7c 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -46,13 +46,6 @@ layui.config({ fullscreen:"fullscreen", //全屏组件 popover:"popover/popover", //汽泡组件 translate:"translate" //多语言翻译组件 -}).use(['layer', 'theme', 'translate'], function () { +}).use(['layer', 'theme'], function () { layui.theme.changeTheme(window, false); - - var translate = layui.translate; - //当页面加载完后执行翻译操作 - //window.onload = function () { - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - translate.execute(); - //}; }); \ No newline at end of file diff --git a/config/pear.config.yml b/config/pear.config.yml index 4b7cd70..f9b8227 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -79,4 +79,14 @@ other: ## 头部配置 header: ## 站内消息,通过 false 设置关闭 - message: "admin/data/message.json" \ No newline at end of file + message: "admin/data/message.json" +## 多语言翻译配置 +translate: + ## 当前语种,有: chinese_simplified 简体中文 、chinese_traditional 繁体中文、english 英语、korean 韩语 ,默认是 chinese_simplified 简体中文 + localLanguage: "chinese_simplified" + ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 + autoDiscriminateLocalLanguage:false + ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 + ignoreClass: "ignore,test1" + ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 + ignoreTag: "script,pre,code" -- Gitee From 2a9ea97c768a67cb1ea585d9aeec6de4437d5e12 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 14:24:51 +0800 Subject: [PATCH 12/37] update yml --- config/pear.config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/pear.config.yml b/config/pear.config.yml index f9b8227..e2e1c36 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -85,8 +85,8 @@ translate: ## 当前语种,有: chinese_simplified 简体中文 、chinese_traditional 繁体中文、english 英语、korean 韩语 ,默认是 chinese_simplified 简体中文 localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 - autoDiscriminateLocalLanguage:false + autoDiscriminateLocalLanguage: false ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 - ignoreTag: "script,pre,code" + ignoreTag: "script,pre,code" \ No newline at end of file -- Gitee From c99c602a109a2a218742a8d94eaec011599e0509 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 14:29:40 +0800 Subject: [PATCH 13/37] update yml --- component/pear/module/admin.js | 2 +- config/pear.config.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 89146dd..6f919c6 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -420,7 +420,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm return; } window.translate = translate; - if(typeof(option.translate.autoDiscriminateLocalLanguage) != 'undefined' && option.translate.autoDiscriminateLocalLanguage == true){ + if(typeof(option.translate.autoDiscriminateLocalLanguage) != 'undefined' && (option.translate.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 } if(typeof(option.translate.currentLanguage) != 'undefined' && option.translate.currentLanguage.length > 0){ diff --git a/config/pear.config.yml b/config/pear.config.yml index e2e1c36..ea8ed32 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -85,7 +85,7 @@ translate: ## 当前语种,有: chinese_simplified 简体中文 、chinese_traditional 繁体中文、english 英语、korean 韩语 ,默认是 chinese_simplified 简体中文 localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 - autoDiscriminateLocalLanguage: false + autoDiscriminateLocalLanguage: "false" ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 -- Gitee From 30b0bd140ccd144ac22f95503635e6c3782e16f3 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 14:33:18 +0800 Subject: [PATCH 14/37] update yml --- config/pear.config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/pear.config.yml b/config/pear.config.yml index ea8ed32..ef0c9d9 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -85,7 +85,8 @@ translate: ## 当前语种,有: chinese_simplified 简体中文 、chinese_traditional 繁体中文、english 英语、korean 韩语 ,默认是 chinese_simplified 简体中文 localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 - autoDiscriminateLocalLanguage: "false" + ## 这个开启yml格式化报错 message: "Unable to parse." 所以注释掉了 + ##autoDiscriminateLocalLanguage: "false" ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 -- Gitee From 4321ddc69419760ea6d61e6455837c63392477e9 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 14:56:07 +0800 Subject: [PATCH 15/37] update admin.js --- component/pear/module/admin.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 6f919c6..626249e 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -455,8 +455,11 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } } - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - translate.execute(); + window.onload = function(){ + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.execute(); + } + } }; -- Gitee From 8505b614826d13bf4b18355ae10e565995978cb7 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 15:16:38 +0800 Subject: [PATCH 16/37] update admin.js --- component/pear/module/admin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 626249e..c076e20 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -458,8 +458,10 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm window.onload = function(){ translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 translate.execute(); + + //避免有遗漏,特别是表格的render渲染等,诡异的会复原 + setTimeout(translate.execute,1500); } - } }; -- Gitee From e380655b5bd33393edeaef6a33148aedd27c3717 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 15:29:35 +0800 Subject: [PATCH 17/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index a67eeae..757453c 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,7 +3,7 @@ */ layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.7.20230109",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} + var translate={version:"2.1.8.20230110",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); -- Gitee From c79d72472c36385c3a1238db63e6124f182425b9 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 15:31:52 +0800 Subject: [PATCH 18/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 757453c..707125b 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,7 +3,7 @@ */ layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.8.20230110",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} + var translate={version:"2.1.9.20230110",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); -- Gitee From 17298643694edd49453897628cae66281360efdc Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 15:43:51 +0800 Subject: [PATCH 19/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/translate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/module/translate.js b/component/pear/module/translate.js index 707125b..e08441d 100644 --- a/component/pear/module/translate.js +++ b/component/pear/module/translate.js @@ -3,7 +3,7 @@ */ layui.define(['table', 'form', 'element'], function (exports) { //下行是直接将https://gitee.com/mail_osc/translate 压缩后粘贴过来 - var translate={version:"2.1.9.20230110",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} + var translate={version:"2.1.8.20230110",useVersion:"v1",setUseVersion2:function(){translate.useVersion="v2"},translate:null,includedLanguages:"zh-CN,zh-TW,en",resourcesUrl:"//res.zvo.cn/translate",selectLanguageTag:{show:!0,languages:"zh-CN,zh-TW,en",alreadyRender:!1,render:function(){if(!translate.selectLanguageTag.alreadyRender&&(translate.selectLanguageTag.alreadyRender=!0,translate.selectLanguageTag.show)){if(null==document.getElementById("translate")){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}else if(null!=document.getElementById("translateSelectLanguage"))return;translate.request.post("https://api.translate.zvo.cn/language.json",{},function(e){if(0!=e.result){var t=function(e){var t=e.target.value;translate.changeLanguage(t)},n=document.createElement("select");n.id="translateSelectLanguage",n.className="translateSelectLanguage";for(var a=0;a0?translate.to==e.list[a].id&&l.setAttribute("selected","selected"):e.list[a].id==translate.language.local&&l.setAttribute("selected","selected"),l.appendChild(document.createTextNode(e.list[a].name)),n.appendChild(l)}window.addEventListener?n.addEventListener("change",t,!1):n.attachEvent("onchange",t),document.getElementById("translate").appendChild(n)}else console.log("load language list error : "+e.info)})}}},localLanguage:"zh-CN",googleTranslateElementInit:function(){var e="";null!=document.getElementById("translate")&&(e="translate"),translate.translate=new google.translate.TranslateElement({pageLanguage:"zh-CN",includedLanguages:translate.selectLanguageTag.languages,layout:0},e)},init:function(){var e=window.location.protocol;"file:"==window.location.protocol&&(e="http:"),-1==this.resourcesUrl.indexOf("://")&&(this.resourcesUrl=e+this.resourcesUrl)},execute_v1:function(){if(null==document.getElementById("translate")&&translate.selectLanguageTag.show){var e=document.getElementsByTagName("body")[0],t=document.createElement("div");t.id="translate",e.appendChild(t)}"zh-CN,zh-TW,en"!=translate.includedLanguages&&(translate.selectLanguageTag.languages=translate.includedLanguages,console.log("translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set"));var n=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.src=this.resourcesUrl+"/js/element.js",n.appendChild(a)},setCookie:function(e,t){var n=e+"="+escape(t);document.cookie=n},getCookie:function(e){for(var t=document.cookie.split("; "),n=0;n0?e.substr(e.lastIndexOf("/")+1,e.length-1):translate.localLanguage},changeLanguage:function(e){if(",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,".indexOf(","+e+",")>-1){translate.check();var t="/"+translate.localLanguage+"/"+e,n=document.location.host.split(".");if(n.length>2){var a=n[n.length-2]+"."+n[n.length-1];document.cookie="googtrans=;expires="+new Date(1)+";domain="+a+";path=/",document.cookie="googtrans="+t+";domain="+a+";path=/"}return translate.setCookie("googtrans",""+t),void location.reload()}translate.setUseVersion2(),translate.to=e,translate.storage.set("to",e),location.reload()},check:function(){"file:"==window.location.protocol&&console.log("\r\n---WARNING----\r\ntranslate.js 主动翻译组件自检异常,当前协议是file协议,翻译组件要在正常的线上http、https协议下才能正常使用翻译功能\r\n------------")},to:"",autoDiscriminateLocalLanguage:!1,documents:[],ignore:{tag:["style","script","img","head","link","i","pre","code"],class:["ignore","translateSelectLanguage"]},setAutoDiscriminateLocalLanguage:function(){translate.autoDiscriminateLocalLanguage=!0},nodeQueue:{},setDocuments:function(e){null!=e&&void 0!==e&&(void 0===e.length?translate.documents[0]=e:translate.documents=e,translate.nodeQueue={},console.log("set documents , clear translate.nodeQueue"))},getDocuments:function(){return null!=translate.documents&&void 0!==translate.documents&&translate.documents.length>0?translate.documents:document.all},listener:{isExecuteFinish:!1,isStart:!1,start:function(){translate.temp_linstenerStartInterval=setInterval(function(){"complete"==document.readyState&&(clearInterval(translate.temp_linstenerStartInterval),translate.listener.addListener())},50)},addListener:function(){translate.listener.isStart=!0;const e={attributes:!0,childList:!0,subtree:!0},t=new MutationObserver(function(e,t){var n=[];for(let t of e)"childList"===t.type&&t.addedNodes.length>0&&n.push.apply(n,t.addedNodes);n.length>0&&translate.execute(n)});for(var n=translate.getDocuments(),a=0;a0&&(translate.to=n)}try{translate.selectLanguageTag.render()}catch(e){console.log(e)}if(null!=translate.to&&void 0!==translate.to&&0!=translate.to.length){var a;if(void 0!==e){if(null==e)return void cnosole.log("translate.execute(...) 中传入的要翻译的目标区域不存在。");void 0===e.length?(a=new Array)[0]=e:a=e}else a=translate.getDocuments();for(var l=0;l0)for(var g=0;g0)for(var a=0;a-1)){for(var a=!1,l=t.parentNode;t!=l&&null!=l;)null!=l.className&&translate.ignore.class.indexOf(l.className)>-1&&(a=!0),l=l.parentNode;if(!a)if("INPUT"==t.nodeName||"TEXTAREA"==t.nodeName){if(null==t.attributes||void 0===t.attributes)return;void 0!==t.attributes.placeholder&&translate.addNodeToQueue(e,t.attributes.placeholder)}else if(null!=t.nodeValue&&t.nodeValue.trim().length>0){if(!(null!=t.nodeValue&&"string"==typeof t.nodeValue&&t.nodeValue.length>0))return;translate.addNodeToQueue(e,t)}}}},addNodeToQueue:function(e,t){if(null!=t.nodeValue&&0!=t.nodeValue.length){translate.util.hash(t.nodeValue);if(!translate.util.findTag(t.nodeValue)){var n=translate.language.get(t.nodeValue);for(var a in void 0!==n[translate.to]&&delete n[translate.to],n){null!=translate.nodeQueue[e].list[a]&&void 0!==translate.nodeQueue[e].list[a]||(translate.nodeQueue[e].list[a]=new Array);for(var l=0;l]+>/g.test(e)},arrayFindMaxNumber:function(e){for(var t={},n=[],a=0,l=0,r=e.length;la&&(a=t[e[l]]);for(var s in t)t[s]===a&&n.push(s);return n},hash:function(e){if(null==e||void 0===e)return e;var t,n=0;if(0===e.length)return n;for(t=0;t0&&(o+="&"),o=o+u+"="+t[u];var i=null;try{i=new XMLHttpRequest}catch(e){i=new ActiveXObject("Microsoft.XMLHTTP")}if(i.open(a,e,l),null!=r)for(var u in r)i.setRequestHeader(u,r[u]);i.send(o),i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status){var e=null;try{e=JSON.parse(i.responseText)}catch(e){console.log(e)}n(null==e?i.responseText:e)}else null!=s&&s(i)}}},storage:{set:function(e,t){localStorage.setItem(e,t)},get:function(e){return localStorage.getItem(e)}}};try{translate.init()}catch(e){console.log(e)} //默认就是用新的v2版本 translate.setUseVersion2(); -- Gitee From 0069f625da01d0d664ad65ecd66cb7cb4acc5207 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 16:09:33 +0800 Subject: [PATCH 20/37] update admin.js --- component/pear/module/admin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index c076e20..76dc1e9 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -454,6 +454,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } } } + translate.setUseVersion2(); //设置使用v2.x 版本 window.onload = function(){ translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 -- Gitee From c820b675b27bbbed3809ab0625af2c1414b969e7 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 19:43:07 +0800 Subject: [PATCH 21/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 76dc1e9..081ecb3 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -456,13 +456,19 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } translate.setUseVersion2(); //设置使用v2.x 版本 - window.onload = function(){ - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - translate.execute(); - - //避免有遗漏,特别是表格的render渲染等,诡异的会复原 - setTimeout(translate.execute,1500); - } + window.translate.temp_layuiExecuteInterval = setInterval(function(){ + if(document.readyState == 'complete'){ + //dom加载完成,进行启动 + clearInterval(window.translate.temp_layuiExecuteInterval);//停止 + console.log('window.translate.temp_layuiExecuteInterval stop'); + + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.execute(); + + //避免有遗漏,特别是表格的render渲染等,诡异的会复原 + setTimeout(translate.execute,1500); + } + }, 30); } }; -- Gitee From 68f3d278596bd5e0a60e118e6d31d858b1144dbe Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 19:47:36 +0800 Subject: [PATCH 22/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 081ecb3..5035dea 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -416,6 +416,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } }, this.translate = function(option){ + console.log('translate ....') + console.log(option); if(typeof(option.translate) == 'undefined'){ return; } @@ -951,6 +953,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm if (param.header.message != false) { pearAdmin.messageRender(param); } + pearAdmin.translate(param); } function getColorById(id) { -- Gitee From 61934076ab91818757cb8ced3be61beb0a640455 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 19:50:14 +0800 Subject: [PATCH 23/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 5035dea..ad8f39d 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -431,7 +431,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm if(typeof(option.translate.ignoreClass) != 'undefined' && option.translate.ignoreClass.length > 0){ var classs = option.translate.ignoreClass.split(','); for(var ci = 0; ci < classs.length; ci++){ - var className = classs[i].trim(); + var className = classs[ci].trim(); if(className.length > 0){ if(translate.ignore.class.indexOf(className.toLowerCase()) > -1){ //已经有了,忽略 @@ -443,15 +443,15 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } } if(typeof(option.translate.ignoreTag) != 'undefined' && option.translate.ignoreTag.length > 0){ - var classs = option.translate.ignoreTag.split(','); - for(var ci = 0; ci < classs.length; ci++){ - var className = classs[i].trim(); - if(className.length > 0){ - if(translate.ignore.tag.indexOf(className.toLowerCase()) > -1){ + var tags = option.translate.ignoreTag.split(','); + for(var ti = 0; ti < tags.length; ti++){ + var tagName = tags[i].trim(); + if(tagName.length > 0){ + if(translate.ignore.tag.indexOf(tagName.toLowerCase()) > -1){ //已经有了,忽略 }else{ //还没有,加入 - translate.ignore.tag.push(className); + translate.ignore.tag.push(tagName); } } } -- Gitee From c08f564bdf7933f3f04548ceb607da2d3f8f835e Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 19:51:39 +0800 Subject: [PATCH 24/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index ad8f39d..d0a7960 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -445,7 +445,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm if(typeof(option.translate.ignoreTag) != 'undefined' && option.translate.ignoreTag.length > 0){ var tags = option.translate.ignoreTag.split(','); for(var ti = 0; ti < tags.length; ti++){ - var tagName = tags[i].trim(); + var tagName = tags[ti].trim(); if(tagName.length > 0){ if(translate.ignore.tag.indexOf(tagName.toLowerCase()) > -1){ //已经有了,忽略 -- Gitee From 3d1443d7275075ccce10ac65af4dabaf51998733 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:04:48 +0800 Subject: [PATCH 25/37] =?UTF-8?q?=E4=B8=8D=E7=BF=BB=E8=AF=91LOGO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/pear.config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/pear.config.yml b/config/pear.config.yml index ef0c9d9..c90eb24 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -88,6 +88,6 @@ translate: ## 这个开启yml格式化报错 message: "Unable to parse." 所以注释掉了 ##autoDiscriminateLocalLanguage: "false" ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 - ignoreClass: "ignore,test1" + ignoreClass: "ignore,test1,layui-logo" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 ignoreTag: "script,pre,code" \ No newline at end of file -- Gitee From d7c102931bb50e406a06cbda059e324f2d465ef2 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:09:57 +0800 Subject: [PATCH 26/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/pear.config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/pear.config.yml b/config/pear.config.yml index c90eb24..0abd8d4 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -86,7 +86,7 @@ translate: localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 ## 这个开启yml格式化报错 message: "Unable to parse." 所以注释掉了 - ##autoDiscriminateLocalLanguage: "false" + autoDiscriminateLocalLanguage: "false" ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1,layui-logo" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 -- Gitee From 7ee87a9e9b6556e591925d8c9b8a734f25d6a0b2 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:20:25 +0800 Subject: [PATCH 27/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 6 +++--- config/pear.config.json | 6 ++++++ config/pear.config.yml | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index d0a7960..3f61f2d 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -416,12 +416,12 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } }, this.translate = function(option){ - console.log('translate ....') - console.log(option); + //console.log('translate ....') + //console.log(option); if(typeof(option.translate) == 'undefined'){ return; } - window.translate = translate; + //window.translate = translate; if(typeof(option.translate.autoDiscriminateLocalLanguage) != 'undefined' && (option.translate.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 } diff --git a/config/pear.config.json b/config/pear.config.json index 2c1334d..580fb5a 100644 --- a/config/pear.config.json +++ b/config/pear.config.json @@ -66,5 +66,11 @@ }, "header": { "message": "admin/data/message.json" + }, + "translate": { + "localLanguage": "chinese_simplified", + "autoDiscriminateLocalLanguage": false, + "ignoreClass": "ignore,test1,layui-logo", + "ignoreTag": "script,pre,code" } } \ No newline at end of file diff --git a/config/pear.config.yml b/config/pear.config.yml index 0abd8d4..9ee5147 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -86,7 +86,7 @@ translate: localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 ## 这个开启yml格式化报错 message: "Unable to parse." 所以注释掉了 - autoDiscriminateLocalLanguage: "false" + autoDiscriminateLocalLanguage: false ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1,layui-logo" ## 翻译时忽略指定的tag标签,多个标签之间用逗号分割 -- Gitee From 40b9cbc6ebda70c999cee673103f7133c1123595 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:26:02 +0800 Subject: [PATCH 28/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/component/pear/pear.js b/component/pear/pear.js index 3255b7c..19ac771 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -48,4 +48,17 @@ layui.config({ translate:"translate" //多语言翻译组件 }).use(['layer', 'theme'], function () { layui.theme.changeTheme(window, false); + + window.translate.temp_pearInterval = setInterval(function(){ + if(typeof(translate) != 'undefined'){ //admin.js初始化完毕,translate已初始化成功 + clearInterval(window.translate.temp_pearInterval);//停止 + console.log('window.translate.temp_pearIntervalstop'); + + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.execute(); + + //避免有遗漏,特别是表格的render渲染等,诡异的会复原 + setTimeout(translate.execute,1500); + } + }, 30); }); \ No newline at end of file -- Gitee From 68009251ff754592688da422b8d1f5207b889cac Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:33:31 +0800 Subject: [PATCH 29/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index 19ac771..d64f90b 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -49,16 +49,20 @@ layui.config({ }).use(['layer', 'theme'], function () { layui.theme.changeTheme(window, false); - window.translate.temp_pearInterval = setInterval(function(){ - if(typeof(translate) != 'undefined'){ //admin.js初始化完毕,translate已初始化成功 - clearInterval(window.translate.temp_pearInterval);//停止 - console.log('window.translate.temp_pearIntervalstop'); - - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - translate.execute(); - - //避免有遗漏,特别是表格的render渲染等,诡异的会复原 - setTimeout(translate.execute,1500); - } - }, 30); + if(typeof(window.translate.temp_pearInterval) == 'undefined'){ + window.translate.temp_pearInterval = setInterval(function(){ + if(typeof(translate) != 'undefined' && translate.listener.start){ //admin.js初始化完毕,translate已初始化成功 + clearInterval(window.translate.temp_pearInterval);//停止 + console.log('window.translate.temp_pearIntervalstop'); + + translate.selectLanguageTag.show = false; //内页中不显示 select 语言选择,因为在顶部已经有了 + translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.execute(); + + //避免有遗漏,特别是表格的render渲染等,诡异的会复原 + setTimeout(translate.execute,1500); + } + }, 30); + } + }); \ No newline at end of file -- Gitee From d6998371c42b8becc29650add8d48a61ad1b54d9 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:35:54 +0800 Subject: [PATCH 30/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index d64f90b..109bd16 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -51,7 +51,7 @@ layui.config({ if(typeof(window.translate.temp_pearInterval) == 'undefined'){ window.translate.temp_pearInterval = setInterval(function(){ - if(typeof(translate) != 'undefined' && translate.listener.start){ //admin.js初始化完毕,translate已初始化成功 + if(typeof(translate) != 'undefined' && translate.listener.isStart){ //admin.js初始化完毕,translate已初始化成功 clearInterval(window.translate.temp_pearInterval);//停止 console.log('window.translate.temp_pearIntervalstop'); -- Gitee From 4f5d7f8c04c5f1caf526a94c90500ded25b765f7 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 20:39:59 +0800 Subject: [PATCH 31/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index 109bd16..c0b2e3d 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -49,11 +49,11 @@ layui.config({ }).use(['layer', 'theme'], function () { layui.theme.changeTheme(window, false); - if(typeof(window.translate.temp_pearInterval) == 'undefined'){ - window.translate.temp_pearInterval = setInterval(function(){ + if(typeof(template_temp_pearInterval) == 'undefined'){ + var template_temp_pearInterval = setInterval(function(){ if(typeof(translate) != 'undefined' && translate.listener.isStart){ //admin.js初始化完毕,translate已初始化成功 - clearInterval(window.translate.temp_pearInterval);//停止 - console.log('window.translate.temp_pearIntervalstop'); + clearInterval(template_temp_pearInterval);//停止 + console.log('template_temp_pearInterval stop'); translate.selectLanguageTag.show = false; //内页中不显示 select 语言选择,因为在顶部已经有了 translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 -- Gitee From f04c292a5216154e95240b0eb97a7c7b1f930d31 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 21:18:36 +0800 Subject: [PATCH 32/37] =?UTF-8?q?=E5=A4=A7=E8=B0=83=E6=95=B4=EF=BC=8C?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E4=BA=A4=E7=BB=99=20pear.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 56 ++++------------------------- component/pear/pear.js | 66 +++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 57 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 3f61f2d..ddbb2ad 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -421,56 +421,14 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm if(typeof(option.translate) == 'undefined'){ return; } - //window.translate = translate; - if(typeof(option.translate.autoDiscriminateLocalLanguage) != 'undefined' && (option.translate.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ - translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 - } - if(typeof(option.translate.currentLanguage) != 'undefined' && option.translate.currentLanguage.length > 0){ - translate.language.setLocal(option.translate.currentLanguage); - } - if(typeof(option.translate.ignoreClass) != 'undefined' && option.translate.ignoreClass.length > 0){ - var classs = option.translate.ignoreClass.split(','); - for(var ci = 0; ci < classs.length; ci++){ - var className = classs[ci].trim(); - if(className.length > 0){ - if(translate.ignore.class.indexOf(className.toLowerCase()) > -1){ - //已经有了,忽略 - }else{ - //还没有,加入 - translate.ignore.class.push(className); - } - } - } - } - if(typeof(option.translate.ignoreTag) != 'undefined' && option.translate.ignoreTag.length > 0){ - var tags = option.translate.ignoreTag.split(','); - for(var ti = 0; ti < tags.length; ti++){ - var tagName = tags[ti].trim(); - if(tagName.length > 0){ - if(translate.ignore.tag.indexOf(tagName.toLowerCase()) > -1){ - //已经有了,忽略 - }else{ - //还没有,加入 - translate.ignore.tag.push(tagName); - } - } - } - } - translate.setUseVersion2(); //设置使用v2.x 版本 + window.pear.config.translate = option.translate; //暴露 pear.config.yml 中的 translate 配置出来,以便子页面在pear中获取配置信息。 - window.translate.temp_layuiExecuteInterval = setInterval(function(){ - if(document.readyState == 'complete'){ - //dom加载完成,进行启动 - clearInterval(window.translate.temp_layuiExecuteInterval);//停止 - console.log('window.translate.temp_layuiExecuteInterval stop'); - - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 - translate.execute(); - - //避免有遗漏,特别是表格的render渲染等,诡异的会复原 - setTimeout(translate.execute,1500); - } - }, 30); + /* + + 因为所有页面中都有 pear.js,但admin.js只有主页面中才有,但翻译能力是需要所有页面都具备的,故而放到pear.js 之中,老哥看是否合理,或怎么进行一下调整。 + + */ + } }; diff --git a/component/pear/pear.js b/component/pear/pear.js index c0b2e3d..dd6d060 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -46,16 +46,64 @@ layui.config({ fullscreen:"fullscreen", //全屏组件 popover:"popover/popover", //汽泡组件 translate:"translate" //多语言翻译组件 -}).use(['layer', 'theme'], function () { +}).use(['layer', 'theme', 'translate'], function () { layui.theme.changeTheme(window, false); - if(typeof(template_temp_pearInterval) == 'undefined'){ - var template_temp_pearInterval = setInterval(function(){ - if(typeof(translate) != 'undefined' && translate.listener.isStart){ //admin.js初始化完毕,translate已初始化成功 - clearInterval(template_temp_pearInterval);//停止 - console.log('template_temp_pearInterval stop'); + /***** translate.js 翻译 ******/ + var template_temp_pearInterval = setInterval(function(){ + if(typeof(parent.window.pear) == 'undefined' || typeof(parent.window.pear.config) == 'undefined' || typeof(parent.window.pear.config.translate) == 'undefined'){ + //配置还没加载出来,等待加载 + return; + } + //admin.js 初始化完毕,translate配置已获取成功 + clearInterval(template_temp_pearInterval);//停止 + console.log('template_temp_pearInterval stop'); + + /***** 配置项赋予 *****/ + if(typeof(window.pear.config.translate.autoDiscriminateLocalLanguage) != 'undefined' && (window.pear.config.translate.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ + translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 + } + if(typeof(window.pear.config.translate.currentLanguage) != 'undefined' && window.pear.config.translate.currentLanguage.length > 0){ + translate.language.setLocal(window.pear.config.translate.currentLanguage); + } + if(typeof(window.pear.config.translate.ignoreClass) != 'undefined' && window.pear.config.translate.ignoreClass.length > 0){ + var classs = window.pear.config.translate.ignoreClass.split(','); + for(var ci = 0; ci < classs.length; ci++){ + var className = classs[ci].trim(); + if(className.length > 0){ + if(translate.ignore.class.indexOf(className.toLowerCase()) > -1){ + //已经有了,忽略 + }else{ + //还没有,加入 + translate.ignore.class.push(className); + } + } + } + } + if(typeof(window.pear.config.translate.ignoreTag) != 'undefined' && window.pear.config.translate.ignoreTag.length > 0){ + var tags = window.pear.config.translate.ignoreTag.split(','); + for(var ti = 0; ti < tags.length; ti++){ + var tagName = tags[ti].trim(); + if(tagName.length > 0){ + if(translate.ignore.tag.indexOf(tagName.toLowerCase()) > -1){ + //已经有了,忽略 + }else{ + //还没有,加入 + translate.ignore.tag.push(tagName); + } + } + } + } + //设置使用v2.x 版本 + translate.setUseVersion2(); + + //页面加载完毕后执行翻译 + window.temp_pearExecuteInterval = setInterval(function(){ + if(document.readyState == 'complete'){ + //dom加载完成,进行启动 + clearInterval(window.translate.temp_pearExecuteInterval);//停止 + console.log('window.translate.temp_pearExecuteInterval stop'); - translate.selectLanguageTag.show = false; //内页中不显示 select 语言选择,因为在顶部已经有了 translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 translate.execute(); @@ -63,6 +111,8 @@ layui.config({ setTimeout(translate.execute,1500); } }, 30); - } + + }, 30); + console.log('template_temp_pearInterval create') }); \ No newline at end of file -- Gitee From 901c6803b37330d27f26b4274719dc092e32e569 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 21:24:12 +0800 Subject: [PATCH 33/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 2 +- component/pear/pear.js | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index ddbb2ad..2dfc8bd 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -421,7 +421,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm if(typeof(option.translate) == 'undefined'){ return; } - window.pear.config.translate = option.translate; //暴露 pear.config.yml 中的 translate 配置出来,以便子页面在pear中获取配置信息。 + window.pearTranslateConfig = option.translate; //暴露 pear.config.yml 中的 translate 配置出来,以便子页面在pear中获取配置信息。 /* diff --git a/component/pear/pear.js b/component/pear/pear.js index dd6d060..7189a75 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -51,23 +51,25 @@ layui.config({ /***** translate.js 翻译 ******/ var template_temp_pearInterval = setInterval(function(){ - if(typeof(parent.window.pear) == 'undefined' || typeof(parent.window.pear.config) == 'undefined' || typeof(parent.window.pear.config.translate) == 'undefined'){ + if(typeof(parent.window.pearTranslateConfig) == 'undefined'){ //配置还没加载出来,等待加载 return; } //admin.js 初始化完毕,translate配置已获取成功 + var translateConfig = parent.window.pearTranslateConfig; + clearInterval(template_temp_pearInterval);//停止 console.log('template_temp_pearInterval stop'); /***** 配置项赋予 *****/ - if(typeof(window.pear.config.translate.autoDiscriminateLocalLanguage) != 'undefined' && (window.pear.config.translate.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ + if(typeof(translateConfig.autoDiscriminateLocalLanguage) != 'undefined' && (translateConfig.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 } - if(typeof(window.pear.config.translate.currentLanguage) != 'undefined' && window.pear.config.translate.currentLanguage.length > 0){ - translate.language.setLocal(window.pear.config.translate.currentLanguage); + if(typeof(translateConfig.currentLanguage) != 'undefined' && translateConfig.currentLanguage.length > 0){ + translate.language.setLocal(translateConfig.currentLanguage); } - if(typeof(window.pear.config.translate.ignoreClass) != 'undefined' && window.pear.config.translate.ignoreClass.length > 0){ - var classs = window.pear.config.translate.ignoreClass.split(','); + if(typeof(translateConfig.ignoreClass) != 'undefined' && translateConfig.ignoreClass.length > 0){ + var classs = translateConfig.ignoreClass.split(','); for(var ci = 0; ci < classs.length; ci++){ var className = classs[ci].trim(); if(className.length > 0){ @@ -80,8 +82,8 @@ layui.config({ } } } - if(typeof(window.pear.config.translate.ignoreTag) != 'undefined' && window.pear.config.translate.ignoreTag.length > 0){ - var tags = window.pear.config.translate.ignoreTag.split(','); + if(typeof(translateConfig.ignoreTag) != 'undefined' && translateConfig.ignoreTag.length > 0){ + var tags = translateConfig.ignoreTag.split(','); for(var ti = 0; ti < tags.length; ti++){ var tagName = tags[ti].trim(); if(tagName.length > 0){ -- Gitee From ae3217f9baa665b7c43c11575aa6ccd0035cd04d Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 21:31:31 +0800 Subject: [PATCH 34/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index 7189a75..ce88ff2 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -62,7 +62,7 @@ layui.config({ console.log('template_temp_pearInterval stop'); /***** 配置项赋予 *****/ - if(typeof(translateConfig.autoDiscriminateLocalLanguage) != 'undefined' && (translateConfig.autoDiscriminateLocalLanguage == true || option.translate.autoDiscriminateLocalLanguage == 'true' )){ + if(typeof(translateConfig.autoDiscriminateLocalLanguage) != 'undefined' && (translateConfig.autoDiscriminateLocalLanguage == true || translateConfig.autoDiscriminateLocalLanguage == 'true' )){ translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换 } if(typeof(translateConfig.currentLanguage) != 'undefined' && translateConfig.currentLanguage.length > 0){ -- Gitee From 5e4455be55ea1bff1410c9e4ed6c5c893016a948 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Tue, 10 Jan 2023 21:40:59 +0800 Subject: [PATCH 35/37] =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index ce88ff2..3eb66ba 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -98,21 +98,20 @@ layui.config({ } //设置使用v2.x 版本 translate.setUseVersion2(); + //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + translate.listener.start(); //页面加载完毕后执行翻译 - window.temp_pearExecuteInterval = setInterval(function(){ - if(document.readyState == 'complete'){ - //dom加载完成,进行启动 - clearInterval(window.translate.temp_pearExecuteInterval);//停止 - console.log('window.translate.temp_pearExecuteInterval stop'); - - translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 + if(document.readyState == 'complete'){ + translate.execute(); + }else{ + window.onload = function(){ translate.execute(); - - //避免有遗漏,特别是表格的render渲染等,诡异的会复原 - setTimeout(translate.execute,1500); } - }, 30); + } + //避免有遗漏,特别是表格的render渲染等,诡异的会复原 + setTimeout(translate.execute,1500); + console.log('translate execute') }, 30); console.log('template_temp_pearInterval create') -- Gitee From 8db57a60438056fc2ba7897c4e8ea57944a8ea63 Mon Sep 17 00:00:00 2001 From: xnx3 Date: Wed, 11 Jan 2023 09:23:18 +0800 Subject: [PATCH 36/37] =?UTF-8?q?=E7=B2=BE=E7=AE=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/module/admin.js | 2 -- config/pear.config.yml | 1 - 2 files changed, 3 deletions(-) diff --git a/component/pear/module/admin.js b/component/pear/module/admin.js index 2dfc8bd..7724dea 100644 --- a/component/pear/module/admin.js +++ b/component/pear/module/admin.js @@ -416,8 +416,6 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm } }, this.translate = function(option){ - //console.log('translate ....') - //console.log(option); if(typeof(option.translate) == 'undefined'){ return; } diff --git a/config/pear.config.yml b/config/pear.config.yml index 9ee5147..ebfa809 100644 --- a/config/pear.config.yml +++ b/config/pear.config.yml @@ -85,7 +85,6 @@ translate: ## 当前语种,有: chinese_simplified 简体中文 、chinese_traditional 繁体中文、english 英语、korean 韩语 ,默认是 chinese_simplified 简体中文 localLanguage: "chinese_simplified" ## 设置用户第一次用时,自动识别其所在国家的语种进行切换,true:使用。 默认为false不使用。 - ## 这个开启yml格式化报错 message: "Unable to parse." 所以注释掉了 autoDiscriminateLocalLanguage: false ## 翻译时忽略指定的 class name,多个 class name 之间用逗号分割 ignoreClass: "ignore,test1,layui-logo" -- Gitee From 653c5b9ca3a2363b4a5fa1055ddf175d9a8cfb7c Mon Sep 17 00:00:00 2001 From: xnx3 Date: Wed, 11 Jan 2023 09:39:11 +0800 Subject: [PATCH 37/37] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/pear/pear.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/component/pear/pear.js b/component/pear/pear.js index 3eb66ba..c7e9fee 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -57,9 +57,8 @@ layui.config({ } //admin.js 初始化完毕,translate配置已获取成功 var translateConfig = parent.window.pearTranslateConfig; - - clearInterval(template_temp_pearInterval);//停止 - console.log('template_temp_pearInterval stop'); + //停止 + clearInterval(template_temp_pearInterval); /***** 配置项赋予 *****/ if(typeof(translateConfig.autoDiscriminateLocalLanguage) != 'undefined' && (translateConfig.autoDiscriminateLocalLanguage == true || translateConfig.autoDiscriminateLocalLanguage == 'true' )){ @@ -96,11 +95,8 @@ layui.config({ } } } - //设置使用v2.x 版本 - translate.setUseVersion2(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化部分,是指当 translate.execute(); 已经完全执行完毕之后,如果页面再有变化的部分,才会对其进行翻译。 translate.listener.start(); - //页面加载完毕后执行翻译 if(document.readyState == 'complete'){ translate.execute(); @@ -111,9 +107,8 @@ layui.config({ } //避免有遗漏,特别是表格的render渲染等,诡异的会复原 setTimeout(translate.execute,1500); - console.log('translate execute') }, 30); - console.log('template_temp_pearInterval create') + /***** translate.js 翻译 结束 ******/ }); \ No newline at end of file -- Gitee