《快速掌握PyQt5》第二十九章 国际化

第二十九章 国际化

29.1 设计好界面

29.2 创建ts文件

29.3 使用Qt Linguist

29.4 在程序中导入qm翻译文件并实现语言切换功能

29.5 不借助Qt Designer来实现语言动态切换

29.6 非动态切换

29.7 小结


《快速掌握PyQt5》专栏已整理成书出版,书名为《PyQt编程快速上手》,详情请见该链接。感谢大家一直以来的支持!祝大家PyQt用得越来越顺!

程序界面如果只能显示一种语言的话,那以后怎么能走向国际呢~所以这章就来帮助大家了解下怎么给程序添加其他语种。

笔者发现,为了实现程序动态切换语种的功能,大部分人目前是通过Qt Designer完成界面,并在逻辑代码中调用retranslateUi()方法来实现界面更新,从而达到动态切换语种的目的(许多人也认为这是唯一方法)。但是有部分小伙伴不喜欢用Qt Designer,并想能不能不借助Qt Designer也可以直接实现语言的动态切换以及界面更新?答案是可以的。

笔者接下来会把两种方法都给讲解掉,先来示范下涉及到qt designer的方法:

29.1 设计好界面

我们先使用Qt Designer设计好界面:

我们就放入一个QComboBox控件、一个QPushButton控件以及一个QLabel控件。将文本设置好,QComboBox中包含三项,分别是:English,中文,français

也就是说当我们选择QComboBox中不同项时,界面的文本翻译会随之变化,这就是该程序要演示的效果。笔者设计好界面后,将其保存到了桌面的example文件夹中,UI文件命名为change_lang.ui。

接下来使用pyuic5命令将UI文件转换成py文件:

打开后的py文件内容如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'change_lang.ui'
#
# Created by: PyQt5 UI code generator 5.11.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(120, 130)
        self.gridLayout_2 = QtWidgets.QGridLayout(Form)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.comboBox = QtWidgets.QComboBox(Form)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 1)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 1, 0, 1, 1)
        self.label = QtWidgets.QLabel(Form)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 2, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.comboBox.setItemText(0, _translate("Form", "English"))
        self.comboBox.setItemText(1, _translate("Form", "中文"))
        self.comboBox.setItemText(2, _translate("Form", "français"))
        self.pushButton.setText(_translate("Form", "Start"))
        self.label.setText(_translate("Form", "Hello, World"))

我们看下retranslateUi()方法中已经把所有的文本内容都列了出来,也就是说从Form到Hello, World,这些都是一个程序中可以翻译的文本。

29.2 创建ts文件

界面完成好后我们就需要通过命令行来获取到翻译源文件(ts是translation source的简称),步骤如下:

1.首先我们打开命令行工具,并进入到项目目录下:

2. 输入pylupdate5 test.py -ts eng-chs.ts

这行命令的意思是将test.py程序代码中要翻译的文本全部输出到eng-chs.ts文件中。ts文件本质上就是一个xml文件。

运行完后项目目录中就会多出一个eng-chs.ts文件了。

29.3 使用Qt Linguist

翻译是在Qt Linguist软件中进行的,该软件跟Qt Assistant和Qt Designer在同一个目录下。

我们打开Qt Linguist,点击左上角的文件夹图标,找到我们的eng-chs.ts文件并打开,之后屏幕中会出现一个语言和地区设置弹框:

上面程序的文本为英语,所以源语言为英语,要翻译成中文和法语,所以目标语言为中文和法语。

一个个来,我们先翻译成中文,所以可如下设置:

点击确定后显示如下,现在来介绍下四个标签所指的窗口:

1. 上下文窗口:其中每个上下文中都包含一个或多个要翻译的源文,从这里我们看出Form上下文中包含6个源文。

2. 源文窗口:显示要翻译的源文。

3. 源码窗口:显示代码。

4. 翻译窗口:翻译在这里进行。一共有两个输入框,上面的输入框用于输入翻译后的文本,下面的用于输入译文注释(可以帮助修改或审核人员更好地理解翻译)。

5. 词组和猜测窗口:如果从外部导入词汇的话,这里的窗口可以自动显示可能的翻译结果,从而帮助翻译人员更快速地翻译文本。

6. 警告窗口:用于显示翻译时出现的错误警告。

我们接下来将源文翻译好,如果确保翻译无误的话,可以点击红框中的打勾图标(QComboBox中三个选项我们就是不必翻译的,窗口标题Form我们也就不翻了,主要就是翻译用来演示用的Start和Hello, World):

中文的翻译已经好了,我们接下来重复29.2创建ts文件步骤,生成一个eng-fr.ts文件并用Qt Linguist打开,进行语言和地区设置:

点击OK后我们发现在翻译窗口多了两个用于输入法语的文本框:

同样我们将法语译文输入进去,确保没问题后,点击上方的绿勾,最后我们点击File菜单中的Release All进行发布,之后会在项目目录中生成一个eng-chs.qm文件和一个eng-fr.qm文件。这两个文件就是我们需要在程序中进行载入的:

29.4 在程序中导入qm翻译文件并实现语言切换功能

我们接下来进行逻辑代码的编写:

