Greasy Fork

Greasy Fork is available in English.

Translate

划词翻译调用“必应翻译(必应词典)、谷歌翻译、有道词典(有道翻译)、百度翻译”网页翻译

当前为 2017-11-08 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Translate
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  划词翻译调用“必应翻译(必应词典)、谷歌翻译、有道词典(有道翻译)、百度翻译”网页翻译
// @author       barrer
// @match        http://*/*
// @include      https://*/*
// @run-at document-end
// @connect      dict.youdao.com
// @connect      cn.bing.com
// @connect      translate.googleapis.com
// @connect      fanyi.baidu.com
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function () {
    'use strict';

    // Your code here...
    /**日志输出*/
    function log() {
        var debug = false;
        if (!debug)
            return;
        if (arguments) {
            for (var i = 0; i < arguments.length; i++) {
                console.log(arguments[i]);
            }
        }
    }

    log('url:' + window.location.href);
    // 翻译图标
    var icon = document.createElement('div'), style = '' +
        'font-family:Arial,sans-serif!important;' +
        'font-weight:normal!important;' +
        'background:#f60!important;' +
        'color:#fff!important;' +
        'border-radius:3px!important;' +
        'font-size:13px!important;' +
        'line-height:100%!important;' +
        'padding:2px 4px!important;' +
        'margin:0 4px!important;' +
        'display:inline-block!important;' +
        'text-decoration:none!important;' +
        '';
    icon.innerHTML = '' +
        '<a href="javascript:void(0)" style="' + style + '"  type="bing">必应</a>' +
        '<a href="javascript:void(0)" style="' + style + '"  type="google">谷歌</a>' +
        '<a href="javascript:void(0)" style="' + style + '" type="youdao">有道</a>' +
        '<a href="javascript:void(0)" style="' + style + '"  type="baidu_translator">百度</a>' +
        '';
    icon.setAttribute('style', '' +
        'display:none!important;' +
        'position:absolute!important;' +
        'font-size:13px!important;' +
        'text-align:left!important;' +
        'z-index:2147483647!important;' +
        '');
    // 添加翻译图标到 DOM
    document.documentElement.appendChild(icon);
    // 鼠标事件:防止选中的文本消失
    document.addEventListener('mousedown', function (e) {
        if (e.target == icon || (e.target.parentNode && e.target.parentNode == icon)) {// 点击了翻译图标
            e.preventDefault();
        }
    });
    // 选中变化事件:当点击已经选中的文本的时候,隐藏翻译图标和翻译面板(此时浏览器动作是:选中的文本已经取消选中了)
    document.addEventListener("selectionchange", function () {
        log('selectionchange:' + window.getSelection().toString());
        if (!window.getSelection().toString().trim()) {
            icon.style.display = 'none';
            server.containerDestroy();
        }
    });
    // 鼠标事件:防止选中的文本消失;显示、隐藏翻译图标
    document.addEventListener('mouseup', function (e) {
        if (e.target == icon || (e.target.parentNode && e.target.parentNode == icon)) {// 点击了翻译图标
            e.preventDefault();
            return;
        }
        for (var i = 0; i < server.rendered.length; i++) {// 点击了翻译内容面板
            if (e.target == server.rendered[i])
                return;// 不再创建翻译图标
        }
        var text = window.getSelection().toString().trim();
        log('text:' + text);
        if (text && icon.style.display == 'none') {
            log('show icon');
            log(text + '|' + e.pageX + '|' + e.pageY);
            icon.style.top = e.pageY + 10 + 'px';
            icon.style.left = e.pageX + 10 + 'px';
            icon.style.display = 'block';
        } else if (!text) {
            log('hide icon');
            icon.style.display = 'none';
            server.containerDestroy();// 销毁翻译内容面板
        }
    });
    // 翻译图标点击事件
    icon.addEventListener('click', function (e) {
        var text = window.getSelection().toString().trim();
        if (text) {
            log('click:' + text);
            server.containerDestroy();// 销毁翻译内容面板
            // 新建翻译内容面板
            var container = server.container();
            container.style.top = e.pageY + 16 + 'px';
            if (e.pageX + 250 + 16 <= document.body.clientWidth)// container 面板css最大宽度为250px
                container.style.left = e.pageX + 16 + 'px';
            else
                container.style.left = document.body.clientWidth - 250 + 'px';
            document.body.appendChild(container);
            server.rendered.push(container);
            // 判断用户选择的翻译引擎
            var engine = e.target.hasAttribute('type') ? e.target.getAttribute('type') : '';
            log('engine:' + engine);
            switch (engine) {
                case 'bing':
                    server.bing(text, container);
                    break;
                case 'google':
                    server.google(text, container);
                    break;
                case 'baidu_translator':
                    server.baidu_translator(text, container);
                    break;
                default:
                    server.youdao(text, container);
            }
        }
    });
    // 翻译server
    var server = {
        // 存放已经生成的翻译内容面板(销毁的时候用)
        rendered: [],
        // 有道翻译 引擎
        youdao: function (text, element) {
            this.ajax('http://dict.youdao.com/w/eng/' + text, function (rst, ele) {
                var parser = new DOMParser(), doc = parser.parseFromString(rst, 'text/html'), html = '';
                var word = doc.querySelector('#phrsListTab .wordbook-js .keyword'),
                    pronounce = doc.querySelector('#phrsListTab .wordbook-js .baav'),
                    trans = doc.querySelector('#phrsListTab .trans-container'),
                    webTrans = doc.querySelectorAll('#tWebTrans .wt-container .title');
                if (!!!pronounce) // 中文拼音
                    pronounce = doc.querySelector('#phrsListTab .wordbook-js .phonetic');
                // 排版
                var pos = trans && trans.querySelectorAll('ul li,ul .wordGroup');
                for (var i = 0; pos && i < pos.length; i++) {
                    pos[i].innerHTML = pos[i].innerHTML + '▓';
                }
                html += word ? word.innerText.trim() : '';
                html += pronounce ? ' ' + pronounce.innerText.replace(/(\s)+/g, ' ').trim() : '';
                html += trans && trans.querySelector('ul') ? '\n' +
                    trans.querySelector('ul').innerText
                        .replace(/(\s)+/g, ' ')
                        .replace(/(▓)+/g, '\n').trim()
                    : '';
                html += trans && trans.querySelector('.additional') ?
                    '\n' + trans.querySelector('.additional').innerText.trim().replace(/\n/g, '') : '';
                if (!!webTrans.length) {
                    html += '\n网络释义:\n';
                    for (var j = 0; j < webTrans.length; j++) {
                        if (j !== 0)
                            html += ';';
                        html += webTrans[j].innerText.replace(/\n/g, '').trim();
                    }
                }
                ele.innerText = html;
                ele.style.display = 'block';// 显示结果
            }, function (rst, ele) {
                ele.innerText = '有道翻译 无法连接!';
                ele.style.display = 'block';// 显示结果
            }, element);
        },
        // Bing词典 引擎
        bing: function (text, element) {
            this.ajax('http://cn.bing.com/dict/search?q=' + text, function (rst, ele) {
                var parser = new DOMParser(), doc = parser.parseFromString(rst, 'text/html'), html = '';
                var word = doc.querySelector('.hd_area'),
                    trans = doc.querySelector('.qdef ul'),
                    forms = doc.querySelector('.qdef .hd_if');
                // 排版
                var headword = doc.querySelector('#headword');
                if (headword)
                    headword.innerHTML = headword.innerHTML + '<br>';
                var pos = doc.querySelectorAll('.qdef ul li .pos');
                for (var i = 0; i < pos.length; i++) {
                    pos[i].innerText = '\n【' + pos[i].innerText + '】';
                }
                html += word ? word.innerText.replace(/\n/g, ' ').trim() : '';
                html += trans ? '\n' + trans.innerText.trim() : '';
                html += forms ? '\n' + forms.innerText.trim() : '';
                ele.innerText = html;
                ele.style.display = 'block';// 显示结果
            }, function (rst, ele) {
                ele.innerText = 'Bing词典 无法连接!';
                ele.style.display = 'block';// 显示结果
            }, element);
        },
        // 谷歌翻译 引擎
        google: function (text, element) {
            var apiUrl = 'https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&dt=bd&dj=1&source=input&sl=en&tl=zh-CN&hl=en&q=';
            this.ajax(apiUrl + text, function (rst, ele) {
                var json = JSON.parse(rst), html = '';
                for (var i = 0; i < json.sentences.length; i++) {
                    html += json.sentences[i].orig + '\n';
                    html += json.sentences[i].trans + '\n';
                }
                ele.innerText = html;
                ele.style.display = 'block';// 显示结果
            }, function (rst, ele) {
                ele.innerText = '谷歌翻译 无法连接!';
                ele.style.display = 'block';// 显示结果
            }, element);
        },
        // 百度翻译 引擎
        baidu_translator: function (text, element) {
            var data = new FormData();
            data.set('from', 'en');
            data.set('to', 'zh');
            data.set('query', text);
            this.ajax('http://fanyi.baidu.com/v2transapi', function (rst, ele) {
                    var json = JSON.parse(rst), html = '';
                    for (var i = 0; i < json.trans_result.data.length; i++) {
                        html += json.trans_result.data[i].src + '\n';
                        html += json.trans_result.data[i].dst + '\n';
                    }
                    ele.innerText = html;
                    ele.style.display = 'block';// 显示结果
                }, function (rst, ele) {
                    ele.innerText = '百度翻译 无法连接!';
                    ele.style.display = 'block';// 显示结果
                },
                element,
                'POST',
                data
            );
        },
        // ajax 跨域访问公共方法
        ajax: function (url, success, error, element, method, data, headers) {
            if (!!!method)
                method = 'GET';
            // >>>因为Tampermonkey跨域访问(a.com)时会自动携带对应域名(a.com)的对应cookie
            // 不会携带当前域名的cookie
            // 所以,GM_xmlhttpRequest【不存在】cookie跨域访问安全性问题
            // 以下设置默认headers不起作用<<<
            if (!!!headers)
                headers = {'cookie': ''};
            GM_xmlhttpRequest({
                method: method,
                url: url,
                headers: headers,
                data: data,
                onload: function (res) {
                    success(res.responseText, element);
                },
                onerror: function (res) {
                    error(res.responseText, element);
                }
            });
        },
        // 销毁已经生成的翻译内容面板
        containerDestroy: function () {
            for (var i = this.rendered.length - 1; i >= 0; i--) {
                if (this.rendered[i] && this.rendered[i].parentNode) {
                    this.rendered[i].parentNode.removeChild(this.rendered[i]);
                }
            }
        },
        // 生成翻译结果面板 DOM (此时还未添加到页面)
        container: function () {
            var div = document.createElement('div');
            div.setAttribute('style', '' +
                'display:none!important;' +
                'position:absolute!important;' +
                'font-size:13px!important;' +
                'overflow:auto!important;' +
                'background:#fefee6!important;' +
                'font-family:Arial,sans-serif!important;' +
                'font-weight:normal!important;' +
                'text-align:left!important;' +
                'color:#000!important;' +
                'padding:0.5em 1em!important;' +
                'line-height:1.5em!important;' +
                'border-radius:5px!important;' +
                'border:1px solid #ccc!important;' +
                'max-width:250px!important;' +
                'max-height:150px!important;' +
                'z-index:2147483647!important;' +
                '');
            return div;
        }
    };// 翻译server结束
})();