// ==UserScript== // @name 网页翻译-扩展版本 // @author Kaiter-Plus // @namespace https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/Translate/Translate_ext.js // @description 给非中文的网页右下角添加一个google翻译图标对网页进行翻译,该版本主要适配手机浏览器: X浏览器、via浏览器等不支持油猴扩展的浏览器 // @version 1.49 // @license BSD-3-Clause // @icon https://www.google.cn/favicon.ico // @include *://* // @run-at document-end // @noframes // @note 2021/03/18 网页整页翻译功能,稍微调整了布局 // @note 2021/03/20 添加了排除网站的功能 // @note 2021/12/14 直接使用 https 获取谷歌翻译接口(防止有可能火狐浏览器无法用于翻译本地文件的bug)@古海沉舟 // @note 2022/10/05 由于谷歌关闭了国内的翻译接口,所以只能使用国际版的接口,现在使用脚本必须配合梯子 // @downloadURL https://update.greasyfork.icu/scripts/423469/%E7%BD%91%E9%A1%B5%E7%BF%BB%E8%AF%91-%E6%89%A9%E5%B1%95%E7%89%88%E6%9C%AC.user.js // @updateURL https://update.greasyfork.icu/scripts/423469/%E7%BD%91%E9%A1%B5%E7%BF%BB%E8%AF%91-%E6%89%A9%E5%B1%95%E7%89%88%E6%9C%AC.meta.js // ==/UserScript== ;(function () { 'use strict' // 此处使用正则表达式排除不用进行翻译的网站 const noTranslateDomain = [ /^([0-9]+\.){3}[0-9]+/, /.*duyaoss\.com/, /.*lanzous\.com/, /.*w3school.*cn/, /.*iqiyi\.com/, /.*baidu.*/, /.*cnblogs\.com/, /.*csdn\.net/, /.*zhku\.edu\.cn/, /.*zhihuishu\.com/, /.*aliyuncs\.com/, /.*chaoxing\.com/, /.*youku\.com/, /.*examcoo\.com/, /.*mooc\.com/, /.*bilibili\.com/, /.*qq\.com/, /.*yy\.com/, /.*huya\.com/, /localhost/, /.*acfun\.cn/ ] // 获取 head const head = document.head // 获取body const body = document.body // 获取当前页面的语言 const lang = document.documentElement.lang.toLowerCase().substr(0, 2) // 获取网页使用的主要语言 const mainLang = document.characterSet.toLowerCase().substr(0, 2) // 设置是否排除网站的标识 let noTranslateDomainflag = false // 排除一些网站的翻译 noTranslateDomain.every(reg => { if (reg.test(document.domain)) { noTranslateDomainflag = true return false } else { return true } }) // 判断是不是中文,如果是则直接return,否则执行 if (lang === 'zh' || mainLang === 'gb' || noTranslateDomainflag) { return } else { // 创建网页元素方法 function createElement(html, nodeText, attr, parent) { const element = document.createElement(nodeText) if (attr) { element[attr] = html } else { element.innerHTML = html } parent.appendChild(element) } // 自定义样式,隐藏顶部栏 createElement( ` html,body{ top: 0!important; } #google_translate_element { position: fixed; bottom: 60px; height: 21px; border-radius: 11px; left: 0px; transform: translateX(-75%); z-index: 10000000; overflow: hidden; box-shadow: 1px 1px 3px 0 #888; opacity: .5; transition: all .3s; } #google_translate_element .goog-te-gadget-simple { border: 0; } #google_translate_element .goog-te-gadget-simple span { margin-right: 0; border-radius: 11px; } #lb { display: inline-block; } .recoverPage { width: 4em; background-color: #fff; position: fixed; z-index: 10000000; bottom: 60px; right: 0px; transform: translateX(78%); user-select: none; text-align: center; font-size: small; line-height: 2em; border-radius: 1em; box-shadow: 1px 1px 3px 0 #888; opacity: .5; transition: all .3s; } #google_translate_element:hover, .recoverPage:hover { opacity: 1; transform: translateX(0); } .recoverPage:active { box-shadow: 1px 1px 3px 0 #888 inset; } #google_translate_element .goog-te-gadget-simple { width: 100%; } /* 隐藏移动端顶部栏 */ [id=":1.container"].skiptranslate { display: none; } /* 隐藏 PC 端顶部栏 */ [id=":2.container"].skiptranslate { display: none; } @media handheld, only screen and (max-width: 768px) { #google_translate_element { width: 104px; } #google_translate_element .goog-te-gadget>div:first-child { margin: 2px; } #google_translate_element .goog-te-combo { margin: 0; padding-top: 2px; border: none; } #goog-gt- { visibility: hidden!important; display: none!important; } .goog-text-highlight { background-color: inherit!important; box-shadow: 0 0 0 0 transparent!important; } .recoverPage { width: 2.8em; line-height: 2.8em; border-radius: 50%; opacity: .3; transform: translateX(0); } .recoverPage:hover { opacity: .3; } } `, 'style', '', head ) // 创建容器 createElement('google_translate_element', 'div', 'id', body) // 初始化 createElement( `function googleTranslateElementInit() { let google_translate_element = document.getElementById('google_translate_element') let timer = setInterval(function () { google_translate_element = document.getElementById('google_translate_element') if (google_translate_element) { clearInterval(timer) new google.translate.TranslateElement( { pageLanguage: 'auto', //包括的语言,中文简体,中文繁体,英语,日语,俄语 includedLanguages: 'zh-CN,zh-TW,en,ja,ru', layout: /mobile/i.test(navigator.userAgent) ? 0 : 2, }, 'google_translate_element' ) // 清除图片的请求,加快访问速度 let img = [].slice.call(document.querySelectorAll('#goog-gt- img,#google_translate_element img')); img.forEach(function(v) { const a = v a.src = '' let b = a.outerHTML.replace(//, () => { return '' }) const c = document.createElement('div') c.innerHTML = b a.parentNode.insertBefore(c.children[0], a.parentNode.children[0]) a.remove() }); const recoverPage = document.createElement('div') recoverPage.setAttribute('class', 'notranslate recoverPage') recoverPage.innerText = '原' document.body.appendChild(recoverPage) // 点击恢复原网页 recoverPage.onclick = () => { const phoneRecoverIframe = document.getElementById(':1.container') // 移动端 const PCRecoverIframe = document.getElementById(':2.container') // PC端 if (phoneRecoverIframe) { const recoverDocument = phoneRecoverIframe.contentWindow.document recoverDocument.getElementById(':1.restore').click() } else if (PCRecoverIframe) { const recoverDocument = PCRecoverIframe.contentWindow.document recoverDocument.getElementById(':2.restore').click() } } } }, 300) }`, 'script', '', head ) // 导入翻译接口 createElement( 'https://translate.google.com/translate_a/element.js?&cb=googleTranslateElementInit', 'script', 'src', head ) // 排除一些代码的翻译 const noTranslateArray = ['.bbCodeCode', 'tt', 'pre[translate="no"]'] noTranslateArray.forEach(selectorName => { ;[...document.querySelectorAll(selectorName)].forEach(node => { if (node.className.indexOf('notranslate') === -1) { node.classList.add('notranslate') } }) }) } })()