赞
踩
《快速掌握PyQt5》专栏已整理成书出版,书名为《PyQt编程快速上手》,详情请见该链接。感谢大家一直以来的支持!祝大家PyQt用得越来越顺!
程序界面如果只能显示一种语言的话,那以后怎么能走向国际呢~所以这章就来帮助大家了解下怎么给程序添加其他语种。
笔者发现,为了实现程序动态切换语种的功能,大部分人目前是通过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. 通常我们编写国际化程序的步骤为:
欢迎关注我的微信公众号,发现更多有趣内容:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。