网页翻译-扩展版本

给非中文的网页右下角添加一个google翻译图标对网页进行翻译,该版本主要适配手机浏览器: X浏览器、via浏览器等不支持油猴扩展的浏览器

  1. // ==UserScript==
  2. // @name 网页翻译-扩展版本
  3. // @author Kaiter-Plus
  4. // @namespace https://gitee.com/Kaiter-Plus/TampermonkeyScript/tree/master/Translate/Translate_ext.js
  5. // @description 给非中文的网页右下角添加一个google翻译图标对网页进行翻译,该版本主要适配手机浏览器: X浏览器、via浏览器等不支持油猴扩展的浏览器
  6. // @version 1.49
  7. // @license BSD-3-Clause
  8. // @icon https://www.google.cn/favicon.ico
  9. // @include *://*
  10. // @run-at document-end
  11. // @noframes
  12. // @note 2021/03/18 网页整页翻译功能,稍微调整了布局
  13. // @note 2021/03/20 添加了排除网站的功能
  14. // @note 2021/12/14 直接使用 https 获取谷歌翻译接口(防止有可能火狐浏览器无法用于翻译本地文件的bug)@古海沉舟
  15. // @note 2022/10/05 由于谷歌关闭了国内的翻译接口,所以只能使用国际版的接口,现在使用脚本必须配合梯子
  16. // ==/UserScript==
  17.  
  18. ;(function () {
  19. 'use strict'
  20. // 此处使用正则表达式排除不用进行翻译的网站
  21. const noTranslateDomain = [
  22. /^([0-9]+\.){3}[0-9]+/,
  23. /.*duyaoss\.com/,
  24. /.*lanzous\.com/,
  25. /.*w3school.*cn/,
  26. /.*iqiyi\.com/,
  27. /.*baidu.*/,
  28. /.*cnblogs\.com/,
  29. /.*csdn\.net/,
  30. /.*zhku\.edu\.cn/,
  31. /.*zhihuishu\.com/,
  32. /.*aliyuncs\.com/,
  33. /.*chaoxing\.com/,
  34. /.*youku\.com/,
  35. /.*examcoo\.com/,
  36. /.*mooc\.com/,
  37. /.*bilibili\.com/,
  38. /.*qq\.com/,
  39. /.*yy\.com/,
  40. /.*huya\.com/,
  41. /localhost/,
  42. /.*acfun\.cn/
  43. ]
  44. // 获取 head
  45. const head = document.head
  46. // 获取body
  47. const body = document.body
  48. // 获取当前页面的语言
  49. const lang = document.documentElement.lang.toLowerCase().substr(0, 2)
  50. // 获取网页使用的主要语言
  51. const mainLang = document.characterSet.toLowerCase().substr(0, 2)
  52. // 设置是否排除网站的标识
  53. let noTranslateDomainflag = false
  54. // 排除一些网站的翻译
  55. noTranslateDomain.every(reg => {
  56. if (reg.test(document.domain)) {
  57. noTranslateDomainflag = true
  58. return false
  59. } else {
  60. return true
  61. }
  62. })
  63.  
  64. // 判断是不是中文,如果是则直接return,否则执行
  65. if (lang === 'zh' || mainLang === 'gb' || noTranslateDomainflag) {
  66. return
  67. } else {
  68. // 创建网页元素方法
  69. function createElement(html, nodeText, attr, parent) {
  70. const element = document.createElement(nodeText)
  71. if (attr) {
  72. element[attr] = html
  73. } else {
  74. element.innerHTML = html
  75. }
  76. parent.appendChild(element)
  77. }
  78.  
  79. // 自定义样式,隐藏顶部栏
  80. createElement(
  81. `
  82. html,body{
  83. top: 0!important;
  84. }
  85. #google_translate_element {
  86. position: fixed;
  87. bottom: 60px;
  88. height: 21px;
  89. border-radius: 11px;
  90. left: 0px;
  91. transform: translateX(-75%);
  92. z-index: 10000000;
  93. overflow: hidden;
  94. box-shadow: 1px 1px 3px 0 #888;
  95. opacity: .5;
  96. transition: all .3s;
  97. }
  98. #google_translate_element .goog-te-gadget-simple {
  99. border: 0;
  100. }
  101. #google_translate_element .goog-te-gadget-simple span {
  102. margin-right: 0;
  103. border-radius: 11px;
  104. }
  105. #lb {
  106. display: inline-block;
  107. }
  108. .recoverPage {
  109. width: 4em;
  110. background-color: #fff;
  111. position: fixed;
  112. z-index: 10000000;
  113. bottom: 60px;
  114. right: 0px;
  115. transform: translateX(78%);
  116. user-select: none;
  117. text-align: center;
  118. font-size: small;
  119. line-height: 2em;
  120. border-radius: 1em;
  121. box-shadow: 1px 1px 3px 0 #888;
  122. opacity: .5;
  123. transition: all .3s;
  124. }
  125. #google_translate_element:hover, .recoverPage:hover {
  126. opacity: 1;
  127. transform: translateX(0);
  128. }
  129. .recoverPage:active {
  130. box-shadow: 1px 1px 3px 0 #888 inset;
  131. }
  132. #google_translate_element .goog-te-gadget-simple {
  133. width: 100%;
  134. }
  135. /* 隐藏移动端顶部栏 */
  136. [id=":1.container"].skiptranslate {
  137. display: none;
  138. }
  139. /* 隐藏 PC 端顶部栏 */
  140. [id=":2.container"].skiptranslate {
  141. display: none;
  142. }
  143. @media handheld, only screen and (max-width: 768px) {
  144. #google_translate_element {
  145. width: 104px;
  146. }
  147. #google_translate_element .goog-te-gadget>div:first-child {
  148. margin: 2px;
  149. }
  150. #google_translate_element .goog-te-combo {
  151. margin: 0;
  152. padding-top: 2px;
  153. border: none;
  154. }
  155. #goog-gt- {
  156. visibility: hidden!important;
  157. display: none!important;
  158. }
  159. .goog-text-highlight {
  160. background-color: inherit!important;
  161. box-shadow: 0 0 0 0 transparent!important;
  162. }
  163. .recoverPage {
  164. width: 2.8em;
  165. line-height: 2.8em;
  166. border-radius: 50%;
  167. opacity: .3;
  168. transform: translateX(0);
  169. }
  170. .recoverPage:hover {
  171. opacity: .3;
  172. }
  173. }
  174. `,
  175. 'style',
  176. '',
  177. head
  178. )
  179.  
  180. // 创建容器
  181. createElement('google_translate_element', 'div', 'id', body)
  182.  
  183. // 初始化
  184. createElement(
  185. `function googleTranslateElementInit() {
  186. let google_translate_element = document.getElementById('google_translate_element')
  187. let timer = setInterval(function () {
  188. google_translate_element = document.getElementById('google_translate_element')
  189. if (google_translate_element) {
  190. clearInterval(timer)
  191. new google.translate.TranslateElement(
  192. {
  193. pageLanguage: 'auto',
  194. //包括的语言,中文简体,中文繁体,英语,日语,俄语
  195. includedLanguages: 'zh-CN,zh-TW,en,ja,ru',
  196. layout: /mobile/i.test(navigator.userAgent) ? 0 : 2,
  197. },
  198. 'google_translate_element'
  199. )
  200. // 清除图片的请求,加快访问速度
  201. let img = [].slice.call(document.querySelectorAll('#goog-gt- img,#google_translate_element img'));
  202. img.forEach(function(v) {
  203. const a = v
  204. a.src = ''
  205. let b = a.outerHTML.replace(/<img(.*?)>/, () => {
  206. return '<span id="lb"' + RegExp.$1 +'></span>'
  207. })
  208. const c = document.createElement('div')
  209. c.innerHTML = b
  210. a.parentNode.insertBefore(c.children[0], a.parentNode.children[0])
  211. a.remove()
  212. });
  213. const recoverPage = document.createElement('div')
  214. recoverPage.setAttribute('class', 'notranslate recoverPage')
  215. recoverPage.innerText = '原'
  216. document.body.appendChild(recoverPage)
  217. // 点击恢复原网页
  218. recoverPage.onclick = () => {
  219. const phoneRecoverIframe = document.getElementById(':1.container') // 移动端
  220. const PCRecoverIframe = document.getElementById(':2.container') // PC端
  221. if (phoneRecoverIframe) {
  222. const recoverDocument = phoneRecoverIframe.contentWindow.document
  223. recoverDocument.getElementById(':1.restore').click()
  224. } else if (PCRecoverIframe) {
  225. const recoverDocument = PCRecoverIframe.contentWindow.document
  226. recoverDocument.getElementById(':2.restore').click()
  227. }
  228. }
  229. }
  230. }, 300)
  231. }`,
  232. 'script',
  233. '',
  234. head
  235. )
  236.  
  237. // 导入翻译接口
  238. createElement(
  239. 'https://translate.google.com/translate_a/element.js?&cb=googleTranslateElementInit',
  240. 'script',
  241. 'src',
  242. head
  243. )
  244.  
  245. // 排除一些代码的翻译
  246. const noTranslateArray = ['.bbCodeCode', 'tt', 'pre[translate="no"]']
  247. noTranslateArray.forEach(selectorName => {
  248. ;[...document.querySelectorAll(selectorName)].forEach(node => {
  249. if (node.className.indexOf('notranslate') === -1) {
  250. node.classList.add('notranslate')
  251. }
  252. })
  253. })
  254. }
  255. })()