2

先贴一个链接,在写chrome插件的过程中,需要经常查看chrome的文档,因为需要用到很多chrome的接口
chrome官方对如何写插件的教程
github源码

什么是chrome插件

在我们平时使用chrome浏览器的过程中,经常会使用到插件,他让我们可以更方便的处理一些事情。

请看浏览器上面部分的那一排图标
title

这些就是插件!
比如第一个用来收发邮件的插件,点击菜单栏上该插件的按钮,会弹出一个框,可以很方便的查看当前有哪些邮件
title
如果想要看更详细的内容,查看右上角的那些按钮,根据相应功能点击对应的按钮就行了。

插件在【扩展程序】里进行管理。

打开扩展程序网页进入管理插件的网页
或者点击浏览器窗口右上角的这个橙色选项
title

然后选择【更多工具】→【扩展程序】
就可以看到下面这个网页,打开【开发者模式】,我们就可以开始写自己的插件了。
title

配置文件

每个插件都必须有这个文件,配置文件用来设置该插件的一些东西,为浏览器提供了关于这个插件的重要信息,比如这个插件的名字,版本号,描述,图标,权限等设置。

创建配置文件manifest.json

//json文件里不能有注释,我这里写了注释只是为了更容易理解一点,如果是直接把这里的内容粘贴到编辑器中,为了避免报错,需要把所有的注释删除掉

//下面我会用 【必须有】【推荐】【可选】这三个词语来描述该文件内的必须写的内容和其他可以选择的内容

{
//【必须有】
  //插件的名字
  "name": "yj-translate",
  //你的插件版本
  "version": "0.1",
  //对于chrome18及以上的浏览器版本,需要指明这个manifest.json文件的版本是2,以该版本的格式来描述这个文件,如果你的插件需要支持chrome17及以下的版本,则推荐把值设置为1
  "manifest_version": 2,
   
 //【推荐】
   //对插件的描述
  "description": "这是一个chrome翻译插件",
  //插件的图标。128*128尺寸必须提供(使用场景:下载时&chrome Web Store中显示的图标);48*48也应该提供,该图标会在插件管理页面显示(chrome://extensions);最好用png格式,对透明度的支持最好。总之最好能提供多样的尺寸(并且图片都需要是正方形),这样chrome会根据场景选择最适当的图标大小。
  "icons": {
    "16": "images/get_started16.png",
    "32": "images/get_started32.png",
    "48": "images/get_started48.png",
    "128": "images/get_started128.png"
  },
  
//【两个中选其中一个/一个也不写】
  "browser_action": {
    "default_icon": {
      "16": "images/get_started16.png",
      "32": "images/get_started32.png"
    },
    "default_title": "划词翻译",
    "default_popup": "popup.html"
  },
    "page_action": {
          "default_icon": {                    
            "16": "images/icon16.png",           
            "24": "images/icon24.png",           
            "32": "images/icon32.png"        
          },
          "default_title": "Google Mail",   
          "default_popup": "popup.html"     
        }
}

该文件还可以配置很多其他的内容,等用到相关的再写,现在先写这些就差不多了。

注:上面的icon选项的值有写images/icon16.png 等等,里面的路径是相对路径,可以自己根据目录结构的情况来写,我这里之所以这样写是我在根目录那里创建了一个images文件
如下
title

关于最后部分的两个选项,browser_action , page_action

[browser_action]
通过这个配置选项可以配置chrome浏览器工具栏(地址栏右边那部分)的插件图标
title

还可以设置,当点击该图标后,弹出的小框里的内容由哪个HTML构成
title

查看上面manifest.json文件中关于browser_action的配置

 "browser_action": {
 //默认浏览器工具栏上插件的默认图标
    "default_icon": {
      "16": "images/get_started16.png",
      "32": "images/get_started32.png"
    },
    //鼠标悬浮在图标上后显示的插件名字
    "default_title": "划词翻译",
    //在当前同路径下面创建一个popup.html文件,点击图标按钮后,弹出的小框里的HTML内容就是该文件的内容
    "default_popup": "popup.html"
  }

