Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How to translate text with QUiLoader?
Qt 6.11 is out! See what's new in the release blog

How to translate text with QUiLoader?

Scheduled Pinned Locked Moved Unsolved Qt for Python
9 Posts 4 Posters 1.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • feiyuhuahuoF Offline
    feiyuhuahuoF Offline
    feiyuhuahuo
    wrote on last edited by
    #1

    Hi guys,
    I'm trying to translate the UI texts. The problem is that I use Designer to design my UI, and so I then use QUiLoader to load my ui file. But when I try to use retranslateUi, it just comes with this error: AttributeError: 'PySide6.QtWidgets.QWidget' object has no attribute 'retranslateUi'. Code:

    class CustomMessageBox(QMainWindow):
        def __init__(self):
            super().__init__()
            self.ui = QUiLoader().load('../../message.ui')  # 主界面
            self.setCentralWidget(self.ui)
    
            self.trans = QTranslator()
            self.trans.load('../../message.qm')
            app = QApplication.instance()
            app.installTranslator(self.trans)
            self.ui.retranslateUi(self)
    
    
    if __name__ == '__main__':
        from PySide6.QtWidgets import QApplication
    
        app = QApplication()
        ui = CustomMessageBox()
        ui.show()
        app.exec()
    

    Is it possible to translate the UI for application created by QUiLoader?

    JonBJ 1 Reply Last reply
    0
    • feiyuhuahuoF feiyuhuahuo

      Hi guys,
      I'm trying to translate the UI texts. The problem is that I use Designer to design my UI, and so I then use QUiLoader to load my ui file. But when I try to use retranslateUi, it just comes with this error: AttributeError: 'PySide6.QtWidgets.QWidget' object has no attribute 'retranslateUi'. Code:

      class CustomMessageBox(QMainWindow):
          def __init__(self):
              super().__init__()
              self.ui = QUiLoader().load('../../message.ui')  # 主界面
              self.setCentralWidget(self.ui)
      
              self.trans = QTranslator()
              self.trans.load('../../message.qm')
              app = QApplication.instance()
              app.installTranslator(self.trans)
              self.ui.retranslateUi(self)
      
      
      if __name__ == '__main__':
          from PySide6.QtWidgets import QApplication
      
          app = QApplication()
          ui = CustomMessageBox()
          ui.show()
          app.exec()
      

      Is it possible to translate the UI for application created by QUiLoader?

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @feiyuhuahuo
      I wonder whether QUiLoader().load() already respects current translator and translates for you?? What if you move your translator stuff to before the load()??

      S feiyuhuahuoF 2 Replies Last reply
      0
      • JonBJ JonB

        @feiyuhuahuo
        I wonder whether QUiLoader().load() already respects current translator and translates for you?? What if you move your translator stuff to before the load()??

        S Offline
        S Offline
        StarterKit
        wrote on last edited by
        #3

        @JonB good point.
        QWidget indeed has no retranslateUi() and it is uic who adds it to the class when it is created from ui-file.
        So either your are right or it isn't possible.

        But QUiLoader.load() returns QWidget so should type-casting be there?...

        JonBJ 1 Reply Last reply
        0
        • S StarterKit

          @JonB good point.
          QWidget indeed has no retranslateUi() and it is uic who adds it to the class when it is created from ui-file.
          So either your are right or it isn't possible.

          But QUiLoader.load() returns QWidget so should type-casting be there?...

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by
          #4

          @StarterKit said in How to translate text with QUiLoader?:

          But QUiLoader.load() returns QWidget so should type-casting be there?...

          Don't know what you mean here. You are Python, so what "type-casting"??

          retranslateUi() is not a method on any widget. It is a little function which is produced by running the "pyuic"-type program for what PySide/PyQt you use on the .ui file produced by the designer. But you don't run these, so I don't think you have one anywhere. See e.g. https://stackoverflow.com/questions/66361580/what-does-retranslateui-do-in-pyqt.

          1 Reply Last reply
          0
          • JonBJ JonB

            @feiyuhuahuo
            I wonder whether QUiLoader().load() already respects current translator and translates for you?? What if you move your translator stuff to before the load()??

            feiyuhuahuoF Offline
            feiyuhuahuoF Offline
            feiyuhuahuo
            wrote on last edited by
            #5

            @JonB

                    self.trans = QTranslator()
                    self.trans.load('../../message.qm')
                    app = QApplication.instance()
                    app.installTranslator(self.trans)
            

            I move the four lines before QUiLoader().load(), and yes, it works. The UI can be translated successfully. But still, there's a problem. If I want to change the language real-timely,is it possble? I mean that in my UI there are several buttons. Each button means a certain language. By clicking these buttons, the UI can directly update the language without restart the APP. If so, seems I must use retranslateUi function. But I can't get it if use QUiLoader().load().

            JonBJ 1 Reply Last reply
            0
            • feiyuhuahuoF feiyuhuahuo

              @JonB

                      self.trans = QTranslator()
                      self.trans.load('../../message.qm')
                      app = QApplication.instance()
                      app.installTranslator(self.trans)
              

              I move the four lines before QUiLoader().load(), and yes, it works. The UI can be translated successfully. But still, there's a problem. If I want to change the language real-timely,is it possble? I mean that in my UI there are several buttons. Each button means a certain language. By clicking these buttons, the UI can directly update the language without restart the APP. If so, seems I must use retranslateUi function. But I can't get it if use QUiLoader().load().

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by JonB
              #6

              @feiyuhuahuo
              So you want to be able to re-change the language dynamically at runtime. I don't think using QUiLoader().load() in itself prevents this. It just means that you do not have individual variables pointing to each widget which should be translated, rather any time you want to access widgets you have to walk the hierarchy via QObject.findChildren<QWidget>. You then need to know which ones (all of them?) you want translated and get the translation.

              I don't do translation, but one problem I see: I believe the original English (or whatever you type into the Designer) gets completely replaced by the translation (e.g. in QUiLoader().load()). So I don't know when you want to re-translate you are supposed to find the original text to lookup from?

              You might want to try running pyuic (or whatever) on your project or a sample one just to look at the code it generates for retranslateUi(). You will see it's nothing "magic", but has the advantage if called again that it knows exactly which widgets need translating.

              Google also for something like qt translation dynamic to see what work you have to do, e.g. an old link is https://forum.qt.io/topic/55200/dynamic-translation-of-strings-in-widgets.

              feiyuhuahuoF 1 Reply Last reply
              0
              • F Offline
                F Offline
                friedemannkleint
                wrote on last edited by
                #7

                Provided all the .qm are created and loaded properly, QUiLoader should retranslate on receiving QEvent::LanguageChange if QUiLoader.setLanguageChangeEnabled() was set to true.

                See https://doc.qt.io/qtforpython-6/tutorials/basictutorial/translations.html
                and https://doc.qt.io/qtforpython-6/PySide6/QtUiTools/QUiLoader.html?highlight=quiloader#PySide6.QtUiTools.PySide6.QtUiTools.QUiLoader.setLanguageChangeEnabled

                Note we generally recommend using pyside6-uic for Qt Designer forms (see https://doc.qt.io/qtforpython-6/tutorials/basictutorial/uifiles.html ).

                feiyuhuahuoF 1 Reply Last reply
                2
                • JonBJ JonB

                  @feiyuhuahuo
                  So you want to be able to re-change the language dynamically at runtime. I don't think using QUiLoader().load() in itself prevents this. It just means that you do not have individual variables pointing to each widget which should be translated, rather any time you want to access widgets you have to walk the hierarchy via QObject.findChildren<QWidget>. You then need to know which ones (all of them?) you want translated and get the translation.

                  I don't do translation, but one problem I see: I believe the original English (or whatever you type into the Designer) gets completely replaced by the translation (e.g. in QUiLoader().load()). So I don't know when you want to re-translate you are supposed to find the original text to lookup from?

                  You might want to try running pyuic (or whatever) on your project or a sample one just to look at the code it generates for retranslateUi(). You will see it's nothing "magic", but has the advantage if called again that it knows exactly which widgets need translating.

                  Google also for something like qt translation dynamic to see what work you have to do, e.g. an old link is https://forum.qt.io/topic/55200/dynamic-translation-of-strings-in-widgets.

                  feiyuhuahuoF Offline
                  feiyuhuahuoF Offline
                  feiyuhuahuo
                  wrote on last edited by
                  #8

                  @JonB
                  So I need to add code to translate each widget by myself just like what retranslateUi() does? I have quite a lot of widgets. I prefer to keep my code short and clean. So I will try some other ways. Thanks for the reply.
                  By the way, according to @friedemannkleint , I've already done some successful test. But still, there's some problem. Would like to take a look?

                  1 Reply Last reply
                  0
                  • F friedemannkleint

                    Provided all the .qm are created and loaded properly, QUiLoader should retranslate on receiving QEvent::LanguageChange if QUiLoader.setLanguageChangeEnabled() was set to true.

                    See https://doc.qt.io/qtforpython-6/tutorials/basictutorial/translations.html
                    and https://doc.qt.io/qtforpython-6/PySide6/QtUiTools/QUiLoader.html?highlight=quiloader#PySide6.QtUiTools.PySide6.QtUiTools.QUiLoader.setLanguageChangeEnabled

                    Note we generally recommend using pyside6-uic for Qt Designer forms (see https://doc.qt.io/qtforpython-6/tutorials/basictutorial/uifiles.html ).

                    feiyuhuahuoF Offline
                    feiyuhuahuoF Offline
                    feiyuhuahuo
                    wrote on last edited by feiyuhuahuo
                    #9

                    @friedemannkleint @JonB
                    Thanks for the help. I'm going to succeed. There's still a problem. Codes first:

                    from PySide6.QtUiTools import QUiLoader
                    from PySide6.QtWidgets import QMainWindow
                    from PySide6.QtWidgets import QApplication, QMenu, QMessageBox
                    from PySide6.QtGui import QCursor, QAction
                    from PySide6.QtCore import QTranslator
                    
                    class PP(QMainWindow):
                        def __init__(self):
                            super().__init__()
                    
                            loader = QUiLoader()
                            loader.setLanguageChangeEnabled(True)
                            print(loader.isLanguageChangeEnabled())
                    
                            self.app = QApplication.instance()
                    
                            self.main_ui = loader.load('test.ui')
                            self.setCentralWidget(self.main_ui)
                            self.main_ui.pushButton.clicked.connect(self.trans_ui)
                    
                            self.menu = QMenu(self)
                            self.action = QAction(self.tr('hello'), self)
                            self.action.triggered.connect(self.trans_code)
                            self.menu.addAction(self.action)
                            self.main_ui.pushButton.customContextMenuRequested.connect(self.show_menu)
                    
                            self.show()
                    
                        def changeEvent(self, event):
                            print(event)
                    
                        def load_qm(self):
                            self.trans_window = QTranslator()
                            self.trans_window.load('test.qm')
                            self.app.installTranslator(self.trans_window)
                            
                            self.trans_main = QTranslator()
                            self.trans_main.load('ttt.qm')
                            self.app.installTranslator(self.trans_main)
                    
                        def trans_ui(self):
                            self.load_qm()
                    
                        def trans_code(self):
                            self.main_ui.label.setText(self.tr('pear'))
                            QMessageBox.information(self, self.tr('cat'), self.tr('apple'))
                    
                        def show_menu(self):
                            self.menu.exec(QCursor.pos())
                    
                    if __name__ == '__main__':
                        app = QApplication()
                        ui = PP()
                        app.exec()
                    

                    The related ts file:
                    bd22e1d3-7cfc-4b38-993c-9d01907d813b-image.png
                    There are a button "translate" and a label. Right click the button, a menu will appear. And then left click the 'hello' action, a QMessage box will appear and text 'pear' will be set to the label. I hope that before I left click the button, all the text are English. And after I left click the button, all the text can be translated to Chinese directly.
                    But in the below GIF:
                    case3.gif
                    Problem 1: after I left click the button, the action text 'hello' was not translated. The label text 'pear' was translated afterI left click the action. (I hope it can be translated as soon as I left click the button.)

                    If I change the code as follows, which means load 'ttt.qm' before load() ui file just as what @JonB said.

                    class PP(QMainWindow):
                        def __init__(self):
                            super().__init__()
                    
                            loader = QUiLoader()
                            loader.setLanguageChangeEnabled(True)
                            print(loader.isLanguageChangeEnabled())
                    
                            self.app = QApplication.instance()
                    
                            self.trans_main = QTranslator()
                            self.trans_main.load('ttt.qm')
                            self.app.installTranslator(self.trans_main)
                    
                            self.main_ui = loader.load('test.ui')
                            self.setCentralWidget(self.main_ui)
                            self.main_ui.pushButton.clicked.connect(self.trans_ui)
                            ......
                    
                        ......
                    
                        def load_qm(self):
                            self.trans_window = QTranslator()
                            self.trans_window.load('test.qm')
                            self.app.installTranslator(self.trans_window)
                    
                        def trans_ui(self):
                            self.load_qm()
                      
                        ......
                    

                    case4.gif
                    All text in 'ttt.ts' can be translated at the beginning, but this is not what I want.
                    Problem 2: what's the difference between this two case? I'm puzzled on what the code is doing.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved