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

背景

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

效果

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

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

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

插件基础

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

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

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

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

原理

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

开撸

新建项目

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

创建manifest.json文件

  • google插件必须文件

manifest.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

console.log('浏览器脚本translate.js文件')

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

{
   "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内容

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

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

// 监听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文件

// 两个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的增删改查

原文链接:https://juejin.cn/post/7353561676090490895 作者:开荒人

(0)
上一篇 2024年4月6日 下午5:07
下一篇 2024年4月7日 上午10:00

相关推荐

发表回复

登录后才能评论