简单的翻译小工具
🛗

简单的翻译小工具

Property
notion image
成品差不多是下面这样,使用的方式是,Ctrl+c复制需要翻译的内容,按Alt+D进行翻译,窗口会全程置顶。如果你希望运行之后,没有黑漆漆的CMD窗口的话,将py后缀改为pyw就好。
以Python3.9的文档界面一段话作为演示,可以看到,去掉了换行看起来还行。对文本主要进行了多余空格的替换,以及去掉换行,连接因为一行放不下而在文献中常常出现的“-”连接符。

起因

是这样的,因为知云崩溃到直接无法打开,加上不知道是不是开了太多VPN(公司的,别多想),导致翻译的速度实在拉跨。没办法,想起来大四的选修课用过百度API-OCR接口,翻译图片上的文字。心想,自己申请一个百度的文本翻译API,自用岂不是很爽。
想到Python也可以建立GUI界面,而且还算是比较容易上手的,就直接开干。

翻译部分

API申请的话,可以看看Bob这个软件文档提供的申请步骤,我就是参考这个申请的翻译API。说到这个,就是因为换了Windows,Bob用不了,它只有macOS端。如果是用macOS的同学,我血书推荐Bob。
扯远了,直接看百度官方提供的调用代码,稍微改改之后就是下面这样了。
    def translate(text='Test successed!', fromLang='auto', toLang='zh', appID='', secretKey=''):

        # 创建专有的API链接
        httpClient = None
        myUrl = '/api/trans/vip/translate'
        salt = random.randint(32768, 65536)
        sign = appID + text + str(salt) + secretKey
        md5 = hashlib.md5()
        md5.update(sign.encode("utf-8"))
        sign = md5.hexdigest()
        myUrl = myUrl+'?appid=' + appID + '&q=' + parse.quote(text) + '&from=' + fromLang + '&to=' + toLang+'&salt=' + str(salt) + '&sign=' + sign

        try:
            # 客户端连接
            httpClient = http.client.HTTPConnection('api.fanyi.baidu.com')
            httpClient.request('GET', myUrl)
            response = httpClient.getresponse()

            #转码
            html = response.read().decode('utf-8')
            html = json.loads(html)
            dst = html["trans_result"][0]["dst"]

            # 打印输出翻译的内容
            print("Results: " + dst)
            return dst

        except Exception as e:

            # 打印错误信息
            print(e)
            return None

        finally:

            # 关闭API连接
            if httpClient:
                httpClient.close()

因为我是将它封装到类里面了,所以这里定义了一个函数。各位用的时候,只要填入自己的appID和secretKey就可以了。

界面部分

界面因为没什么需求,加上对界面这部分也确实不了解。唯二写过的带界面的桌面软件,也就是课设的VisualBasic,跟毕业设计用的Matlab了。
所以界面就用了4个QLabel空间,设置了一下位置跟文字大小之后,差不多就是你们之前看到的样式了。
class shawnWindow(QDialog):
    sig_keyhot = pyqtSignal(str)
    def __init__(self):
        super(shawnWindow, self).__init__()

        # 初始化状态
        self.windowOnTop = True
        self.setWindowFlags(Qt.WindowStaysOnTopHint)


        # 设置标题
        self.setWindowTitle('Shawn')
        font = QFont()
        font.setFamily("")
        font.setPointSize(12)

        # 创建 4 个 Label
        nameLb1 = QLabel('原文:', self)
        self.nameLb2 = QLabel(None, self)
        nameLb3 = QLabel('译文:', self)
        self.nameLb4 = QLabel(None, self)
        self.nameLb2.setFont(font)
        self.nameLb4.setFont(font)

        # 主要布局
        mainLayout = QGridLayout(self)
        mainLayout.addWidget(nameLb1, 0, 0)
        mainLayout.addWidget(self.nameLb2, 1, 0)
        mainLayout.addWidget(nameLb3, 2, 0)
        mainLayout.addWidget(self.nameLb4, 3, 0)
        mainLayout.setColumnMinimumWidth(0, 500)
        mainLayout.setRowMinimumHeight(0, 50)
        mainLayout.setRowMinimumHeight(1, 200)
        mainLayout.setRowMinimumHeight(2, 50)
        mainLayout.setRowMinimumHeight(3, 200)
        self.nameLb2.setWordWrap(True)
        self.nameLb4.setWordWrap(True)
        self.setWindowIcon(QIcon("logo.ico"))

键盘监听部分

因为不想加一个按钮,纯键盘操作是最好的,所以直接监听键盘了,我设置的快捷键是 Alt + D 操作,理论上直接设置为 Ctrl + C 为快捷键是最好的,因为这样的话,可以复制完立马翻译。
说到这个,是因为不会获取鼠标选中的内容,所以曲线救国,先复制,再读取剪切板。这样的话,如果将翻译的监听快捷键设置为 Ctrl + C 的话,会使得先执行翻译,后执行复制,每次翻译的内容都是前面剪贴板的内容。因此,就暂时这么设置为 Alt + D 了。

        # 设置自定义热键响应函数
        self.sig_keyhot.connect(self.hotKeyPressEvent)

        # 初始化热键
        self.hk_start = SystemHotkey()

        # 绑定快捷键和对应的信号发送函数
        self.hk_start.register(('alt','d'), callback = lambda x: self.send_key_event("start"))

    # 热键处理函数
    def hotKeyPressEvent(self, event) -> None:
        copyFromClipBoard = pyperclip.paste()
        copyFromClipBoard = copyFromClipBoard.replace('-\\n', ' ').replace('-\\r', ' ').replace('\\n', ' ').replace('\\r', ' ')
        copyFromClipBoard = re.sub(' +', ' ', copyFromClipBoard)
        translateFormAPI = self.translate(text = copyFromClipBoard)
        self.setLable(copyFromClipBoard, translateFormAPI)

    # 热键信号发送函数(将外部信号,转化成qt信号)
    def send_key_event(self,i_str):
        self.sig_keyhot.emit(i_str)

    # 设置翻译
    def setLable(self, copyFromClipBoard, translateFormAPI):
        self.nameLb2.setText(copyFromClipBoard)
        self.nameLb4.setText(translateFormAPI)

什么BUG?

暂时用着挺好的,没什么问题。就是太简陋了,以及API其实反应也没有我想的那么快,只不过专属的API接口确实不错就是了。
希望后面会有时间折腾一下,OCR,也就是截图翻译识别文本。
还有就是,没有用到多线程,这个在后面折腾一个压缩图片的工具时学了下,可惜这里没用到。