PySide Qt tr() 不翻译,translate() 做 - 上下文错误?
PySide Qt tr() does not translate, translate() does - context wrong?
我想使用 QTranslator 来使用英文文本标签,并且仍然有显示德文标签的软件。
很遗憾,我的应用无法翻译,除非我指定了上下文。
以下静态函数实例化了一个 QApplication 并添加了所需的转换器。
第一次打印将 'Apple2' 正确翻译为 'Apfel2'。 Qt Linguist中的上下文也有上下文'app'。
第二个打印虽然没有翻译。 tr()
classes 中的调用(在同一个 python 文件中定义)也不翻译。
def load_application():
app = QApplication()
qt_translator = QTranslator()
qt_translator.load('qt_' + QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath))
app.installTranslator(qt_translator)
app_translator = QTranslator()
r = app_translator.load('i18n/' + QLocale.system().name())
app.installTranslator(app_translator)
print(app.translate('app', 'Apple2'))
print(app.tr('Apple'))
return app
编辑:
静态函数部分是正确的。应用程序的上下文是 QApplication。不过,这对 QMainWindow subclass 没有帮助。我相应地更新了代码。 pyside-lupdate 为 class 生成的上下文是 MainWindow:
查看
class MainWindow(QMainWindow):
add_model_widget = None
def __init__(self):
QMainWindow.__init__(self)
# Create menu bar
menu_bar = QMenuBar(self)
m_file = QMenu(self.tr('File'), menu_bar)
a_add_model = QAction(QIcon('add.png'), self.tr('Add Jewel'), self)
m_file.addAction(a_add_model)
menu_bar.addMenu(m_file)
self.setMenuBar(menu_bar)
def load_application():
app = QApplication()
app_translator = QTranslator()
app_translator.load(QLocale.system().name(), 'i18n')
app.installTranslator(app_translator)
return app
控制器
def initiate():
model.initiate_mongodb()
app = view.load_application()
main_window = view.MainWindow()
main_window.show()
sys.exit(app.exec_())
解法:
我的问题的解决方案是 QTranslator 没有任何父级。 QTranslator(app) 解决了我的问题。
这似乎是因为,与 Qt 不同,PySide/PyQt 在运行时确定上下文。
在您的示例中,上下文将(我认为)在运行时解析为 QApplication
,而 pyside/pyqt lupdate 工具会将其硬编码为 app
。这些工具只对源代码进行静态分析,所以我认为它们不够聪明,无法弄清楚正确的 class 应该是什么。
示例代码 应该 如果你这样做,但是:
class App(QtGui.QApplication):
def __init__(self):
super(App, self).__init__()
message = self.tr('Apple')
...
app = App()
...
print(app.tr('Apple'))
(显然您需要先更新翻译文件)。
编辑:
这是一个适合我的简化演示:
test.py:
import sys, os
from PySide import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
menu = self.menuBar().addMenu(self.tr('File'))
menu.addAction(self.tr('Hello World'))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator(app)
translator.load('i18n/tr_de', os.path.dirname(__file__))
app.installTranslator(translator)
window = MainWindow()
window.show()
sys.exit(app.exec_())
i18n/tr.pro:
SOURCES = ../test.py
TRANSLATIONS = tr_de.ts
i18n/tr_de.ts:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="1.1" language="de_DE">
<context>
<name>MainWindow</name>
<message>
<location filename="../test.py" line="7"/>
<source>File</source>
<translation>Datei</translation>
</message>
<message>
<location filename="../test.py" line="8"/>
<source>Hello World</source>
<translation>Hallo Welt</translation>
</message>
</context>
</TS>
命令输出:
$ pyside-lupdate -verbose -noobsolete i18n/tr.pro
Updating 'tr_de.ts'...
Found 2 source texts (2 new and 0 already existing)
$ lrelease-qt4 i18n/tr.pro
Updating './i18n/tr_de.qm'...
Generated 2 translation(s) (2 finished and 0 unfinished)
如果你像我一样来到这里,想了解如何使用 PySide 进行翻译。
使用 translate(),而不是 tr()
使用 tr()
的烦人之处在于,每次使用他建议的方法编辑源代码时,您都必须手动编辑生成的 .ts 文件,这种编辑会花费很多时间,尤其是在更新时你的 .ts 文件,因为它将所有 .tr() 调用放在 "Unknown context" 上下文中,你必须再次手动将所有翻译移回正确的上下文,这很快就会失控。
相反,有一个非常简单的解决方案。
我读了the official pyqt4-lupdate documentation,它说
The PyQt4 behaviour is unsatisfactory and may be changed in the
future. It is recommended that QCoreApplication.translate() be used in
preference to tr() (and trUtf8()). This is guaranteed to work with
current and future versions of PyQt4 and makes it much easier to share
message files between Python and C++ code. Below is the alternative
implementation of A that uses QCoreApplication.translate():
from QtCore import QCoreApplication
translate = QCoreApplication.translate
class A(QtCore.QObject):
def hello(self):
return translate("A", "Hello")
其中 "A" 是硬编码上下文,pyside-lupdate
将 找到。好多了!
我想使用 QTranslator 来使用英文文本标签,并且仍然有显示德文标签的软件。
很遗憾,我的应用无法翻译,除非我指定了上下文。 以下静态函数实例化了一个 QApplication 并添加了所需的转换器。
第一次打印将 'Apple2' 正确翻译为 'Apfel2'。 Qt Linguist中的上下文也有上下文'app'。
第二个打印虽然没有翻译。 tr()
classes 中的调用(在同一个 python 文件中定义)也不翻译。
def load_application():
app = QApplication()
qt_translator = QTranslator()
qt_translator.load('qt_' + QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath))
app.installTranslator(qt_translator)
app_translator = QTranslator()
r = app_translator.load('i18n/' + QLocale.system().name())
app.installTranslator(app_translator)
print(app.translate('app', 'Apple2'))
print(app.tr('Apple'))
return app
编辑:
静态函数部分是正确的。应用程序的上下文是 QApplication。不过,这对 QMainWindow subclass 没有帮助。我相应地更新了代码。 pyside-lupdate 为 class 生成的上下文是 MainWindow:
查看
class MainWindow(QMainWindow):
add_model_widget = None
def __init__(self):
QMainWindow.__init__(self)
# Create menu bar
menu_bar = QMenuBar(self)
m_file = QMenu(self.tr('File'), menu_bar)
a_add_model = QAction(QIcon('add.png'), self.tr('Add Jewel'), self)
m_file.addAction(a_add_model)
menu_bar.addMenu(m_file)
self.setMenuBar(menu_bar)
def load_application():
app = QApplication()
app_translator = QTranslator()
app_translator.load(QLocale.system().name(), 'i18n')
app.installTranslator(app_translator)
return app
控制器
def initiate():
model.initiate_mongodb()
app = view.load_application()
main_window = view.MainWindow()
main_window.show()
sys.exit(app.exec_())
解法: 我的问题的解决方案是 QTranslator 没有任何父级。 QTranslator(app) 解决了我的问题。
这似乎是因为,与 Qt 不同,PySide/PyQt 在运行时确定上下文。
在您的示例中,上下文将(我认为)在运行时解析为 QApplication
,而 pyside/pyqt lupdate 工具会将其硬编码为 app
。这些工具只对源代码进行静态分析,所以我认为它们不够聪明,无法弄清楚正确的 class 应该是什么。
示例代码 应该 如果你这样做,但是:
class App(QtGui.QApplication):
def __init__(self):
super(App, self).__init__()
message = self.tr('Apple')
...
app = App()
...
print(app.tr('Apple'))
(显然您需要先更新翻译文件)。
编辑:
这是一个适合我的简化演示:
test.py:
import sys, os
from PySide import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
menu = self.menuBar().addMenu(self.tr('File'))
menu.addAction(self.tr('Hello World'))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator(app)
translator.load('i18n/tr_de', os.path.dirname(__file__))
app.installTranslator(translator)
window = MainWindow()
window.show()
sys.exit(app.exec_())
i18n/tr.pro:
SOURCES = ../test.py
TRANSLATIONS = tr_de.ts
i18n/tr_de.ts:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="1.1" language="de_DE">
<context>
<name>MainWindow</name>
<message>
<location filename="../test.py" line="7"/>
<source>File</source>
<translation>Datei</translation>
</message>
<message>
<location filename="../test.py" line="8"/>
<source>Hello World</source>
<translation>Hallo Welt</translation>
</message>
</context>
</TS>
命令输出:
$ pyside-lupdate -verbose -noobsolete i18n/tr.pro
Updating 'tr_de.ts'...
Found 2 source texts (2 new and 0 already existing)
$ lrelease-qt4 i18n/tr.pro
Updating './i18n/tr_de.qm'...
Generated 2 translation(s) (2 finished and 0 unfinished)
如果你像我一样来到这里,想了解如何使用 PySide 进行翻译。
使用 translate(),而不是 tr()
使用 tr()
的烦人之处在于,每次使用他建议的方法编辑源代码时,您都必须手动编辑生成的 .ts 文件,这种编辑会花费很多时间,尤其是在更新时你的 .ts 文件,因为它将所有 .tr() 调用放在 "Unknown context" 上下文中,你必须再次手动将所有翻译移回正确的上下文,这很快就会失控。
相反,有一个非常简单的解决方案。
我读了the official pyqt4-lupdate documentation,它说
The PyQt4 behaviour is unsatisfactory and may be changed in the future. It is recommended that QCoreApplication.translate() be used in preference to tr() (and trUtf8()). This is guaranteed to work with current and future versions of PyQt4 and makes it much easier to share message files between Python and C++ code. Below is the alternative implementation of A that uses QCoreApplication.translate():
from QtCore import QCoreApplication
translate = QCoreApplication.translate
class A(QtCore.QObject):
def hello(self):
return translate("A", "Hello")
其中 "A" 是硬编码上下文,pyside-lupdate
将 找到。好多了!