Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically retranslate all widgets in application through a menu?

I am working on a Qt project consisting in a QMainWindow and multiple Qt and non-Qt classes. Many of them use QStrings with tr() that are translated with Qt Linguist. The language change (QTranslator load & install/QTranslator load & remove) is triggered by QActions in the app's menu.

I have read the official Qt documentation concerning dynamic translation, and it basically suggests the following overload:

void MainWindow::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::LanguageChange) {
        titleLabel->setText(tr("Document Title"));
        ... // all my tr() QStrings here
        okPushButton->setText(tr("&OK"));
    } else
        QWidget::changeEvent(event);
}

The problem I am facing is that the QStrings to translate are many (58 in QMainWindow alone), and several are filled at runtime as well, through user interaction; e. g. myFunction(a,b) below is called through a QPushButton:

void MainWindow::myFunction(MyClassA a, MyClassB b)
            {
            ...
            if(b.myCondition() == 0)
                {
                ...
                // below is the problem
                myLabel->setText(myLabel->text() + QString("\n" + a->getName() + tr(" gagne ") + exp + tr(" points d'expérience")));
                }
             else
             {
                myLabel->setText(QString(tr("something else")));
             }
            ...
            }

So I hardly see how I can include this type of QString in the changeEvent() method above. What about the classes outside of MainWindow, which also have QStrings to translate but are not QWidget (so no changeEvent overload possible) ?

I have read that there's another way to use this method, with a UI form:

void MainWindow::changeEvent(QEvent* event)
{
    if (event->type() == QEvent::LanguageChange)
    {
        ui.retranslateUi(this);
    }
...
}

But this involves that I am using a UI form in my project, which I am not doing (all widgets are created in code). I tried to export my MainWindow in a UI form, but when I try to include the generated header into the project, I get the following error:

ui_fenetreprincipale.h:32: error: qmainwindowlayout.h: No such file or directory

Thank you by advance for any suggestion to select the best way to translate my application.

like image 498
Ety Avatar asked Aug 13 '16 08:08

Ety


1 Answers

Organize your code so that all the setting of translatable strings is done in one method in each class.

eg give every class that has translatable strings a setTrs() method that actually sets the strings.

class A 
{
   void setTrs()
   { 
     okPushButton->setText(tr("&OK"));    
   }
}
//--------------
class B
{
   int _trCond;
   void myFunction(MyClassA a, MyClassB b)
   {
        _trCond = b.myCondition(); 
        setTrs();
   }

   void setTrs()
   {
         if(_trCond == 0)
            myLabel->setText(myLabel->text() + QString("\n" + a->getName() + tr(" gagne ") + exp + tr(" points d'expérience")));
         else
            myLabel->setText(QString(tr("something else")));
   }

Then whenever the language for the application changes (eg connect to a menu entry selection, or MainWindow::event() or however the required language can change), you have to manually call the setTrs method of each of these objects

eg

void MainWindow::changeEvent(QEvent *event)
{
   if (event->type() == QEvent::LanguageChange) 
   {
        setTrs();
        objA.setTrs();
        objB.setTrs();
    }
}

Even more elegant would be to store the objects in a QList and just iterate through it calling the setTrs method on each element in turn

like image 184
Declan Avatar answered Nov 10 '22 01:11

Declan