使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)

使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)

前言:

这是 qt for python 的语言国际化,基于 UI 的,python 也有自身的语言国际化,两者是不同的。

先来看最终效果:

前期准备:

这次创建一个 main window 在 menu bar 加一个 language 的 menu:

我们还要对 action 进行一些设置,如下:

生成 .py 文件:

生成代码:

 1 # -*- coding: utf-8 -*-
 2
 3 # Form implementation generated from reading ui file ‘.\internationalizationTest.ui‘
 4 #
 5 # Created: Sun Nov 18 02:16:18 2018
 6 #      by: pyside-uic 0.2.15 running on PySide 1.2.4
 7 #
 8 # WARNING! All changes made in this file will be lost!
 9
10 from PySide import QtCore, QtGui
11
12 class Ui_MainWindow(object):
13     def setupUi(self, MainWindow):
14         MainWindow.setObjectName("MainWindow")
15         MainWindow.resize(320, 248)
16         self.centralwidget = QtGui.QWidget(MainWindow)
17         self.centralwidget.setObjectName("centralwidget")
18         MainWindow.setCentralWidget(self.centralwidget)
19         self.menubar = QtGui.QMenuBar(MainWindow)
20         self.menubar.setGeometry(QtCore.QRect(0, 0, 320, 26))
21         self.menubar.setObjectName("menubar")
22         self.menuLanguage = QtGui.QMenu(self.menubar)
23         self.menuLanguage.setObjectName("menuLanguage")
24         MainWindow.setMenuBar(self.menubar)
25         self.actionEnglish = QtGui.QAction(MainWindow)
26         self.actionEnglish.setObjectName("actionEnglish")
27         self.actionChinese = QtGui.QAction(MainWindow)
28         self.actionChinese.setObjectName("actionChinese")
29         self.menuLanguage.addAction(self.actionEnglish)
30         self.menuLanguage.addAction(self.actionChinese)
31         self.menubar.addAction(self.menuLanguage.menuAction())
32
33         self.retranslateUi(MainWindow)
34         QtCore.QMetaObject.connectSlotsByName(MainWindow)
35
36     def retranslateUi(self, MainWindow):
37         MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
38         self.menuLanguage.setTitle(QtGui.QApplication.translate("MainWindow", "Language", None, QtGui.QApplication.UnicodeUTF8))
39         self.actionEnglish.setText(QtGui.QApplication.translate("MainWindow", "English", None, QtGui.QApplication.UnicodeUTF8))
40         self.actionChinese.setText(QtGui.QApplication.translate("MainWindow", "Chinese", None, QtGui.QApplication.UnicodeUTF8))

internationalizationTest_ui_pyside.py

其实 pyside 有 uic 模块可以直接load .ui 文件获得 ui 类,但是没办法实现语言国际化,或许通过另外的方法可以。

1. 使用 lupdate 从 .py 生成 .ts

安装了 PySide 或者 PySide2 后,就会有 lupdate 工具,如果不知道在哪,就在 python 的安装目录下搜 lupdate ,PySide 和 PyQt 的前缀都不一样:

这里我们使用第一个 pyside-lupdate.exe,这个参数会简单,lupdate 的参数相对复杂,在 cmd 中查看 pyside-lupdate.exe 的帮助:

可以看到 Usage,有两种用法,这里我们使用第一种project-file,方便以后反复修改,我们新建一个文件 translation_en_to_zh_CN.pro, 内容语法如下:

SOURCES = internationalizationTest_ui_pyside.py

TRANSLATIONS = translation_en_to_zh_CN.ts

CODECFORTR = UTF-8

CODECFORSRC = UTF-8

SOURCES:从一个或者多个 .py 文件中提取需要翻译的文本,不同 .py 用空格隔开,例如:

SOURCES = internationalizationTest_ui_pyside.py otherUI.py     

TRANSLATIONS:指定生成的 ts 文件名,注意文件名,因为我们不单单会有一种语言的翻译,例如如果我们还需要中文繁体,那么就可以新建另外的一个 project 文件:translation_en_to_zh_TW.pro,关于各国语言的简写,请参考:https://www.cnblogs.com/ibingshan/p/9871211.html

