Leohearts的Blog

拥有一颗坚强而又温柔的心 *博客主题正在开发

cover

写了个划词翻译TamperMonkey脚本

发现自己用的翻译插件莫名其妙相当吃CPU, 又找不到好用的, 正好前段时间申请了一个百度翻译的api, 就决定自己搓一个.

大致思路是, 监听点击事件, 提取选中的文字, 如果有效就发送到百度请求翻译, 将响应解析后扔进创建的泡泡中.

期间遇到了Allow-Origin的问题, 找到的解决方案是用cors-anywhere做一次代理, 问题是减慢了速度(但是也能用)

完成品:

// ==UserScript==
// @name         Inline Translater
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  在网页上弹出气泡实现划词翻译(基于百度翻译)
// @author       Leohearts
// @match        http://*/*
// @match        https://*/*
// @grant        none
// @require      http://cdn.bootcss.com/blueimp-md5/1.1.0/js/md5.min.js
// ==/UserScript==

var appid = "";
var key = "thisistheapikey";
var globalpageX;
var globalpageY;
var translatecancel = false;

// This function is from https://stackoverflow.com/questions/7790725/javascript-track-mouse-position
function handleMouseMove(event) {
    var eventDoc, doc, body;

    event = event || window.event; // IE-ism

    // If pageX/Y aren't available and clientX/Y are,
    // calculate pageX/Y - logic taken from jQuery.
    // (This is to support old IE)
    if (event.pageX == null && event.clientX != null) {
        eventDoc = (event.target && event.target.ownerDocument) || document;
        doc = eventDoc.documentElement;
        body = eventDoc.body;

        event.pageX = event.clientX +
            (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
            (doc && doc.clientLeft || body && body.clientLeft || 0);
        event.pageY = event.clientY +
            (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
            (doc && doc.clientTop  || body && body.clientTop  || 0 );
    }

    globalpageX = event.pageX;
    globalpageY = event.pageY;
}
document.onmousemove = handleMouseMove;

function closetranslater(){
    translatecancel = true;
    try{
        bdtranslateimg.style.visibility='hidden'
        document.getElementById("bdtranslateimg").innerHTML = ""
        document.getElementById("bdtranslateimg").outerHTML = ""
    }
    catch(error) {}
}

function displaytext(text){
    if (translatecancel){
        return 1;
    }
    //console.log(text)
    var newdiv = document.createElement("div");
    newdiv.id="bdtranslateimg";
    newdiv.style="position: absolute; left: 311; top: 815;visibility :hidden;max-width:40%;z-index:9999999999;";
    newdiv.align="right";
    newdiv.onmouseover=function(){bdtranslateimg.style.opacity=1};
    newdiv.onmouseout=function(){bdtranslateimg.style.opacity=.6};
    var newa = document.createElement("a");
    newa.style="CURSOR:hand;font-size:12px;color:black;border: 1px solid #c0c0c0;text-decoration: none;";
    newa.href="javascript:";
    newa.onclick=function(event){
        event.stopPropagation();
        bdtranslateimg.style.visibility='hidden'
        document.getElementById("bdtranslateimg").innerHTML = "";
        document.getElementById("bdtranslateimg").outerHTML = "";
        translatecancel = true;
    };
    newa.innerText="X";
    var newdiv2 = document.createElement("div");
    newdiv2.style="border: 1px solid #c0c0c0;margin: 0 auto;padding: 5px;background: #f0f0f0;border-radius: 10px;font-size:12px;text-align:left;";
    newdiv2.innerText=text;
    newdiv2.onclick = function(event){event.stopPropagation();};
    newdiv.append(newa);
    newdiv.append(newdiv2);
    document.querySelector("body").append(newdiv);

    var xPos = globalpageX - 30;
    var yPos = globalpageY - 0;
    bdtranslateimg.style.top = yPos+"px";
    bdtranslateimg.style.left = xPos+"px";
    bdtranslateimg.style.visibility = "visible";
}

function bdtranslate(txt){
    var salt = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
    var apisign = md5(''+appid+txt+salt+key);
    var url = "https://api.fanyi.baidu.com/api/trans/vip/translate?q="+encodeURI(txt)+"&from=auto&to=zh&appid="+appid+"&salt="+salt+"&sign="+apisign;
    fetch("https://cors-anywhere.herokuapp.com/" + url, {
        "credentials": "omit",
        "method": "GET",
        "headers": {
            "x-requested-with": "XMLHttpRequest"
        },
        "mode": "cors"
    }).then(function(response){
        return response.json();
    }).then(function(resp){
        try{
            if (resp.error_code){
                closetranslater();
                translatecancel = false;
                displaytext("error");
                return 1;
            }
        }
        catch(error){}
        var st = "";
        for (var i = 0;i<resp.trans_result.length;i++){
            st += resp.trans_result[i].dst;
        }
        closetranslater();
        translatecancel = false;
        displaytext(st);
    });
}
document.onclick = function(){
    closetranslater();
    var selecttext=window.getSelection().toString();
    if(selecttext!=null && selecttext.trim()!=""){
        translatecancel = false;
        displaytext("Translating..");
        bdtranslate(selecttext.trim());
        //console.log(selecttext.trim());
    }
}