I want to use a QTranslator to be able to use English text labels and still have the software showing German labels.
Unfortunately my app does not translate, except when I specify the context. The following static function instanciates a QApplication and adds the desired translators.
The first print translates 'Apple2' correctly to 'Apfel2'. The context in Qt Linguist also has the context 'app'.
The second print does not translate though. tr()
calls in classes (defined in the same python file) don't translate either.
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
EDIT:
The part for the static function was correct. The context for the application was QApplication. This did not help with the QMainWindow subclass though. I updated the code accordingly. The context generated by pyside-lupdate for the class is MainWindow:
view
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
controller
def initiate():
model.initiate_mongodb()
app = view.load_application()
main_window = view.MainWindow()
main_window.show()
sys.exit(app.exec_())
Solution: The solution to my problem was that the QTranslator didn't have any parent. QTranslator(app) solved my problem.
This seems to happen because, unlike Qt, PySide/PyQt determines the context at runtime.
In your example, the context will (I think) resolve to QApplication
at runtime, whereas the pyside/pyqt lupdate tools will hardcode it as app
. The tools only do static analysis of the source code, and so I suppose they are not smart enough to figure out what the correct class should be.
The example code should work if you do something like this, though:
class App(QtGui.QApplication):
def __init__(self):
super(App, self).__init__()
message = self.tr('Apple')
...
app = App()
...
print(app.tr('Apple'))
(Obviously you will need to update the translation files first).
EDIT:
Here's a simplified demo that works for me:
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>
command output:
$ 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)