page_action
可以设置只在某些网页可以显示该插件的图标,在其他网页,这个图标的颜色会变成灰色,也就是不可用。一个例子就是vue的开发者工具插件,如果当前网页用了vue,这个插件就是有颜色的可用的,如果在其他网页,插件的图标就会变成灰色,标识不可用。

如下面的这个RSS插件,在特定网页下是可用的,在其他网页下是灰色的不可用。
title

开始写插件

在线调试

在写插件的额过程中,我们如果想要一边写一边看效果,请打开扩展程序页面

title
1.打开开发者模式
2.加载已解压的扩展程序
title

找到你的项目文件,点击【选择文件夹】

插件中就会增加一个新的插件
title

每当我们在编辑器编辑了一次文件后,需要点击插件上的刷新按钮应用最新代码
title

功能1:翻译网页中选中的内容

在我们平时用的如网易有道词典,goldendict等翻译软件中,大部分都有在网页中划词翻译的功能。

比如网易有道词典的划词翻译功能:打开一个网页,选中一个英语单词,就会出现一个图标
title

再点击一次图标,就会翻译出用户选中的文本
title

我们做的第一个功能就是:
在任意网页中选中文本后,弹出一个小框,将选中的文本翻译成中文。

目前,先不考虑其他语言类型,只考虑一种情况:用户选中的文本是【英文】,需要翻译成【中文】。

要做出这一个功能,我们可以思考一下,把这个功能分割成多个需要完成的步骤;
1.情景是在任意网页中,而不是特定网页,所以我们需要告知浏览器,这个功能是在每个chrome标签页中都有效
2.触发出这个翻译面板的事件是当用户释放鼠标时触发,比如平时用鼠标点击一个地方的时候,会先按下鼠标,再释放鼠标。这里我们监听释放鼠标的事件,这个事件稍后我们去查看有没有相应的webAPI
3.获取用户选中的文本,稍后去查看是否有相应的webAPI
4.前面的三个步骤是触发出翻译面板之前的大概步骤,当触发出翻译面板后,我们需要将获取到的用户选中的文本插入到翻译面板中,然后通过谷歌翻译接口把内容翻译后,把翻译后的文本插入到翻译面板中。
翻译面板样式如下
title

大致就是上面的步骤,接下来从第一个步骤开始。

关于chrome插件,它不仅可以在网页中用插件
title

还可以在网页中鼠标右键时,出现一个该插件的菜单title

或者点击浏览器工具栏上的插件按钮时,弹出的小框中的内容等等。

这些所有的功能并不是写在同一个HTML / js 文件中,chrome对他们进行了不同的类型划分。

我们当前想在网页上进行的交互,对chrome来说属于[Content Scripts]

title

manifest.json中添加如下代码

  "content_scripts": [
    {
    //匹配:所有的网页都有效
      "matches": ["<all_urls>"],
    //css样式写在content-script.css
      "css": ["content-script.css"],
    //js代码写在content-script.js
      "js": ["content-script.js"]
    }
  ],
  //添加权限使它可用
  "permissions": [
    "activeTab"
  ]

manifest.json中配置好之后,我们已经从上面看到,我们需要创建两个相应的文件来完成我们的第一个功能。

在根目录中新建content-script.js,content-script.css这两个文件。

当前目录结构如下
title

先抛开功能,我们把样式写出来
title

样式的代码如下
https://jsfiddle.net/okokok/v...

由于content Script只有js 和 css文件可以配置,外加面板里面的内容也不是固定的,比如用户选中的需要翻译的内容和需要动态显示翻译后的内容,因此我们的HTML代码需要在js文件内动态创建。

打开content-script.css

//添加下面的内容
.translate-panel {
    width: 280px;
    box-shadow: 1px 1px 8px 2px rgba(0, 0, 0, .2);
    border-radius: 8px;
    transform: scale(0.6);
    z-index: 1000;
    background: #fff;
    position: absolute;
    top: 10px;
    opacity: 0;
    transition: all .2s;
}

.translate-panel.show {
    transform: scale(1);
    opacity: 1;
}

