2

I needed to translate my english UI in french, so I did all the necessary with .ts and .qm files, load it in the QTranslator class, and install it to the QApplication:

//in the InterfaceWidget constructor:
QTranslator myappTranslator;
bool loaded = myappTranslator.load("myApp_" + QLocale::system().name());
qDebug()  << "Is translation file loaded?" << loaded; // RETURNS TRUE
QApplication::installTranslator(&myappTranslator);
ui.setupUi(this);
ui.retranslateUi(this); //works, it translates the UI

Later, I create and attach to the InterfaceWidget another Widget (in a tab) called ConfigurationTabUI :

m_ConfigurationTabUI = new ConfigurationTabUI(ui.configTab);

The corresponding UI is also translated to french, correctly.

And here is my problem: in the ConfigurationTabUI's methods, it doesn't work when I try to translate a simple QString:

void ConfigurationTabUI::on_ValidButton_clicked(){

    QString msg(ConfigurationTabUI::tr("message to translate"));
    qDebug() << "translated string: " << msg; // NOT TRANSLATED
}

I really have no clue why... Thanks for your help.

Note: I Use Qt5.2 and I double checked that the .ts file contains the right translated string.

toussa
  • 1,058
  • 12
  • 21
  • 2
    What you're printing isn't the same variable where you stored the translated string. You stored the translation into "msg" but printed "l_sMsg", which isn't defined anywhere that we can see and have no idea what it might be set to. If it's a typo, please fix the question and then we can look at it again. – goug Feb 08 '17 at 22:58
  • Ah sorry, it was a typo... Thanks to look at it – toussa Feb 08 '17 at 23:28
  • Does the `ConfigurationTabUI` class have the `Q_OBJECT` macro? What happens when you use `QObject::tr` instead of `ConfigurationTabUI::tr`? – Mike Feb 08 '17 at 23:55
  • Yes it has the correct macro (the code in the above example is in a slot). Using QObject::tr doesn't change a thing (except the context of the string in Qt linguist) :( – toussa Feb 09 '17 at 00:06
  • The Q_OBJECT macro isn't involved in this. QObject::tr is a static method, so if it compiles, it's fine. It implies that ConfigurationTabUI is derived from QObject, which is all that's necessary. – goug Feb 09 '17 at 00:06
  • Just to confirm: you've used lupdate to extract the string from your source code, added the translation to the .ts file, and then compiled the .ts to .qm with lrelease? And made sure that the resulting .qm file is in the correct location to be loaded (which should be the "current directory", whatever that happens to be? – goug Feb 09 '17 at 00:09
  • Yes I confirm I did all those steps. And I checked that the qm file is loaded correctly. And by the way, all my UI widgets are translated correctly. I also tried to translate a QString in the InterfaceWidget object and it worked... So it looks like it might be something with translation in ConfigurationTabUI – toussa Feb 09 '17 at 00:12

1 Answers1

2

Ok, I found the problem, it's just a dumb oversight:

QTranslator is created on the stack and not dynamically (on the heap), so the object is destroyed at the end of the method. As a result, it translates the UI because the object is still there but later, when a slot is called, nothing get translated.

Here is my code:

//in the InterfaceWidget constructor:
QTranslator* myappTranslator = new QTranslator(QApplication::instance());
bool loaded = myappTranslator->load("myApp_" + QLocale::system().name());
qDebug()  << "Is translation file loaded?" << loaded; // RETURNS TRUE
QApplication::installTranslator(myappTranslator);
ui.setupUi(this);

and in ConfigurationTabUI (which inherits from QWidget):

void ConfigurationTabUI::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange) {
        ui.retranslateUi(this);
        reset(); //my method to reload some data in UI
    } else
        QWidget::changeEvent(e);
}
toussa
  • 1,058
  • 12
  • 21
  • I think it would be safer to create the translator as a child of your `QApplication`. I would probably do that directly in the `main.cpp` after constructing the `QApplication` object. – smerlin Feb 10 '17 at 09:30
  • I don't have access to main.cpp because my code is a framework plugin. InterfaceWidget class is the "main" class of my plugin. Would still `QTranslator* myappTranslator = new QTranslator(QApplication::instance());` be better ? In which case ? – toussa Feb 10 '17 at 09:36
  • The QApplication references the translator object thus you need to make sure that the lifetime of the QTranslator object does not end before the QApplication object gets destroyed. In Qt you do that by making the QTranslator a child of QApplication. – smerlin Feb 10 '17 at 11:16