// ==UserScript==
// @name 划词翻译
// @namespace http://tampermonkey.net/
// @version 0.1.180626
// @description 基于 translate.google.cn 的划词翻译,用鼠标选中纯英文内容即可。每次翻译的结果自动复制到剪贴板,用户可直接粘贴使用。
// @author laohoo
// @match http://*/*
// @match https://*/*
// @exclude http*://*.baidu.com/*
// @connect translate.google.cn
// @run-at document-idle
// @grant GM.xmlHttpRequest
// @grant GM.setClipboard
// ==/UserScript==
(function () {
'use strict';// @require https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js
function parseText(text) {
let doc = null;
try {
doc = document.implementation.createHTMLDocument("");
doc.documentElement.innerHTML = text;
return doc;
}
catch (e) {
// alert("parse error");
}
}
// a:你要翻译的内容
// uq:tkk的值
function vq(a, uq = tkk) {
if (null !== uq) {
var b = uq;
} else {
b = sq('T');
var c = sq('K');
b = [b(), c()];
b = (uq = window[b.join(c())] || "") || ""
}
var d = sq('t');
c = sq('k');
d = [d(), c()];
c = "&" + d.join("") + "=";
d = b.split(".");
b = Number(d[0]) || 0;
for (var e = [], f = 0, g = 0; g < a.length; g++) {
var l = a.charCodeAt(g);
128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 :
(55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ?
(l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
e[f++] = l >> 18 | 240,
e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
e[f++] = l >> 6 & 63 | 128),
e[f++] = l & 63 | 128)
}
a = b;
for (f = 0; f < e.length; f++)
a += e[f],
a = tq(a, "+-a^+6");
a = tq(a, "+-3^+b+-f");
a ^= Number(d[1]) || 0;
0 > a && (a = (a & 2147483647) + 2147483648);
a %= 1000000;
return c + (a.toString() + "." + (a ^ b))
};
/*--------------------------------------------------------------------------------
参数:a 为你要翻译的原文
其他外部函数:
--------------------------------------------------------------------------------*/
function sq(a) {
return function () {
return a
}
}
function tq(a, b) {
for (var c = 0; c < b.length - 2; c += 3) {
var d = b.charAt(c + 2);
d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d);
d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
}
return a
}
var gturl = "http://translate.google.cn/";
var tkk = null;
var tk = null;
GM.xmlHttpRequest({
method: "GET",
url: gturl,
onload: function (response) {
let magHtml = parseText(response.responseText);
var sc = magHtml.body.querySelector("#gt-c > script:nth-child(2)");
var ftstr = sc.innerText.match(/'\(\(function\(\){var(.*?)x27\+\(a\+b\)}\)\(\)\)'/g)[0];
var result = eval(ftstr);
console.log(result);
var nums = result.match(/-?\d+/g); //取出字符串中的所有数字部分
console.log(nums);
tkk = nums[2] + "." + (parseInt(nums[0]) + parseInt(nums[1]));
console.log(tkk);
},
});
var endx = 0, endy = 0, startx = 0, starty = 0;
var selectedText;
document.addEventListener("mousedown", function (event) {
if (event.button == 0) {
startx = event.clientX;
starty = event.clientY;
if (window.getSelection) {
window.getSelection().removeAllRanges();
} else if (document.selection) {
document.selection.empty();
}
var ctips = document.getElementById("ctips");
if (ctips) {
document.body.removeChild(ctips);
}
selectedText = "";
}
console.log("Mouse Left or Right", event.button);
});
console.log("Translate begin...");
document.addEventListener("mouseup", function (event) {
if (event.button == 0) {
selectedText = null;
var endx = event.clientX, endy = event.clientY;
var widthSelected = event.target.clientWidth;
console.log("widthSelected: ", widthSelected);
console.log(`x,y: ${startx},${starty}: ${endx},${endy} `);
var x = startx > endx ? endx : startx;
var y = starty > endy ? starty : endy;
y += document.documentElement.scrollTop || document.body.scrollTop;
console.log(`xy: ${x},${y}`);
var start = 0, end = 0;
if (window.getSelection) {
selectedText = document.getSelection().toString();
start = window.getSelection().anchorOffset;
end = window.getSelection().focusOffset;
} else if (document.selection) {
selectedText = document.selection.createRange().text;
}
console.log(start, end);
console.log("English: ", (/[\x00-\xff]+$/g.test(selectedText)));
if (selectedText.trim()) {
if ((/[\x00-\xff]+$/g.test(selectedText))) {
// if(/[\x00-\xff]+/g.test(selectedText)){}
console.log(selectedText);
// 匹配所有回车符
var reg = new RegExp("\r", "g");
// 将匹配的内容替换为 ". "
//selectedText =selectedText.replace(/.?(\r\n\f\t\v)+/g,". ");
selectedText = selectedText.replace(reg, "");
//selectedText = encodeURIComponent(selectedText)
if (selectedText.length > 5000) {
selectedText = selectedText.substring(0, 4990);
}
var tk = vq(selectedText, tkk);
console.log("tk -> ", tk);
GM.xmlHttpRequest({
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Host": "translate.google.cn",
},
url: `https://translate.google.cn/translate_a/single?client=t&sl=en&tl=zh-CN&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=btn&ssel=0&tsel=0&kc=0&tk=${tk}&q=${encodeURI(selectedText)}`,
onload: function (response) {
var resp = response.responseText;
//resp.replace("/\n/","<br>");
console.log(response);
var result = JSON.parse(response.responseText);
//var i=1;
console.log(result);
var showinfo = "";
for (var i = 0; i < result[0].length - 1; i++) {
var content = result[0][i][0];
console.log(i, "分段:", /\n/g.test(content));
showinfo += content;
// if(/\n/g.test(content)){
// showinfo +="<br>";
// }
}
GM.setClipboard(showinfo);
showinfo = showinfo.replace(/\n/g, "<br>");
console.log(x, y);
var c_tip_arrow = "width: 0; " +
"height: 0; " +
"font-size: 0; " +
"line-height: 0; " +
"display: block; " +
"position: absolute; " +
"top: -16px;";
var c_tip_con = "position: absolute; " +
"background: #fff; " +
"border: 1px solid #dcdcdc; " +
"border: 1px solid rgba(0,0,0,.2); " +
"-webkit-transition: opacity .218s; " +
"transition: opacity .218s; " +
"-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2); " +
"box-shadow: 0 2px 4px rgba(0,0,0,.2); " +
"padding: 5px 0; " +
"font-size: 12px; " +
"line-height: 20px; " +
"top: 441.133px; " +
"left: 332.5px; " +
"z-index: 220; " +
"display: block; ";
var info = document.createElement("div");
info.setAttribute("id", "ctips");
info.setAttribute("style", `top: ${y + 15}px; left: ${x}px; z-index: 220; display: block;position: absolute; max-width:${widthSelected}px;background: #fff;border: 1px solid #dcdcdc;border: 1px solid rgba(0,0,0,.2);-webkit-transition: opacity .218s;transition: opacity .218s;-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2);box-shadow: 0 2px 4px rgba(0,0,0,.2);padding: 5px; margin-right:30px;font-size: 12px;line-height: 20px;`);
info.innerHTML = '<div style="padding:3px"><span style="color:#999">译:</span>' + showinfo + '</div>';
console.log(info);
document.body.appendChild(info);
},
onerror: function (ex) {
console.log(`異常:${ex}`);
}
});
}
}
else {
var ctips1 = document.getElementById("ctips");
if (ctips1) {
document.body.removeChild(ctips1);
}
}
}
});
// Your code here...
})();