.translate-panel header {
    background: #eee;
    padding: 10px;
    font-size: 12px;
    color: #666;
    position: relative;
}

.translate-panel header .close {
    position: absolute;
    right: 10px;
    cursor: pointer;
}

.translate-panel main {
    padding: 0 10px;
    margin-bottom: 0;
}

.translate-panel main .source {
    border-bottom: 1px #eee solid;
    padding-bottom: 10px;
}

.translate-panel main .dest {
    padding-bottom: 10px;
}

.translate-panel .title,
.translate-panel .content {
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

.translate-panel .title {
    font-size: 12px;
    color: #888;
    margin-top: 10px;
}

.translate-panel .content {
    color: #666;
    font-size: 13px;
    margin-top: 6px;
    overflow: hidden;
}

然后是js代码,先说下大概思路:
1.先用js创建一个div元素,他的innerHTML是翻译面板的HTML内容,把这个div挂载在页面上,但是默认是隐藏的(opacity:0),只有当用户选中了内容释放鼠标后才会显示
这个翻译面板(给div元素添加一个class,设置该状态的样式为opacity:1;)到这一步为止,显示在网页上的翻译面板的静态样式已经确定好。
2.翻译使用的是谷歌的免费接口 (https://translate.googleapis....'这里是需要翻译的内容')
接口中: sl = source language = 原文本内容的语言类型;tl = target language = 翻译后的内容的语言类型;q = 需要翻译的内容
3.监听鼠标的onmouseup事件,这个是当释放鼠标时会触发的,然后,通过webAPI中的 window.getSelection().toString() 获取到用户选中的
内容,如果用户没有选中任何内容,则return出去后续不做任何反应,如果有内容,则调用封装好的翻译函数,把选中的内容当作内容传递进去,把选中的内容和翻译好的内容
用innerText的方式插入到之前创建的div元素(翻译面板)对应的位置。
在这步同时可以获取到释放鼠标时鼠标所在的位置,把位置当作参数传给封装好的翻译面板位置设置函数。

content-script.js文件中添加如下代码

// 写一个翻译面板的构造函数,可以通过它new一个翻译面板实例出来
function Panel() {
    //实例化panel时,调用create函数(作用:在页面上挂载翻译面板的div元素)
    this.create()
    
    //调用bind函数(作用:绑定翻译面板上关闭按钮的点击事件)
    this.bind()
}

//在Panel的原型链上创建一个create方法(作用:生成一个div元素,innerHTML是翻译面板的HTML内容)
Panel.prototype.create = function () {
    
    //创建一个div元素,变量名叫container
    let container = document.createElement('div')

    /*翻译面板的HTML内容 里面class为content的标签内的内容没有写,因为这里面的内容需要后面动态生成后插入,简体中文那里的content写了三个点是
    是因为那里的翻译后的内容是异步获取的,在真正获取到内容前,把内容都显示成...做一个过渡*/
    let html = `
        <!--X是用来做关闭按钮-->
        <header>翻译<span class="close">X</span></header>
  <main>
    <div class="source">
      <div class="title">英语</div>
      <!--这里动态插入用户选中的需要翻译的内容 所以先留空 什么都不写-->
      <div class="content"></div>
    </div>
    <div class="dest">
      <div class="title">简体中文</div>
      <!--这里动态插入翻译后的内容,由于是异步获取,在获取到内容之前,先显示为...,否则如果当用户需要多次翻译时,在异步获取完成之前,内容会显示上一次翻译完成的文本-->
      <div class="content">...</div>
    </div>
  </main>
    `

    //刚刚创建的div元素里的HTML内容素替换成上面的内容
    container.innerHTML = html
    
    //给container添加一个class,查看content-script.css,这个class是最外层的div需要的class
    container.classList.add('translate-panel')
    
    //把container挂载到页面中
    document.body.appendChild(container)
    
    //把这个container当成一个属性赋值给Panel构造函数,方便后续对这个翻译面板进行其他操作,如替换面板中的内容
    this.container = container
    
    //把关闭按钮也赋值到Panel的属性close上
    this.close = container.querySelector('.close')
    
    //用来显示需要查询的内容
    this.source = container.querySelector('.source .content')
    
    //用来显示翻译后的内容
    this.dest = container.querySelector('.dest .content')
}

//显示翻译面板
Panel.prototype.show = function () {
    //container默认没有show这个class,默认样式是opacity:0;css中,如果container同时拥有show class,则opacity:1 取消隐藏
    this.container.classList.add('show')
}

//隐藏翻译面板
Panel.prototype.hide = function () {
    this.container.classList.remove('show')
}


//Panel函数绑定的事件. 
Panel.prototype.bind = function () {
    //关闭按钮发生点击事件
    this.close.onclick = () => {
        //把翻译面板隐藏起来
        this.hide()
    }
}

//翻译功能函数 (参数raw的含义:用户选中的文本内容)
Panel.prototype.translate = function (raw) {
    //翻译前的文本内容
    this.source.innerText = raw
    //翻译后的文本内容(由于获取到翻译后的内容是一个异步过程,此时还没有开始翻译,先把翻译后的文本设置为...,后面等异步完成,获取到翻译后的内容后,再重新把内容插入进去)
    this.dest.innerText = '...'

    //用户选中的需要翻译的语言 如需要把英文翻译成中文,这里指的就是英文
    let slValue = 'en'
    //需要翻译成的语言 如需要把英文翻译成中文,这里指的就是中文
    let tlValue = 'zh-Hans'
    // })
        //谷歌翻译接口 sl:需要翻译的语言(en 英语) tl:需要翻译成哪种语言 (zh-Hans 中文) q:需要翻译的内容
        fetch(`https://translate.googleapis.com/translate_a/single?client=gtx&sl=${slValue}&tl=${tlValue}&dt=t&q=${raw}`)
            .then(res => res.json()) 
            .then(res => {
                //异步完成后,把获取到的已翻译完成的译文内容插入到翻译面板中
                this.dest.innerText = res[0][0][0]
            })
}

//翻译面板在网页中显示的位置 传入的参数是一个pos对象,其中包含x,y
Panel.prototype.pos = function (pos) {
    //翻译面板用absolute定位,通过传入的鼠标光标位置参数设置面板在网页中显示的位置
    //设置翻译面板的top属性
    this.container.style.top = pos.y + 'px'
    //设置翻译面板的left属性
    this.container.style.left = pos.x + 'px'
}

//实例化一个翻译面板
let panel = new Panel()

//监听鼠标的释放事件
window.onmouseup = function (e) {
    //获取到用户选中的内容
    let raw = window.getSelection().toString().trim()

    //获取释放鼠标时,光标在页面上的位置
    let x = e.pageX
    let y = e.pageY

    //如果什么内容都没有选择,就不执行下面的,直接返回
    if (!raw) {
        return
    } else {
        //否则执行下面的内容
        //设置翻译面板的显示位置
        panel.pos({x: x, y: y})
        //翻译选中的内容
        panel.translate(raw)
        //把翻译面板在网页中显示出来
        panel.show()
    }
}

打开【扩展程序页面】
点击刷新按钮(每次更改后都需要刷新)
title

新开一个标签页,或者任意查看之前已经打开的标签页(该标签页也需要刷新),然后用鼠标选择语言是英文的内容查看是否有翻译面板弹出来,并且是否有显示翻译后的文本内容。
title

功能2:点击浏览器工具栏插件图标,弹出是否开启插件的选择框

需要达到的效果如下:
点击白色框中的插件按钮,会弹出一个框,内容是一个选择框,可以选择是否开启插件的划词翻译功能
title

注意:这里并不是选择【关闭】后就真的不能划词翻译了,要做到这点需要查看chrome提供的API将关闭划词翻译功能的信息传递过去。
目前我们这里需要达到的效果只是:点击浏览器工具栏上的插件图标后,会弹出一个弹出层(popup),弹出层的内容是一个选择框,并且在刷新页面后,选择框里的默认选项是上次用户已选择的内容。

在最开始我们写manifest.json文件时就已经写好了关于popup的一个基本配置

 "browser_action": {
    "default_icon": {
      "16": "images/get_started16.png",
      "32": "images/get_started32.png"
    },
    "default_title": "划词翻译",
    "default_popup": "popup.html"
  },
    "permissions": [
    //由于需要用到chrome的storage接口,所以需要增加使用权限
    "storage"
  ]

default_popup代表我们需要在根目录创建一个popup.html来写弹出层里的内容

 //popup.html
 <!--该文件的作用:用户在浏览器的菜单上点击插件按钮后会弹出一个小框,小框里的HTML内容就是该文件的代码-->
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        .container {
            width: 160px;
        }

        a {
            text-decoration: none;
        }
    </style>
</head>
<body>
<div class="container">
    <p>是否开启划词翻译</p>
    <select id="select">
        <option value="on">开启</option>
        <option value="off" selected>关闭</option>
    </select>
</div>
<!--加载一个js 需要和content-script进行交互传递信息,比如用户选择关闭划词翻译,那么在页面上就不显示翻译面板-->
<script src="popup.js"></script>
</body>
</html>

根目录创建popup.js文件

//每次都需要先查看用户之前有没有设置过开启/关闭划词翻译功能.使用chrome的storage接口,查看能不能获取到 'switch' 这一项
chrome.storage.sync.get(['switch'], function (result) {
    console.log('之前用户选择的是' + result.switch + '划词翻译功能')

    //如果之前有把用户的选择存储到chrome的storage中
    if (result.switch) {
        //把弹出层里选择框的值设置成之前已存储好的值 on / off (这样就不会在每次刷新页面后选择框的选项都被重置)
        selectNode.value = result.switch
    }
});

//监听这个选择框,当值发生变化时触发
selectNode.onchange = function () {
    //划词翻译功能,利用chrome的storageAPI存储开启/关闭状态:把用户选择的选项存储在chrome的 storage 接口中,存到 'switch'中,下次取出来的时候通过 'switch' 取
    chrome.storage.sync.set({switch: this.value})
}

点击【扩展程序】页面中插件的刷新按钮,在浏览器工具栏中点击插件按钮,弹出一个弹出层
title

选择【开启】

重新在浏览器工具栏中点击它,自动获取到上次用户的选择,选项已默认为【开启】
title

功能3:popup和content script进行数据传递

需要做到的效果是:当用户在popup中选择【关闭】选项后,页面真的不能进行划词翻译了。

功能3需要做的就是把功能1和功能2结合起来,如果用户选择【开启】,那么页面上就可以进行划词翻译,如果用户选择关闭,那么页面上不可以进行划词翻译。

由于popup的js是写在popup.js里的,网页中的翻译面板的js是写在content-script.js里的,两个不同的js文件,如果想要互相传递数据,比如popup.js告诉content-script.js用户选择的是【关闭】,那么可以使用chrome的API进行数据的传递。

首先在manifest.json中添加该接口的权限

  "permissions": [
    "tabs"
  ]

popup.js中添加以下代码
title

   //通知 content-script.js 用户选择的是开启还是关闭
   //由于chrome浏览器上可能开启了多个窗口&标签页,所以需要先找到currentWindow,和当前活动的网页 active
    chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
        //给当前标签页发送信息(筛选出来的该标签的第一个的id)
        chrome.tabs.sendMessage(tabs[0].id, {switch: this.value})
    })