CODECFORTR 和 CODECFORSRC:指定一些编码,可以有可以没有。

下面我们来生成 .ts 文件:

这样就生成了 translation_en_to_zh_CN.ts:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!DOCTYPE TS><TS version="1.1">
 3 <context>
 4     <name>MainWindow</name>
 5     <message>
 6         <location filename="internationalizationTest_ui_pyside.py" line="37"/>
 7         <source>MainWindow</source>
 8         <translation type="unfinished"></translation>
 9     </message>
10     <message>
11         <location filename="internationalizationTest_ui_pyside.py" line="38"/>
12         <source>Language</source>
13         <translation type="unfinished"></translation>
14     </message>
15     <message>
16         <location filename="internationalizationTest_ui_pyside.py" line="39"/>
17         <source>English</source>
18         <translation type="unfinished"></translation>
19     </message>
20     <message>
21         <location filename="internationalizationTest_ui_pyside.py" line="40"/>
22         <source>Chinese</source>
23         <translation type="unfinished"></translation>
24     </message>
25 </context>
26 </TS>

那么 lupdate 是根据什么来决定那些文本需要被翻译的呢,看 internationalizationTest_ui_pyside.py 中的

def retranslateUi(self, MainWindow):
  MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
  self.menuLanguage.setTitle(QtGui.QApplication.translate("MainWindow", "Language", None, QtGui.QApplication.UnicodeUTF8))
  self.actionEnglish.setText(QtGui.QApplication.translate("MainWindow", "English", None, QtGui.QApplication.UnicodeUTF8))
  self.actionChinese.setText(QtGui.QApplication.translate("MainWindow", "Chinese", None, QtGui.QApplication.UnicodeUTF8))

可以看到并不是直接的 setText(‘text‘) ,而是有 QtGui.QApplication.translate ,lupdate 就是根据这个来决定的,注意 PySide 和 PySide2 的 QtGui.QApplication.translate 后面的参数有所不一样。

注意:QtGui.QApplication.translate 的前面连个参数是 str 类型,如果需要用参数来传递,最好转换成 str 例如 str(myStr)。

2. 使用 qt linguist 打开 .ts 文件来翻译成各语言版本

打开 qt linguist 了

file -> open,找到 translation_en_to_zh_CN.ts 并且打开,这是会弹出一个指定源语言和目标语言的选择窗口,我们可以在这里设置,也可以以后发布的时候通过 Edit -> Translation File Setting 打开这个窗口:

Source language 我们选择英语,其实源语言决定你使用 qt designer 的时候 widgets 的语言:

打开后如下:

这个使用是非常容易上手的,而且不用担心 lupdate 重新生成 .ts 后会把之前的翻译覆盖掉,事实上 lupdate 会保留已经翻译好的信息,而且会增加你添加的文本,或者你的 UI 中删除了,lupdate都能识别。

点击前面的问号,标记一下你已经翻译好了:

3. ts 发布 .pm

PySide 翻译的时候并不是用 .ts 文件的,需要把 .ts 文件发布为 .pm 文件。

我们可以使用 lrelease.exe 来发布:

在 linguist 中保存好 .ts 文件后:

也可以在 linguist 中直接发布:

这时候就会生成 translation_en_to_zh_CN.qm,如果我们用文本编辑器打开,里面都是乱码。

4.继承 internationalizationTest_ui_pyside.py 中的类

新建一个 internationalizationTest.py:

 1 # -*- coding: utf-8 -*-
 2
 3 import os
 4 import sys
 5
 6 import internationalizationTest_ui_pyside as ui
 7
 8 from PySide import QtGui
 9 from PySide import QtGui as QtWidgets
