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)
If you got here like me, wanting to understand how you should do translation using PySide.
Use translate(), not tr()
The annoying part about using tr()
is that you have to manually edit the generated .ts files every time you edit your source with the method he proposes, this editing takes a lot of time especially when you update your .ts file, because it puts all .tr() calls in the "Unknown context" context, you have to manually move all the translations back to the correct contexts again, this gets out of hand really quickly.
Instead, there's a very simple solution.
I read the official pyqt4-lupdate documentation, and it says
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")
Where "A" is the hard-coded context, which pyside-lupdate
will find. A lot better!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With