content-script.js接收信息,并做出相应的反应
随意位置添加下面代码


//划词翻译默认是关闭状态
let selectState = 'off'

//用chrome的storage接口,查看之前有没有存储 'switch' 这一项(查看用户之前是否已选择开启/关闭划词翻译功能,只要选择过,都会存储在switch里)
chrome.storage.sync.get(['switch'], function (result) {
    //如果有设置
    if (result.switch) {
        //把值(on / off)赋值给网页上翻译插件的状态变量
        selectState = result.switch
    }
});

//运行时,监听是否有数据传过来
chrome.runtime.onMessage.addListener(
    function (request) {
        // 如果有传 'switch' (当选项[开启]/[关闭]发生改变时,popup.js都会给当前活动标签页传递switch数据,也就是用户选择的选项是什么)
        if (request.switch) {
            //把用户修改的选项的值赋值给该变量
            selectState = request.switch
        }
    });

最后在监听onmouseup事件的函数内添加下面内容
title

    //如果用户选择的是关闭选项 就不显示翻译面板
    if (selectState === 'off') return

这样就完成了数据的传递。
【扩展程序】里的插件刷新一下就可以了。

功能4:menu打开翻译页面窗口

效果:
在任意网页中,鼠标右键后,出现插件的菜单
title

点击该选项后,跳转到百度的翻译页面
title

