划词翻译

基于 translate.google.cn 的划词翻译,用鼠标选中纯英文内容即可。每次翻译的结果自动复制到剪贴板,用户可直接粘贴使用。

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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...
})();