29.1 设计好界面
29.2 创建ts文件
29.3 使用Qt Linguist
29.4 在程序中导入qm翻译文件并实现语言切换功能
29.5 不借助Qt Designer来实现语言动态切换
29.6 非动态切换
29.7 小结
程序界面如果只能显示一种语言的话,那以后怎么能走向国际呢~所以这章就来帮助大家了解下怎么给程序添加其他语种。
笔者发现,为了实现程序动态切换语种的功能,大部分人目前是通过Qt Designer完成界面,并在逻辑代码中调用retranslateUi()方法来实现界面更新,从而达到动态切换语种的目的(许多人也认为这是唯一方法)。但是有部分小伙伴不喜欢用Qt Designer,并想能不能不借助Qt Designer也可以直接实现语言的动态切换以及界面更新?答案是可以的。
笔者接下来会把两种方法都给讲解掉,先来示范下涉及到qt designer的方法:
我们先使用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,这些都是一个程序中可以翻译的文本。
界面完成好后我们就需要通过命令行来获取到翻译源文件(ts是translation source的简称),步骤如下:
1.首先我们打开命令行工具,并进入到项目目录下:
2. 输入pylupdate5 test.py -ts eng-chs.ts
这行命令的意思是将test.py程序代码中要翻译的文本全部输出到eng-chs.ts文件中。ts文件本质上就是一个xml文件。
运行完后项目目录中就会多出一个eng-chs.ts文件了。
翻译是在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文件。这两个文件就是我们需要在程序中进行载入的:
我们接下来进行逻辑代码的编写:
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()进行界面更新操作。
运行截图如下,初始状态:
选择中文:
选择法语:
虽然可以不用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()方法来更新界面语言。
运行截图跟之前一样的。
有些小伙伴可能不需要在程序中实现动态切换,只需要在程序一开始运行就换成另一种语言就行了,之后没必要切换。
那这样就更简单啦,请看下方代码:
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变量安装个翻译器就可以了。
运行截图如下:
1. 本章我们介绍了新的软件Qt Linguist,文本翻译在这个软件中进行。
2. 通常我们编写国际化程序的步骤为:
----------------------------------------------------------------------
喜欢的小伙伴可以加入这个Python QQ交流群一起学习:820934083