首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

自制PDF阅读器・翻译与朗读

之前我的 pdf 阅读器上使用的是浏览器的翻译插件,但是我现在突然想让阅读器本身自带翻译和朗读功能。

我们可以使用一下两款 golang package 来完成目标:

github.com/Conight/go-googletrans: 使用免费的 api 进行文本翻译;

github.com/hegedustibor/htgo-tts:  使用免费的 api 进行语言合成朗读;

我们可以先使用 go get 命令来安装它们。

导入包

我们先导入它们:

import (

"github.com/Conight/go-googletrans"

"github.com/hegedustibor/htgo-tts"

"github.com/hegedustibor/htgo-tts/voices"

)

实现对应的 handler 函数

1. 文本翻译

func translate_handler(w http.ResponseWriter, r *http.Request) {

body, err := io.ReadAll(r.Body)

if err != nil {

log.Println(err)

http.Error(w, "load request faild", http.StatusBadRequest)

return

}

var params SelectionParams

err = json.Unmarshal(body, &params)

if err != nil {

log.Println(err)

http.Error(w, "load request faild", http.StatusBadRequest)

return

}

log.Println(params)

t := translator.New()

result, err := t.Translate(params.Words, "auto", "zh-CN")

if err != nil {

log.Println(err)

http.Error(w, "translate faild", http.StatusInternalServerError)

return

}

fmt.Fprint(w, result.Text)

}

2. 语言合成朗读

func to_speech_handler(w http.ResponseWriter, r *http.Request) {

body, err := io.ReadAll(r.Body)

if err != nil {

log.Println(err)

http.Error(w, "load request faild", http.StatusBadRequest)

return

}

var params SelectionParams

err = json.Unmarshal(body, &params)

if err != nil {

log.Println(err)

http.Error(w, "load request faild", http.StatusBadRequest)

return

}

log.Println(params)

speech := htgotts.Speech{Folder: "audio", Language: voices.English}

err = speech.Speak(params.Words)

if err != nil {

log.Println(err)

http.Error(w, "convert to speech faild", http.StatusInternalServerError)

}

}

我们还需要为这两个函数指定路由:

http.HandleFunc("/translate", translate_handler)

http.HandleFunc("/to_speech", to_speech_handler)

重新定义右键菜单

我们需要通过前端代码重新定义右键菜单:

function create_context_menu() {

const contextMenu = document.createElement('div');

document.body.insertAdjacentElement('beforeEnd', contextMenu);

contextMenu.style.position = 'fixed';

contextMenu.hidden = true;

const itemTranslate = document.createElement('button');

contextMenu.appendChild(itemTranslate);

itemTranslate.innerText = 'Translate';

itemTranslate.onclick = async () => {

const origin = document.getSelection().toString();

const resp = await fetch('/translate', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

words: origin,

})

})

if (!resp.ok) {

return;

}

const text = await resp.text()

console.log(text);

alert(text);

}

const itemToSpeech = document.createElement('button');

contextMenu.appendChild(itemToSpeech);

itemToSpeech.innerText = 'To Speech';

itemToSpeech.onclick = async () => {

const origin = document.getSelection().toString();

const resp = await fetch('/to_speech', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

words: origin,

})

})

if (!resp.ok) {

return;

}

}

document.addEventListener('contextmenu', (event) => {

event.preventDefault();

contextMenu.style.left = event.clientX + 'px';

contextMenu.style.top = event.clientY + 'px';

contextMenu.hidden = false;

});

document.addEventListener('click', () => {

contextMenu.hidden = true;

});

}

在 HTML 文档加载完成的时候运行它:

window.onload = async () => {

const page_ix = (new URLSearchParams(location.search)).get('start') || 0;

await load_page('beforeEnd', page_ix);

await load_page('afterBegin', page_ix - 1);

load_more();

// 我们自定义的右键菜单

create_context_menu();

}

效果演示

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O-cHf95O7FbPaT0kJtShBXwQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券