10 from PySide import QtCore
11
12 TRANSLATOR = QtCore.QTranslator()
13
14 #TRANSLATION_DIR = os.path.join(os.path.dirname(__file__), ‘translations‘)
15
16 class MainWindow(QtWidgets.QMainWindow, ui.Ui_MainWindow):
17     def __init__(self, parent = None):
18         super(MainWindow, self).__init__(parent)
19         self.setupUi(self)
20
21         self.languageActionGroup = QtWidgets.QActionGroup(self.menuLanguage)                    #这里把语言actions放到一个组里面,使得每次只能选择一个
22         self.languageActionGroup.addAction(self.actionEnglish)
23         self.languageActionGroup.addAction(self.actionChinese)
24         self.languageActionGroup.triggered[QtWidgets.QAction].connect(self.on_language_changed) #连接 trigger 槽,on_language_changed(self, action)中的action是自动传递的别点击的action对象
25
26     def on_language_changed(self, action):
27         result = False                                              #为了debug TRANSLATOR 加载 pm 文件是否成功
28         if action == self.actionChinese:                            #通过action来判断哪个语言action被点击来选择不同的 pm 加载
29             result = TRANSLATOR.load(‘translation_en_to_zh_CN‘)     #注意,可以不需要 .pm 后缀
30             #TRANSLATOR.load(‘translation_en_to_zh_CN‘, directory = TRANSLATION_DIR)#这里是指定某个路径下的 pm
31         else:
32             TRANSLATOR.load(‘‘)                                     #如果加载失败,则会重置会第一个语言
33
34         print(result)                                               #打印加载结果
35         self.retranslateUi(self)                                    #在TRANSLATOR加载后,记得一定要执行 retranslateUi 或者其他自己定义的重新设置文本的方法。
36
37 def main():
38     app = QtWidgets.QApplication(sys.argv)
39
40     app.installTranslator(TRANSLATOR)   #非常重要的一步,为 app 安装 TRANSLATOR,如果不安装,是没有效果的
41
42     win = MainWindow()
43     win.show()
44     sys.exit(app.exec_())
45
46 if __name__ == "__main__":
47     main()

下面来看看效果:

5.在 maya 中实现

这次是在 maya2015 中实现,如果是 maya2017 以上,请自己修改一下代码,使得 pyside 和 pyside2 兼容

新建一个 internationalizationTest_maya.py:

 1 # -*- coding: utf-8 -*-
 2
 3 #from PySide import QtGui
 4 from PySide import QtGui as QtWidgets       #这样可以使得 pyside 和 pyside2 基本兼容,而且可以不用额外的补丁,也就是说是以 pyside2 为基础的
 5 #import shiboken2 as shiboken               #如果是 maya2017 以上,可以这样。
 6 import shiboken
 7
 8 import internationalizationTest as ui
 9
10 import maya.OpenMayaUI as omui
11 def maya_main_window():
12     main_window_ptr = omui.MQtUtil.mainWindow()                             #获得maya主窗口的指针,主要是为了让插件界面设置它为父窗口
13     return shiboken.wrapInstance(long(main_window_ptr), QtWidgets.QWidget)  #把maya主窗口封装从QtGui对象
14
15 class MainWindow(ui.MainWindow):
16     def __init__(self, parent = None):
17         super(MainWindow, self).__init__(parent)
18
19 win = MainWindow(maya_main_window())
20 def main():
21     app = QtWidgets.QApplication.instance() #因为 maya 已经是启动的 app,所以这里是获得 app 的实例
22
23     app.installTranslator(ui.TRANSLATOR)    #安装 translator
24
25     global win
26     try:
27         win.close()
28     except:
29         pass
30     win.show()

因为是在maya中运行,所以 internationalizationTest.py 要改为如下,也就是 TRANSLATOR.load(‘translation_en_to_zh_CN‘, directory = TRANSLATION_DIR) ,要为 translation_en_to_zh_CN 指定一个路径,如果不指定,那么默认路径是 app 的路径下查找,但是maya的app路径并不在 internationalizationTest_maya.py 所在的路径:

 1 # -*- coding: utf-8 -*-
 2
 3 import os
 4 import sys
 5
 6 import internationalizationTest_ui_pyside as ui
 7
 8 from PySide import QtGui
 9 from PySide import QtGui as QtWidgets