首先还是在manifest.json中写好相应的设置

  "icons": {
  //icons中一定要添加16*16的icon,当右键时显示的菜单的图标就是它
    "16": "images/get_started16.png"
  },
   "permissions": [
   //增加权限
    "contextMenus"
  ],
  //相应的js代码写在background.js中
    "background": {
    "scripts": ["background.js"],
    "persistent": false
  }

创建background.js,代码写在这里

//该文件相当于插件的后台,时刻在运行
//下面的代码做了两个功能: 1.当用户在页面上选择了文字并鼠标右键后,会有该插件的一个菜单选项;
// 2.点击该菜单选项,跳转到一个新标签页,内容是百度翻译刚才选中的文本

chrome.runtime.onInstalled.addListener(function() {
//创建一个chrome的 menu(在页面上右键时出现的菜单)
    chrome.contextMenus.create({
        "id": "translateMenu",
        //title 是当用户右键页面后,在页面上显示的该插件的名字
        "title": "翻译 %s",
        //只有当选中了内容,右键后才会出现插件menu
        "contexts": ["selection"]
    });
});

//菜单被点击时触发该事件
chrome.contextMenus.onClicked.addListener(function(info) {
    //如果 id === ↑创建的菜单的id
    if (info.menuItemId === 'translateMenu') {
        //创建一个 标签页 url是:百度的翻译API 翻译内容是用户选中的内容
        chrome.tabs.create({url: `https://fanyi.baidu.com/#lang-auto/lang-auto/${info.selectionText}`})
    }
})

功能5:配置多语言翻译

效果:
在popup中增加一个设置链接
title

点击后在新标签页打开设置页面,可以设置需要翻译的语言,翻译成什么语言
title

网页中可提供多语言翻译:
title

manifest.json添加以下内容

  "options_page": "options.html"

创建options.html

<!--该页面的内容会应用在插件的【扩展程序选项】-->
<!--该页面完成功能:支持多种语言翻译-->
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置</title>
    <style>
        body {
            background: #eee;
        }

        .container {
            width: 400px;
            margin: 20px auto;
            background: #fff;
            padding: 30px;
        }

    </style>
</head>
<body>
<div class="container">
    <h1>语言设置</h1>
    <h4>From</h4>
    <select id="from">
        <option value="zh-CN" data-key="中文">中文</option>
        <option value="en" selected data-key="English">English</option>
        <option value="ja" data-key="日本語">日本語</option>
        <option value="fr" data-key="Français">Français</option>
        <option value="de" data-key="Deutsch">Deutsch</option>
        <option value="ru" data-key="русский язык">русский язык</option>
        <option value="mn" data-key="Монгол улс">Монгол улс</option>
        <option value="ar" data-key="العربية">العربية</option>
    </select>

    <h4>To</h4>
    <select id="to">
        <option value="zh-CN" data-key="中文" selected>中文</option>
        <option value="en" data-key="English">English</option>
        <option value="ja" data-key="日本語">日本語</option>
        <option value="fr" data-key="Français">Français</option>
        <option value="de" data-key="Deutsch">Deutsch</option>
        <option value="ru" data-key="русский язык">русский язык</option>
        <option value="mn" data-key="Монгол улс">Монгол улс</option>
        <option value="ar" data-key="العربية">العربية</option>
    </select>
</div>
<script src="options.js"></script>
</body>
</html>

