PyQt Multi Language problem
-
I used Qt Linguist to translate languages for my application, it works fine. But I have a problem that when I click change language, widgets all change language, only QDialog is not updating. I used tr(" ") for all the strings in the QDialog, and translated them to .ts and .qm files but it still doesn't work. Can anyone help me?
-
S SGaist moved this topic from General and Desktop on
-
Hi and welcome to devnet,
How are you creating that dialog ?
How do you handle the language in it ? -
@SGaist I am not using default Qt Dialogs. I am using custom dialogs with extend the QDialog class and having a ui file. In Mainwindow, I have QTabWidget. In each screen, I have one or two button, when the button is pressed, it will display a dialog. For example, in screen 1, I have 2 buttons, when I press button 1, the language of the application will change, but when I press button 2 to display the Dialog, the language of the Dialog does not update. I initialize the Dialog at clicked.connect().
My code:
def showDialog(self):
self.dialog = DialogInMap()
self.dialog.setObjectName("DialogInMap")
self.dialog.show()And my dialog:
class DialogInMap(QDialog):
def init(self):
super().init()
self.setObjectName("DialogInMap")
self.load_ui()def load_ui(self): # create label self.mylabel = QLabel(self.tr("Dialog in Map")) # center self.mylabel.setAlignment(Qt.AlignCenter) self.label_2 = QLabel(self.tr("Hello in Map")) # create layout self.layout = QVBoxLayout() self.layout.setAlignment(Qt.AlignTop) self.layout.addWidget(self.mylabel) self.layout.addWidget(self.label_2) self.setLayout(self.layout)
-
Hi @Hai-Anh-Luu
I had similar problem some time ago. If you look into files generated by Qt Designer you will se that it containsretraslateUi()
methods.
There is no magic behind - this method is called to set right text strings for currently choosen language. And it is called as part of your application start-up routine.
So if you want to change language on the fly - you need to callretranslateUi()
for every dialog/window you have. How to do it depends on you application. For mine I decided that the simplest way is to restart application after UI language change. -
@StarterKit
I would have answered that way, but not given that OP claimswhen I click change language, widgets all change language, only QDialog is not updating.
If it were a matter of all widgets need re-translating, how would the OP report that other widgets change language but only a
QDialog
does not?I still suspect retranslation is necessary, but cannot explain the OP's observation in this light.
-
@JonB, topic starter haven't mentioned anything about
retranslateUi()
and how (s)he calls it. So, I have a reason to suspect that it was called for one window but not for another. Am I right? I don't know. But I see reasons to suspect this kind of behavior. -
@StarterKit
retranslateUi
is a method generated not a standard QWidget method however, you are getting in the correct direction.@Hai-Anh-Luu what you need to do is to implement your own
retranslateUi
method and call it from both the__init__
function (orload_ui
function) and from the changeEvent function when theQEvent.LanguageEvent
happens. Set all the texts of your various dialog widgets inretranslateUi
. -
@SGaist Thank for your answer. I wrote the retranslateUi() function and put it in the load_ui() function after initializing the QLabels. But without any change, my QDialog is still not updating. This is my retranslateUi() function:
def retranslateUi(self): self.mylabel.setText(QCoreApplication.translate("DialogInMap", u"Dialog in Map", None)) self.label_2.setText(QCoreApplication.translate("DialogInMap", u"Hello in Map", None))
And this is my .ts file in vi_VN language, in en_US.ts, I do not translate use translation type="unfinished"></translation> , so I will not show it here:
<context>
<name>DialogInMap</name>
<message>
<location filename="../presentation/map_screen/dialog_map.py" line="12"/>
<source>Dialog in Map</source>
<translation type="unfinished">Hộp thoại ở Map</translation>
</message>
<message>
<location filename="../presentation/map_screen/dialog_map.py" line="16"/>
<source>Hello in Map</source>
<translation type="unfinished">Xin chào ở Map</translation>
</message>
</context>@StarterKit Thank for your answer, but I just want to update language without restart application.
-
@Hai-Anh-Luu
I think you should do some simple debugging (print()
statements) which will help you/us identify where the problem lies:- Show what the currently installed/active translation is immediately before the
translate()
statements. - Just output
print(QCoreApplication.translate("DialogInMap", u"Dialog in Map", None))
, now we don't have to worry about setting widget texts. - Copy that line to immediately after wherever you change the translation language. Now we don't have to worry about being in dialog code.
- Create a plain
QDialog
, not sub-classed. Test that for translation.
- Show what the currently installed/active translation is immediately before the
-
@Hai-Anh-Luu from what you wrote, you did not implement one of the most important thing: the changeEvent method. That's the one you need for dynamic translation to happen.
-
Hi @SGaist
Thanks for mentioningQEvent.LanguageEvent
- I overlooked it when I studied my problem.
My biggest pain was creation ofretranalateUi()
methods manually. There were too many stupid manual work so I decided that language change isn't an often thing and user may tolerate application restart that will handle all widgets automatically.But as we have all this discussion - do you know any way or have any idea of how to automate
retranslateUi()
creation for custom dialogs?uic
obviosly does it so I'm curios is there any better way rather then list all widgets by hand and keep them up to date... -
@StarterKit how many widgets do you have in that dialog ?
The only thing you need to do for getting translated widgets is to move all the setText or equivalent calls from the constructor to the "retranslateUi" method.
-
I finally found the solution. Do not need retranslateUi() in QDialog because if the translations exist, and the translation is loaded correctly, when create new Dialog (show() or exec() action), it will also show the appropriate translated text.
My error was loading wrong QTranslator in QApplication. In QMainWindow, this is my correct code:
translator variable must use in both if name function and in body of QMainWindow. Earlier I made the mistake of instantiating a new QTranslator in the body of the QMainWindow (change_language() fuction) and using it to load the new language, so it was out of sync with the original QTranslator in the name function.
def change_language(self): current_language = None if LanguageQSettings().get_current_language() == Style.Language.vie: # Set tieng Anh o day current_language = Style.Language.en else: # Set tieng Viet o day current_language = Style.Language.vie translator.load(current_language) app.installTranslator(translator) self.retranslateUi() LanguageQSettings().set_current_language(current_language) def retranslateUi(self): self.home_screen.retranslate_Ui() if not self.login_screen.deleteLater: self.login_screen.retranslateUi_login() self.update() if __name__ == "__main__": app = QApplication(sys.argv) translator = QTranslator() translator.load(LanguageQSettings().get_current_language()) app.installTranslator(translator) app.setWindowIcon(QIcon(Style.Image.icon128)) app.setApplicationName(Style.Text.app_name) widget = MainWindow() widget.show() sys.exit(app.exec())```
-