10 from PySide import QtCore
11
12 TRANSLATOR = QtCore.QTranslator()
13
14 TRANSLATION_DIR = os.path.dirname(__file__)
15
16 class MainWindow(QtWidgets.QMainWindow, ui.Ui_MainWindow):
17     def __init__(self, parent = None):
18         super(MainWindow, self).__init__(parent)
19         self.setupUi(self)
20
21         self.languageActionGroup = QtWidgets.QActionGroup(self.menuLanguage)                    #这里把语言actions放到一个组里面,使得每次只能选择一个
22         self.languageActionGroup.addAction(self.actionEnglish)
23         self.languageActionGroup.addAction(self.actionChinese)
24         self.languageActionGroup.triggered[QtWidgets.QAction].connect(self.on_language_changed) #连接 trigger 槽,on_language_changed(self, action)中的action是自动传递的别点击的action对象
25
26     def on_language_changed(self, action):
27         result = False                                              #为了debug TRANSLATOR 加载 qm 文件是否成功
28         if action == self.actionChinese:                            #通过action来判断哪个语言action被点击来选择不同的 qm 加载
29             #result = TRANSLATOR.load(‘translation_en_to_zh_CN‘)     #注意,可以不需要 .qm 后缀
30             result = TRANSLATOR.load(‘translation_en_to_zh_CN‘, directory = TRANSLATION_DIR)#这里是指定某个路径下的 qm
31
32         else:
33             TRANSLATOR.load(‘‘)                                     #如果加载失败,则会重置会第一个语言
34
35         print(result)                                               #打印加载结果
36         self.retranslateUi(self)                                    #在TRANSLATOR加载后,记得一定要执行 retranslateUi 或者其他自己定义的重新设置文本的方法。
37
38 def main():
39     app = QtWidgets.QApplication(sys.argv)
40     print(app)
41     app.installTranslator(TRANSLATOR)   #非常重要的一步,为 app 安装 TRANSLATOR,如果不安装,是没有效果的
42
43     win = MainWindow()
44     win.show()
45     sys.exit(app.exec_())
46
47 if __name__ == "__main__":
48     main()

启动 maya,打开 Script Editor,在 python 栏输入:

import sys
sys.path.append(r‘E:\Works\Maya\Scripts\PySideTest‘) #把代码所在的路径添加到环境变量PATH中,这样可以import它们

import internationalizationTest_maya
reload(internationalizationTest_maya)
internationalizationTest_maya.main()

  注意:sys.path.append 的路径改为自己的路径

全选代码,ctrl+shift+enter 运行,效果如下:

总结:

qt 语言国际化实现基本思路:

  1. 创建一个 translator 对象:TRANSLATOR = QtCore.QTranslator()
  2. app对象安装 translator:app.installTranslator(TRANSLATOR)
  3. translator 加载 qm 文件:TRANSLATOR.load(‘translation_en_to_zh_CN‘, directory = TRANSLATION_DIR)
  4. UI 再次设置 widget 文本:self.retranslateUi(self)

至此,使用 PySide2 开发 Maya 插件系列已经完毕,希望对大家有所帮助。

回到总览使用 PySide2 开发 Maya 插件系列 总览

原文地址:https://www.cnblogs.com/ibingshan/p/9965139.html

时间: 2024-10-03 02:39:09

使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)的相关文章

使用 PySide2 开发 Maya 插件系列一:QT Designer 设计GUI, pyside-uic 把 .ui 文件转为 .py 文件

使用 PySide2 开发 Maya 插件系列一:QT Designer 设计GUI, pyside-uic 把 .ui 文件转为 .py 文件 前期准备: 安装 python:https://www.python.org/downloads/ 安装 PySide2:安装 python 后,在安装目录下有 /script 文件夹,里面有 pip.exe ,cmd执行:pip install PySide,pip install PySide2(注意: python2.x 对应 PySide,py

使用 PySide2 开发 Maya 插件系列二:继承 uic 转换出来的 py 文件中的类 Ui_Form

使用 PySide2 开发 Maya 插件系列二:继承 uic 转换出来的 py 文件中的类 Ui_Form 开发环境: Wing IDE 6.1 步骤1: 打开 Wing IDE,创建一个新的 project,保存这个 project 到某个路径下,把之前生产的 py 文件所在的文件夹添加到该 project 中,然后在文件夹下新建一个 py 文件,我这里命名为 PySideTest.py 图中 PySide2ToPySide.py 是一个 PySide2 兼容 PySide 的一个补丁代码,

