X.d 笔记

小Web,大世界

0%

Mini Translate , Chrome 迷你翻译插件

最近报着试一试的心态往Chrome应用商店发了一个插件:迷你翻译,没想到居然过了。

先介绍一下插件

Mini翻译, 是一Chrome浏览器的一个插件,功能很简单,将网页上选中的文字翻译成中文,如果选中的是中文,则翻译为英文。

目前支持英、日、韩、法、意、德、俄、越、印、泰等十几个国家的语言的自动识别!

使用方法

  1. 使用Chorme浏览器打开并安装: https://chrome.google.com/webstore/detail/mini-translate/pgagkefafaecfcchmnohoaekajocbiig
  2. 在网页面上选中文字
  3. 方法一:右键点击,选择翻译,即可翻译
  1. 方法二:按 Ctrl+Q 即可翻译,结果会出现在选中文字的旁边:

为什么要自己做一个插件。

其实就是觉得目前的翻译插件不好用,而且翻译可以使用云服务,基本上没什么开发量就按自己想要的做一个了。

我的需要

我想要这样一个插件:

  1. 不占用资源,平时没有翻译需要的时间意识不到它的存在。
  2. 仅当我想要翻译的时候,随时选中右键或一个快捷键就可以马上翻译。
  3. 自动语种识别,所有语种翻译为中文,如果是中文,则翻译为英文。

目前状况

其它的翻译插件,有个带划词功能,在网页上选择后就会出一个小图标骚扰我,不小心就会点到,感觉很烦。

大部份也不能通过右键直接翻译。

有些突出的是发音音标学习的功能。。。。

有些需要点上面的小图标,再输入文字才能翻译。。。。

总之,感觉很傻,都不是我所需要的。

代码

所以自己造了个轮子,发现,从零开始,参考文档,也不是很麻烦。

以下是所有的代码,不到80行。

  1. tab.js
var x = 0, y = 0;

chrome.runtime.onMessage.addListener(function (resp) {
    if (resp.isClick) {
        let section = window.getSelection();
        var range = section.getRangeAt(0);
        var boundary = range.getBoundingClientRect();
        x = window.scrollX + boundary.left + 12;
        y = window.scrollY + 24 + boundary.top;
        return;
    }

    let div = document.createElement('div');
    div.style = 'top:' + y + 'px;left:' + x + 'px;position:absolute;background-color:rgba(255,255,255,0.85);padding:6px;border-width:1px;border-style:solid;border-color:rgb(187, 187, 187) rgb(187, 187, 187) rgb(168, 168, 168);max-width:480px;display:block;color:#333;z-index:99999;box-shadow:rgba(0, 0, 0, 0.2) 0px 1px 3px;';
    let span = document.createElement('span');
    span.innerHTML = 'X';
    span.style='color:#0008ff;cursor:pointer;text-shadow:0 0 1px black;margin-left:16px;margin-right:8px;opacity:0.6';
    span.setAttribute('title', '关闭');

    span.addEventListener('mouseover',  () => span.style.opacity = '1');
    span.addEventListener('mouseout',  ()  => span.style.opacity = '0.6');
    span.addEventListener('click',  () => document.body.removeChild(div));

    let p = document.createElement('p');
    p.innerText = resp.data;
    p.style = 'font-size:13px;line-height:20px;margin:0;color:#252525;';
    p.append(span);
    div.append(p);

    document.body.append(div);
})


document.addEventListener('keydown', function (event) {
    if (!event.ctrlKey || event.key.toLowerCase() != 'q') return;
    let section = window.getSelection();
    if (section == null || section.anchorNode == null) return;
    let str = String(section).trim();
    if (str == '') return;
    var range = section.getRangeAt(0);
    var boundary = range.getBoundingClientRect();
    x = window.scrollX + boundary.left + 12;
    y = window.scrollY + 24 + boundary.top;
    chrome.runtime.sendMessage(str);
}, true)
  1. menu.js
const MENU_ID = '_M';

function translate(tabId, text) {
    fetch('https://www.xdnote.com/open/translation', {
        credentials: 'include',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json; charset=utf-8',
        },
        body: JSON.stringify({ text }),
    }).then(function (response) {
        response.json().then(function (resp) {
            chrome.tabs.sendMessage(tabId, resp)
        })
    })
}

chrome.contextMenus.create({
    title: '翻译 : "%s"',
    contexts: ["selection"],
    id: MENU_ID,
    onclick:  (info, tab)=> {
        chrome.tabs.sendMessage(tab.id, { isClick: true })
        translate(tab.id, info.selectionText)
    }
});

chrome.runtime.onMessage.addListener( text => {
    chrome.tabs.query({ active: true, currentWindow: true },  tabs=> translate(tabs[0].id, text))
});