AC-有道取词+翻译

一个可以在浏览器中自由使用的屏幕取词脚本-alt+鼠标翻译,或者选中按Q翻译

目前为 2018-05-16 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name AC-有道取词+翻译
  3. // @description 一个可以在浏览器中自由使用的屏幕取词脚本-alt+鼠标翻译,或者选中按Q翻译
  4. // @version 1.4
  5. // @namespace youdao
  6. // @author AC -modified from :Liu Yuyang(sa@linuxer.me)
  7. // @include *
  8. // @icon https://coding.net/u/zb227/p/zbImg/git/raw/master/img0/icon.jpg
  9. // @run-at document-end
  10. // @note V1.4 2018-05-16 修复上一次更新导致的bug,同时修复多种语言翻译,结果却翻译成了英文的bug
  11. // @note V1.3 2018-05-16 修复word词组的时候翻译出错的问题
  12. // @note V1.2 2018-05-16 修复没有添加connect的错误问题
  13. // @note V1.1 2018-05-12 有道自己不更新~~HTTPS证书过期,现在使用搜狗翻译吧,老司机们说搜狗翻译还是很有优势的,至于百度翻译,再说吧
  14. // @note V1.0 2017-11-22 修复firefox57的翻译的BUG
  15. // @note V0.9 2017-11-15 修复了一大堆,优化了下界面的展示问题
  16. // @note V0.8 2017-2-21 修正了由于z-index过低导致的淘宝页面翻译过于底层而看不见
  17. // @note V0.7 2016-9-29 修正了部分格式错误,换行的时候稍微好了点
  18. // @note V0.6 2016-1-12 终于修正了,之前只改了句子翻译中的文字颜色,才发现单词翻译后的颜色简直看不清。。。
  19. // @note V0.5 2016-1-9 修改默认背景色
  20. // @note V0.4 2016-1-8 修正chrome的支持
  21. // @note V0.3 2016-1-8 修改窗体默认大小,尽可能的显示回车功能,避免了以前的全部显示在同一行--依旧有bug
  22. // @note V0.2 2015-11-26 修改部分地方适合自己使用,选中文字,按下Q翻译,或者alt+鼠标选中,自动翻译
  23. // @grant GM_xmlhttpRequest
  24. // @connect fanyi.youdao.com
  25. // @connect fanyi.sogou.com
  26. // ==/UserScript==
  27.  
  28. var curX;
  29. var curY;
  30. var timeout;
  31. var transResult;
  32.  
  33. document.body.addEventListener("mousemove", function(e){curX = e.clientX; curY = e.clientY;}, false);
  34. document.body.addEventListener("keypress", callbackWrapper, false);
  35. document.body.addEventListener("mouseup", callbackWrapper, false);
  36. document.body.addEventListener("dblclick", callbackWrapper, false);
  37.  
  38. function callbackWrapper(e) {
  39. if(e.type === 'dblclick' && isInACTransPop()){
  40. // console.log("双击操作:复制目标文本");
  41. // console.log(transResult);
  42. return;
  43. }
  44. if(e.charCode == 113 || e.type == "mouseup"){ //Q
  45. // remove previous .ACyoudaoPopup if exists
  46. var previous = document.querySelector(".ACyoudaoPopup");
  47. if(previous && isInACTransPop()){
  48. document.body.removeChild(previous);
  49. transResult = "";
  50. }
  51. // quick fix. with ctrl key held
  52. if (e.type == "mouseup" && !e.altKey) {
  53. return;
  54. }
  55. clearTimeout(timeout);
  56. timeout = setTimeout(function(){
  57. translate();
  58. }, 120);
  59. }
  60. }
  61. function isInACTransPop(){
  62. var checkNode = document.getSelection().anchorNode.parentNode;
  63. return checkNode && (""+checkNode.className).indexOf("ACyoudao") < 0;
  64. }
  65. function translate() {
  66. var selectObj = document.getSelection();
  67. if (selectObj.anchorNode.nodeType == 3) {
  68. var word = selectObj.toString();
  69. if (word == "") {
  70. return;
  71. }
  72. word = word.replace(new RegExp('(\r\n)+', 'g'), 'QWER');// 特殊标记便于替换
  73. var ts = new Date().getTime();
  74. var mx = curX;
  75. var my = curY;
  76. translate(word, ts);
  77. }
  78.  
  79. function popup(mx, my, result) {
  80. var youdaoWindow = document.createElement('div');
  81. youdaoWindow.classList.toggle("ACyoudaoPopup");
  82. // parse
  83. var dictJSON = JSON.parse(result);
  84. console.log(dictJSON);
  85. var query = dictJSON['translate']['text'];
  86. // var errorCode = dictJSON['errorCode'];
  87. console.log(query);
  88. if (dictJSON['dictionary']) {
  89. word();
  90. } else {
  91. sentence();
  92. }
  93. // main window
  94. // first insert into dom then there is offsetHeight!IMPORTANT!
  95.  
  96. document.body.appendChild(youdaoWindow);
  97. youdaoWindow.style.color = "#000000";
  98. youdaoWindow.style.textAlign = "left";
  99. youdaoWindow.style.display = "block";
  100. youdaoWindow.style.position = "fixed";
  101. youdaoWindow.style.background = "#EDF6FF";
  102. youdaoWindow.style.borderRadius = "3px";
  103. youdaoWindow.style.boxShadow = "0 0 5px 0";
  104. youdaoWindow.style.opacity = "1";
  105. youdaoWindow.style.minWidth = "300px";
  106. youdaoWindow.style.maxWidth = "550px";
  107. youdaoWindow.style.wordWrap = "break-word";
  108. youdaoWindow.style.fontSize = "15px";
  109. youdaoWindow.style.left = mx + 10 + "px";
  110. if (mx + 200 + 30 >= window.innerWidth) {
  111. youdaoWindow.style.left = parseInt(youdaoWindow.style.left) - 200 + "px";
  112. }
  113. //alert(window.innerHeight);
  114. if (my + youdaoWindow.offsetHeight + 30 >= window.innerHeight) {
  115. youdaoWindow.style.bottom = "20px";
  116. } else {
  117. youdaoWindow.style.top = my + "px";
  118. }
  119. youdaoWindow.style.padding = "3px";
  120. youdaoWindow.style.zIndex = '9999999999';
  121.  
  122. function word() {
  123. function play(word) {
  124. //console.log("[DEBUG] PLAYOUND")
  125. function playSound(buffer) {
  126. var source = context.createBufferSource();
  127. source.buffer = buffer;
  128. source.connect(context.destination);
  129. source.start(0);
  130. }
  131. var context = new AudioContext();
  132. var soundUrl = 'https://dict.youdao.com/dictvoice?type=2&audio='+encodeURIComponent(word);
  133. var p = new Promise(function(resolve, reject) {
  134. var ret = GM_xmlhttpRequest({
  135. method: "GET",
  136. url: soundUrl,
  137. responseType: 'arraybuffer',
  138. onload: function(res) {
  139. try {
  140. context.decodeAudioData(res.response, function(buffer) {
  141. resolve(buffer);
  142. });
  143. } catch(e) {
  144. reject(e);
  145. }
  146. }
  147. });
  148. });
  149. p.then(playSound, function(e) {
  150. console.log(e);
  151. });
  152. }
  153. var basic = dictJSON['basic'] != null ? dictJSON['basic']:dictJSON['dictionary']['content'][0];
  154. var header = document.createElement('div');
  155. header.className = "ACyoudaoPopupDIV";
  156. // header
  157. var span = document.createElement('span');
  158. span.className = "ACyoudaoPopupSpan";
  159. span.innerHTML = query;
  160. header.appendChild(span);
  161. // phonetic if there is
  162. var phonetic = basic['phonetic'];
  163. var transWord;
  164. try{
  165. transWord = basic['category'][0]['sense'][0]['description'];
  166. }catch (e) {
  167. transWord = basic['usual'][0]['values'];
  168. }
  169. if (phonetic) {
  170. var phoneticNode = document.createElement('span');
  171. phoneticNode.innerHTML = '[' + phonetic + ']:'+transWord;
  172. phoneticNode.style.cursor = "pointer";
  173. header.appendChild(phoneticNode);
  174. var playLogo = document.createElement('span');
  175. header.appendChild(phoneticNode);
  176. phoneticNode.addEventListener('mouseup', function(e){
  177. if (e.target === phoneticNode) {
  178. }
  179. e.stopPropagation();
  180. play(query);
  181. }, false);
  182. }
  183. header.style.lineHeight = "1.8";
  184. header.style.color = "black";
  185. header.style.margin = "0";
  186. header.style.padding = "0";
  187. span.style.fontSize = "15px";
  188. span.style.color = "black";
  189.  
  190. youdaoWindow.appendChild(header);
  191. var hr = document.createElement('hr');
  192. hr.className = "ACyoudaoPopupHR";
  193. hr.style.margin = "0";
  194. hr.style.padding = "0";
  195. hr.style.height = "1px";
  196. hr.style.borderTop = "dashed 1px black";
  197. youdaoWindow.appendChild(hr);
  198. var ul = document.createElement('ul');
  199. ul.className = "ACyoudaoPopupUL";
  200. // ul style
  201. ul.style.margin = "0";
  202. ul.style.padding = "0";
  203. var mapNode;
  204. try{
  205. mapNode = basic['category'][0]['sense'][0]['example'];
  206. }catch (e) {
  207. mapNode = basic['content'][0]['item']['core'][0]['branch'];
  208. }
  209. mapNode.map(function(trans) {
  210. var li = document.createElement('li');
  211. li.className = "ACyoudaoPopupLi";
  212. li.style.listStyle = "none";
  213. li.style.margin = "0";
  214. li.style.padding = "0";
  215. li.style.background = "none";
  216. li.style.color = "#008CD8";
  217. var innerHTML = "";
  218. if(trans['source'] != undefined){
  219. innerHTML = trans['source']+":"+trans['target']
  220. }else{
  221. innerHTML = trans['en']+":"+trans['zh']
  222. }
  223. li.appendChild(document.createTextNode(innerHTML));
  224. ul.appendChild(li);
  225. });
  226. youdaoWindow.appendChild(ul);
  227. }
  228.  
  229. function sentence() {
  230. var ul = document.createElement('ul');
  231. ul.className = "ACyoudaoPopupUL";
  232. // ul style
  233. ul.style.margin = "0";
  234. ul.style.padding = "0";
  235. var trans = dictJSON['translate']['dit'];
  236. var oriText = dictJSON['translate']['text'];
  237. var li = document.createElement('li');
  238. li.style.listStyle = "none";
  239. li.style.margin = "0";
  240. li.style.padding = "0";
  241. li.style.background = "none";
  242. li.style.color = "#008CD8";
  243. li.className = "ACyoudaoPopupLi";
  244. trans = trans.replaceAll('QWER', '\n').replaceAll(",", ", ");
  245. console.log(trans);
  246. if(oriText.length < 70 && !/\n/.test(oriText)) // 如果长度比较短,并且没有回车符
  247. trans = oriText+"\n"+trans;
  248. transResult += trans;
  249. var reg = new RegExp("\n","gm");
  250. while(reg.exec(trans) != null){// 如果找不到回车了,那么最后重复一次新建<p>
  251. //找到一个回车,那么添加一个新的<p>,内容为:trans.sub(0, ?); trans = trans.sub(?);
  252. var newNode = document.createElement("li");
  253. newNode.className = "ACyoudaoPopupLi";
  254. newNode.style.listStyle = "none";
  255. newNode.style.margin = "0";
  256. newNode.style.padding = "0";
  257. newNode.style.background = "none";
  258. newNode.style.color = "#008CD8";
  259. newNode.style.fontSize = "15px";
  260. newNode.innerHTML = trans.substring(0, reg.lastIndex-1);
  261. li.appendChild(newNode);
  262. trans = trans.substring(reg.lastIndex);
  263. }
  264. var newNode = document.createElement("div");
  265. newNode.className = "ACyoudaoPopupDiv";
  266. newNode.innerHTML = trans;
  267. newNode.style = "line-height: 1.8;color:#008CD8 !important;font-size:15px !important;margin-left:10px;margin-right:10px;";
  268. li.appendChild(newNode);
  269. ul.appendChild(li);
  270. youdaoWindow.appendChild(ul);
  271. }
  272. }
  273.  
  274. function translate(word, ts) {
  275. var ToLANGUAGE = "en";
  276. if(!/[\u4E00-\u9FA5]/g.test(word)) // 如果没有中文,那么说明是外文--> to=中文
  277. ToLANGUAGE = "zh-CHS";
  278. word = encodeURIComponent(word);
  279. // var reqUrl = 'https://fanyi.youdao.com/openapi.do?type=data&doctype=json&version=1.1&relatedUrl=http%3A%2F%2Ffanyi.youdao.com%2F%23&keyfrom=fanyiweb&key=null&translate=on&q='+word+'&ts='+ts;
  280. var reqUrl = 'https://fanyi.sogou.com/reventondc/translate?from=auto&to='+ToLANGUAGE+'&client=pc&fr=browser_pc&useDetect=on&useDetectResult=on&text='+word+'&ts='+ts;
  281. console.log("request url: ", reqUrl);
  282. var ret = GM_xmlhttpRequest({
  283. method: "GET",
  284. url: reqUrl,
  285. headers: {"Accept": "application/json"}, // can be omitted...
  286. onload: function(res) {
  287. var retContent = res.response;
  288. //console.log(retContent)
  289. popup(mx, my, retContent);
  290. },
  291. onerror: function(res) {
  292. console.log("error");
  293. }
  294. });
  295. }
  296. String.prototype.replaceAll = function(s1,s2){
  297. return this.replace(new RegExp(s1,"gm"),s2);
  298. };
  299. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址