如何查看这些内容在什么地方显示?
打开扩展程序页面
找到你的插件,点击【详细信息】
title

页面往下滑动找到【扩展程序选项】
title

跳转后的页面内容就是刚刚我们在options.html里写的内容
title

记住上面绿色框中的地址,稍后会用到。

在这个页面中我们可以让用户自行选择需要翻译的语言类型是什么,但是每次用户需要设置的时候都要经过上面那几个步骤,所以很麻烦,为了方便,我们在popup中写一个设置链接,点击那个链接,用户就可以直接跳转到这个设置页面,很方便。

在popup中有这样一个设置链接
title

想要达到这个目的只需要打开popup.html文件
在这里添加以下内容
title

    <!--点击该链接,跳转到【扩展程序选项】页面(从新的标签页打开)-->
    <p><a target="_blank" href="chrome-extension://jllpopkjppjffkcppibkbcanfeljcfih/options.html">设置</a></p>

注意上面的a标签里的href属性每个人都不一样的,href是根据你的【扩展程序选项】页面的链接填写,也就是刚刚用绿色框出来的那个url。

刚刚我们在创建options.html时,里面还引用了一个options.js文件,在根目录创建这个文件。

目前我们的目录结构是这样的
title

options.js中添加以下代码

//该页面是【扩展程序选项】的js代码

//获取from选择框
let fromSelect = document.querySelector('#from')
//获取to选择框
let toSelect = document.querySelector('#to')

//使用chrome storage get API,获取存储进去的 sl(source language) tl(target language)
chrome.storage.sync.get(['sl', 'tl'], function(result) {
    //如果有存储过 source language
    if (result.sl) {
        //把值赋值给页面上的from选项 作用:用户上次关于from选择的是英文,刷新页面后该选项还是默认为英文
        fromSelect.value = result.sl.value
    }

    //如果有存储过 target language
    if (result.tl) {
        //把值赋值给页面上的to选项
        toSelect.value = result.tl.value
    }

    //from选项的值改变的时候
    fromSelect.onchange = function() {
        //获取到当前被选择的选项的 data-type 属性
        let key = this.selectedOptions[0].getAttribute('data-key')
        //chrome storage set API 存储信息,srouce language,传入一个对象
        chrome.storage.sync.set({'sl': {key: key, value: this.value}})
    }

    //to选项的值改变的时候
    toSelect.onchange = function() {
        let key = this.selectedOptions[0].getAttribute('data-key')
        chrome.storage.sync.set({'tl': {key: key, value: this.value}})
    }
})

但是这样还不行,我们需要通知content-script(关于页面上的交互),比如我们在【扩展程序选项】页面设置了需要翻译的语言【from】是中文,翻译后的语言【to】为法语, 那么当用户在页面上选中了中文后,划词翻译插件经过翻译后,在页面上显示出来的翻译面板应该是从中文翻译到法语的,就像下面这样
title

content-script.js中的翻译函数部分添加下面的代码
title

 //查看用户是否已经设置了语言类型
    chrome.storage.sync.get(['sl', 'tl'], (result) => {
        if (result.sl) {
            slValue = result.sl.value
            this.container.querySelector('.source .title').innerText = result.sl.key
        }

        if (result.tl) {
            tlValue = result.tl.value
            this.container.querySelector('.dest .title').innerText = result.tl.key
        }

        //谷歌翻译接口 sl:需要翻译的语言(en 英语) tl:需要翻译成哪种语言 (zh-Hans 中文) q:需要翻译的内容
        fetch(`https://translate.googleapis.com/translate_a/single?client=gtx&sl=${slValue}&tl=${tlValue}&dt=t&q=${raw}`)
            .then(res => res.json())
            .then(res => {
                //异步完成后,把获取到的已翻译完成的译文内容插入到翻译面板中
                this.dest.innerText = res[0][0][0]
            })
    })

最后刷新一下插件就可以了。

目前就是这些功能,能满足基本的多语言翻译,样式还需要再进行修改。


君额上似可跑马
39 声望4 粉丝