import sys
from my_ui import Ui_Form
from PyQt5.QtCore import QTranslator
from PyQt5.QtWidgets import QApplication, QWidget


class Demo(QWidget, Ui_Form):
    def __init__(self):
        super(Demo, self).__init__()
        self.setupUi(self)
        self.trans = QTranslator(self)                              # 1
        self.comboBox.currentTextChanged.connect(self.change_func)  # 2

    def change_func(self):                                          # 3
        if self.comboBox.currentText() == '中文':
            self.trans.load('eng-chs')
            _app = QApplication.instance()
            _app.installTranslator(self.trans)
            self.retranslateUi(self)
        elif self.comboBox.currentText() == 'français':
            self.trans.load('eng-fr')
            _app = QApplication.instance()
            _app.installTranslator(self.trans)
            self.retranslateUi(self)
        else:
            _app = QApplication.instance()
            _app.removeTranslator(self.trans)
            self.retranslateUi(self)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1. 首先我们需要实例化一个翻译器,之后会通过该翻译器载入qm翻译文件;

2. 给QComboBox控件进行信号和槽的连接,每次文本发生变化,那界面语言就会变成相应的文本选项;

3. 在槽函数中我们进行判断,如果选择中文的话,我们就用翻译器trans的load()方法载入eng-chs.qm文件(.qm可省略)。既然改语言,我们肯定是要改变整个程序界面的语言,那我们就需要获得一个全局实例来操控整个程序。这里通过QApplication.instance()方法即可获得全局实例。接着我们再调用installTranslator()方法并传入翻译器。最后调用retranslateUi()方法来更新界面。

如果选择法语的话,代码同理。若再次回到英文选项,那我们只需要调用removeTranslator()方法传入当前的翻译器即可进行删除(不需要翻译了),接着调用retranslateUi()进行界面更新操作。

运行截图如下,初始状态:

选择中文:

选择法语:

29.5 不借助Qt Designer来实现语言动态切换

虽然可以不用Qt Designer,但是我们还是要用到类似的技术,也就是需要自己来编写一个retranslateUi()方法。

除了这点之外,我们还需要重实现changeEvent()事件函数。每当程序界面语言发生变化时,触发事件函数,在其中调用retranslateUi()方法来完成界面更新。

请看下方代码(笔者这里就不再重复讲述如何获取到qm翻译文件了):

import sys
from PyQt5.QtCore import Qt, QTranslator, QEvent
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QComboBox, QVBoxLayout


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton('Start', self)
        self.label = QLabel('Hello, World', self)
        self.label.setAlignment(Qt.AlignCenter)

        self.combo = QComboBox(self)
        self.combo.addItem('English')
        self.combo.addItem('中文')
        self.combo.addItem('français')
        self.combo.currentTextChanged.connect(self.change_func)

        self.trans = QTranslator(self)

        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.combo)
        self.v_layout.addWidget(self.button)
        self.v_layout.addWidget(self.label)
        self.setLayout(self.v_layout)

    def change_func(self):
        print(self.combo.currentText())
        if self.combo.currentText() == '中文':
            self.trans.load('eng-chs')
            _app = QApplication.instance()
            _app.installTranslator(self.trans)

        elif self.combo.currentText() == 'français':
            self.trans.load('eng-fr')
            _app = QApplication.instance()
            _app.installTranslator(self.trans)

        else:
            _app = QApplication.instance()
            _app.removeTranslator(self.trans)

    def retranslateUi(self):        # 1
        self.button.setText(QApplication.translate('Demo', 'Start'))
        self.label.setText(QApplication.translate('Demo', 'Hello, World'))

    def changeEvent(self, event):   # 2
        if event.type() == QEvent.LanguageChange:
            self.retranslateUi()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1. 实现retranslateUi()方法,在其中我们往QApplication.translate()方法中传入翻译的上下文‘Demo’以及要翻译的文本‘Start’;

2. 实现事件函数changeEvent(),每当程序触发语言变换事件时,都会调用retranslate()方法来更新界面语言。

运行截图跟之前一样的。

29.6 非动态切换

有些小伙伴可能不需要在程序中实现动态切换,只需要在程序一开始运行就换成另一种语言就行了,之后没必要切换。

那这样就更简单啦,请看下方代码:

import sys
from PyQt5.QtCore import Qt, QTranslator
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton(self.tr('Start'), self)   # 1
        self.label = QLabel(self.tr('Hello, World'), self)
        self.label.setAlignment(Qt.AlignCenter)

        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.button)
        self.v_layout.addWidget(self.label)
        self.setLayout(self.v_layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    trans = QTranslator()               # 2
    trans.load('eng-chs')
    app.installTranslator(trans)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1. 给要翻译的文本包上tr()方法;

2. 接着我们要做的就是在程序入口处给app变量安装个翻译器就可以了。

运行截图如下:

29.7 小结

1. 本章我们介绍了新的软件Qt Linguist,文本翻译在这个软件中进行。

2. 通常我们编写国际化程序的步骤为:

  • 编写程序主体;
  • 制作ts文件;
  • 使用Qt Linguist进行翻译;
  • 转化成qm文件并在程序中导入;
  • 完善程序;

欢迎关注我的微信公众号,发现更多有趣内容:

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

la_vie_est_belle

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值