数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量

当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产 品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架还是自主开发,都会面临一个在哪一层上实现sharding逻辑的问题,本文会对这一系 列的问题逐一进行分析和考量.本文原文连接: http://blog.csdn.net/bluishglc/article/details/7766508转载请注明出处! 一.sharding逻辑的实现层面 从

短信开发系列(三):短信接收引擎

短信开发系列目录: 短信开发系列(一):GSM手机短信开发初探短信开发系列(二):GSM手机短信开发之短信解码短信开发系列(三):短信接收引擎 之前写了短信接收处理的一些内容,今年事情实在太多了,就停顿了这么一大段的时间.接下来会继续完成相关的内容. 今天先写用之前写的短信类库的一个应用,短信接收引擎.可以用在处理一些短信的提醒:作为前面两篇文章的一个实战运用,可以作为一个多线程.委托和事件.串口等方面知识的一个综合运用. 先来分析一下整个程序的流程: - 启动线程 - 定时运行线程主函数 -

iOS开发UINavigation系列三——工具栏UIToolBar

iOS开发UINavigation系列三--工具栏UIToolBar iOS中除了UINavinationBar之外,还有工具栏UIToolBar可以供我们使用,工具栏和导航栏十分类似,只是功能更加简单,工具栏中也有UIBarButtonItem按钮,在前两篇博客中,对导航栏和导航项都进行的讨论,地址如下: UINavigationBar:http://my.oschina.net/u/2340880/blog/527706 UINavigationItem:http://my.oschina.

S5PV210开发系列三_简易Bootloader的实现

S5PV210开发系列三 简易Bootloader的实现 象棋小子          1048272975 Bootloader是嵌入式系统上电后第一段执行的代码.对于功能简单的处理器,可能并没有Bootloader的概念,但对于应用处理器,有不同的启动方式,不同的存储设备(Nand flash.sd/mmc.DDR2.SRAM等),不同的操作系统等,往往需要一个Bootloader先初始化CPU和相关的硬件,建立内存空间映射,把内核或应用程序加载到相应的内存执行位置,最后调用内核或应用程序,释

java web开发环境配置系列(三)安装eclipse

在今天,读书有时是件"麻烦"事.它需要你付出时间,付出精力,还要付出一份心境.--仅以<java web开发环境配置系列>来祭奠那逝去的--1.下载eclipse安装包,下载地址https://www.eclipse.org/downloads/,官方提供了几种工具平台,这里使用的是Eclipse Neon 2.下载后,以管理员身份安装安装包 1)选择适合自己开发方向的开发工具 2)选择后,进入下一步,配置自己的安装路径,并点击安装即可 3)安装好后,第一次打开eclips

J2EE开发实战基础系列一 HelloWorld

开始咱们的第一个程序,首先是配置环境,按照上一章所描述的方式下载开发工具,然后配置Java环境变量,给大家看下具体的结构: 环境变量配置OK的提示,如上图. Eclipse和Tomcat的文件目录位置,本系列采用的都是绿色版本,如上图. 启动Eclipse.exe,Workspace路径的配置,下面的复选框表示选中后就默认一直使用该工作空间,不选择每次启动都出出现该提示框,如上图. 在这里讲解下Workspace的概念,这里目录存储项目程序段的,假如你在别的目录创建一个Java的项目,那么在Wo

J2EE开发实战基础系列一 HelloWorld【转】

开始咱们的第一个程序,首先是配置环境,按照上一章所描述的方式下载开发工具,然后配置Java环境变量,给大家看下具体的结构: 环境变量配置OK的提示,如上图. Eclipse和Tomcat的文件目录位置,本系列采用的都是绿色版本,如上图. 启动Eclipse.exe,Workspace路径的配置,下面的复选框表示选中后就默认一直使用该工作空间,不选择每次启动都出出现该提示框,如上图. 在这里讲解下Workspace的概念,这里目录存储项目程序段的,假如你在别的目录创建一个Java的项目,那么在Wo