零插件基础撸一个谷歌浏览器插件实现中英文翻译

背景

很难受,上学的时候英语没好好学,现在搞到编程这一行来了,时常会查看翻阅一些资料、文章,打开一看,又是一片全英文,好吧,一个窗口看文章,一个窗口打开google翻译,cvcv,一遍又一遍,又开始了。前段时间开始搞一下谷歌浏览器插件,发现可以很方便的往浏览器每个网站注入脚本,很棒,稀奇古怪的思路这不就来了。先来搞一个英译中的谷歌翻译插件。

效果

  • 鼠标选中需要翻译的英文,通过标签title属性显示其翻译后的中文
  • 话不多说,先来看效果
  • 本来是想window+G上次录屏效果的,发现浏览器title效果录屏录不下来,这就只上两张图片效果了(>-<)

插件基础

google插件内容主要由以下几部分组成

  • manifest.json 配置文件
  • content_script 注入到网页的脚本
  • background 插件脚本
  • popup/options页面,插件配置页面
  • 以及插件内置的许多功能

这篇只用到了前面三个,先来上一个翻译插件全部文件目录文件结构

原理

通过浏览器插件,注入脚本到网站,在脚本钟添加selectionchange事件获取鼠标选中的文本,然后调用翻译API,翻译选中的英文,将翻译的结果添加到当前选中标签的title属性中进行展示。

开撸

新建项目

  • 新建一个空文件夹,用于存放插件项目:translate
  • 进入translate文件夹

创建manifest.json文件

  • google插件必须文件

manifest.json,实际使用的时候需要把注释代码去掉

json 复制代码
// 这些项属于每个浏览器插件必备项
{
    "manifest_version": 3, // 插件版本
    "name": "解放英语", // 插件名称
    "version": "1.0.0", // 发布到google应用上的版本
    "description": "阅读英语文档老大难的伙计们的福音", // 插件描述
    "icons": { // 插件图标
      "16": "assets/1.jpg",
      "32": "assets/1.jpg",
      "48": "assets/1.jpg",
      "128": "assets/1.jpg"
    },
}

创建浏览器脚本文件

/content-script/translate.js

arduino 复制代码
console.log('浏览器脚本translate.js文件')

配置manifest.json文件,添加content_scripts配置

json 复制代码
{
   "content_scripts": [ // content_scripts中注册的js脚本会注入到网页中
        {
            "matches": ["https://*/*", "http://*/*"], // 匹配到的URL会注入脚本
            "js": ["content-script/translate.js"]
        }
    ],
}

插件调试

  • google浏览器输入chrome://extensions/ 进入插件页
  • 打开开发者模式,点击加载已解压的扩展程序,选择刚创建的translate文件夹
  • ok,插件已经成功引入了
  • 开启插件
  • 任意进入到一个https或http的网页
  • 打开console,查看translate.js中的代码是否执行
  • ok,一个简单的浏览器插件已经创建成功

添加translate.js内容

插件已经成功引入,接下来当时是添加功能

javascript 复制代码
let str = ''

// 添加 mouseup 事件监听器
document.addEventListener('mouseup', handleMouseUp);
 
// 添加 selectionchange 事件监听器
document.addEventListener('selectionchange', handleSelectionChange);
 
// 处理 selectionchange 事件的回调函数
function handleSelectionChange(event) {
  const selection = window.getSelection();
  if (selection && selection.toString().length != 0) {
      str = selection.toString()
  }
}

// mouseup时,去调用翻译API,翻译选中的文本
async function handleMouseUp(event) {
    if(str.length!==0){
      if (str) {
         // content_script脚本和插件脚本间的通信方式,可以在插件脚本通过固定方法接收
        const res = await chrome.runtime.sendMessage({
          action: 'translate',
          str
        })
        str = ''
        
        // 将翻译结果添加到标签的title属性查看
        event.target.setAttribute('title', res.join(' '))
      }
    }
}

创建background 插件脚本

  • 翻译API选择在插件脚本中调用(内容脚本中调用存在各种各样的问题)

background/service_worker.js

javascript 复制代码
// 监听content_script脚本中sendMessage过来的信息
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action === 'translate') {
    // 在这调用翻译API,翻译文本
  }
  return true // 允许异步sendResponse
})

翻译API选型

百度翻译、google翻译、有道翻译都有翻译API,这选的有道翻译API,为啥选这个呢,问就是勤俭节约(>-<)

有道翻译API文档:ai.youdao.com/doc.s#guide

调用翻译API

修改service_worker.js文件

javascript 复制代码
// 两个key可以根据有道API文档获取
const APP_KEY = ''
const KEY = ''

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action === 'translate') {
    getTraslateRes(request.str).then(res => {
      sendResponse(res.translation) // 将翻译的结果返回给content_script
    })
  }
  return true
})

function getTraslateRes(query) {
	const data = generateTranslateParams(query);
	const formData = new FormData()
	Object.keys(data).forEach((key) => {
		formData.append(key, data[key])
	})
	return new Promise((resolve) => {
		fetch('https://openapi.youdao.com/api', {
		method: 'POST',
		body: formData,
		}).then((res) => {
		if (res.ok) {
			const jsonData = res.json()
			resolve(jsonData)
		}
		})
	})
}

function generateTranslateParams(query) {
  const salt = new Date().getTime()
  const curtime = Math.round(new Date().getTime() / 1000)
  // 多个query可以用\n连接  如 query='apple\norange\nbanana\npear'
  const from = 'en'
  const to = 'zh-CHS'
  const str1 = APP_KEY + truncate(query) + salt + curtime + KEY
  const sign = CryptoJS.SHA256(str1).toString(CryptoJS.enc.Hex)
  const params = {
    q: query,
    appKey: APP_KEY,
    salt: salt,
    from: from,
    to: to,
    sign: sign,
    signType: 'v3',
    curtime: curtime,
    vocabId: APP_KEY
  }
  return params
}

function truncate(q) {
  const len = q.length
  if (len <= 20) return q
  return q.substring(0, 10) + len + q.substring(len - 10, len)
}

结语

ok,就是这么简单,可以更加方便的阅读网页英文文档了,再也不用开两个窗口,然后cvcv,(>-<)

补充

翻译API毕竟免费额度有限,可以通过添加缓存进行优化,已经翻译过的就不要再去调用翻译API了,直接从缓存里面获取就ok。 后续打算的是会通过使用indexDB进行一个英文词句的缓存,通过indexDb的导入导出,逐渐收录壮大一个key-value的英译中字典,到一定程度后,就再也不担心翻译API的免费额度不够用了(>-<) indexDb的增删改查

相关推荐
i听风逝夜28 分钟前
Web 3D地球实时统计访问来源
前端·后端
iMonster32 分钟前
React 组件的组合模式之道 (Composition Pattern)
前端
呐呐呐呐呢40 分钟前
antd渐变色边框按钮
前端
元直数字电路验证1 小时前
Jakarta EE Web 聊天室技术梳理
前端
wadesir1 小时前
Nginx配置文件CPU优化(从零开始提升Web服务器性能)
服务器·前端·nginx
牧码岛1 小时前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端
灵犀坠1 小时前
前端面试八股复习心得
开发语言·前端·javascript
9***Y481 小时前
前端动画性能优化
前端
网络点点滴1 小时前
Vue3嵌套路由
前端·javascript·vue.js
牧码岛1 小时前
Web前端之Vue+Element打印时输入值没有及时更新dom的问题
前端·javascript·html·web·web前端