当前位置:   article > 正文

《快速掌握PyQt5》第二十九章 国际化_pyqt combobox.currenttextchanged

pyqt combobox.currenttextchanged

第二十九章 国际化

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文件内容如下:

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'change_lang.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.11.2
  5. #
  6. # WARNING! All changes made in this file will be lost!
  7. from PyQt5 import QtCore, QtGui, QtWidgets
  8. class Ui_Form(object):
  9. def setupUi(self, Form):
  10. Form.setObjectName("Form")
  11. Form.resize(120, 130)
  12. self.gridLayout_2 = QtWidgets.QGridLayout(Form)
  13. self.gridLayout_2.setObjectName("gridLayout_2")
  14. self.gridLayout = QtWidgets.QGridLayout()
  15. self.gridLayout.setObjectName("gridLayout")
  16. self.comboBox = QtWidgets.QComboBox(Form)
  17. self.comboBox.setObjectName("comboBox")
  18. self.comboBox.addItem("")
  19. self.comboBox.addItem("")
  20. self.comboBox.addItem("")
  21. self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 1)
  22. self.pushButton = QtWidgets.QPushButton(Form)
  23. self.pushButton.setObjectName("pushButton")
  24. self.gridLayout.addWidget(self.pushButton, 1, 0, 1, 1)
  25. self.label = QtWidgets.QLabel(Form)
  26. self.label.setObjectName("label")
  27. self.gridLayout.addWidget(self.label, 2, 0, 1, 1)
  28. self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
  29. self.retranslateUi(Form)
  30. QtCore.QMetaObject.connectSlotsByName(Form)
  31. def retranslateUi(self, Form):
  32. _translate = QtCore.QCoreApplication.translate
  33. Form.setWindowTitle(_translate("Form", "Form"))
  34. self.comboBox.setItemText(0, _translate("Form", "English"))
  35. self.comboBox.setItemText(1, _translate("Form", "中文"))
  36. self.comboBox.setItemText(2, _translate("Form", "français"))
  37. self.pushButton.setText(_translate("Form", "Start"))
  38. 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翻译文件并实现语言切换功能

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

  1. import sys
  2. from my_ui import Ui_Form
  3. from PyQt5.QtCore import QTranslator
  4. from PyQt5.QtWidgets import QApplication, QWidget
  5. class Demo(QWidget, Ui_Form):
  6. def __init__(self):
  7. super(Demo, self).__init__()
  8. self.setupUi(self)
  9. self.trans = QTranslator(self) # 1
  10. self.comboBox.currentTextChanged.connect(self.change_func) # 2
  11. def change_func(self): # 3
  12. if self.comboBox.currentText() == '中文':
  13. self.trans.load('eng-chs')
  14. _app = QApplication.instance()
  15. _app.installTranslator(self.trans)
  16. self.retranslateUi(self)
  17. elif self.comboBox.currentText() == 'français':
  18. self.trans.load('eng-fr')
  19. _app = QApplication.instance()
  20. _app.installTranslator(self.trans)
  21. self.retranslateUi(self)
  22. else:
  23. _app = QApplication.instance()
  24. _app.removeTranslator(self.trans)
  25. self.retranslateUi(self)
  26. if __name__ == '__main__':
  27. app = QApplication(sys.argv)
  28. demo = Demo()
  29. demo.show()
  30. 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翻译文件了):

  1. import sys
  2. from PyQt5.QtCore import Qt, QTranslator, QEvent
  3. from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QComboBox, QVBoxLayout
  4. class Demo(QWidget):
  5. def __init__(self):
  6. super(Demo, self).__init__()
  7. self.button = QPushButton('Start', self)
  8. self.label = QLabel('Hello, World', self)
  9. self.label.setAlignment(Qt.AlignCenter)
  10. self.combo = QComboBox(self)
  11. self.combo.addItem('English')
  12. self.combo.addItem('中文')
  13. self.combo.addItem('français')
  14. self.combo.currentTextChanged.connect(self.change_func)
  15. self.trans = QTranslator(self)
  16. self.v_layout = QVBoxLayout()
  17. self.v_layout.addWidget(self.combo)
  18. self.v_layout.addWidget(self.button)
  19. self.v_layout.addWidget(self.label)
  20. self.setLayout(self.v_layout)
  21. def change_func(self):
  22. print(self.combo.currentText())
  23. if self.combo.currentText() == '中文':
  24. self.trans.load('eng-chs')
  25. _app = QApplication.instance()
  26. _app.installTranslator(self.trans)
  27. elif self.combo.currentText() == 'français':
  28. self.trans.load('eng-fr')
  29. _app = QApplication.instance()
  30. _app.installTranslator(self.trans)
  31. else:
  32. _app = QApplication.instance()
  33. _app.removeTranslator(self.trans)
  34. def retranslateUi(self): # 1
  35. self.button.setText(QApplication.translate('Demo', 'Start'))
  36. self.label.setText(QApplication.translate('Demo', 'Hello, World'))
  37. def changeEvent(self, event): # 2
  38. if event.type() == QEvent.LanguageChange:
  39. self.retranslateUi()
  40. if __name__ == '__main__':
  41. app = QApplication(sys.argv)
  42. demo = Demo()
  43. demo.show()
  44. sys.exit(app.exec_())

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

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

运行截图跟之前一样的。

29.6 非动态切换

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

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

  1. import sys
  2. from PyQt5.QtCore import Qt, QTranslator
  3. from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
  4. class Demo(QWidget):
  5. def __init__(self):
  6. super(Demo, self).__init__()
  7. self.button = QPushButton(self.tr('Start'), self) # 1
  8. self.label = QLabel(self.tr('Hello, World'), self)
  9. self.label.setAlignment(Qt.AlignCenter)
  10. self.v_layout = QVBoxLayout()
  11. self.v_layout.addWidget(self.button)
  12. self.v_layout.addWidget(self.label)
  13. self.setLayout(self.v_layout)
  14. if __name__ == '__main__':
  15. app = QApplication(sys.argv)
  16. trans = QTranslator() # 2
  17. trans.load('eng-chs')
  18. app.installTranslator(trans)
  19. demo = Demo()
  20. demo.show()
  21. sys.exit(app.exec_())

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

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

运行截图如下:

29.7 小结

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

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

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

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

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/219759
推荐阅读
相关标签
  

闽ICP备14008679号