2

I am creating a Qt application and I added dynamic translation (I followed the example at http://www.qtcentre.org/wiki/index.php?title=Dynamic_translation_in_Qt4_applications) with a QCombobox which lists different languages. It works well but the problem is that I don't see how to translate dynamically the text in the dialog windows (for example YES and NO buttons).

In the main.cpp, before executing the app, I have :

QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
a.installTranslator(&qtTranslator);

which translate the dialog Windows in the user system language but I would like to do it dynamically like the rest of my app.

Here are the code of the example : application.h :

#ifndef APPLICATION_H

#include <QApplication>
#include <QHash>
#include <QStringList>
class QDir;
class QTranslator;

typedef QHash<QString, QTranslator*> Translators;

class Application : public QApplication
{
    Q_OBJECT

public:
    explicit Application(int& argc, char* argv[]);
    ~Application();

    static void loadTranslations(const QString& dir);
    static void loadTranslations(const QDir& dir);
    static const QStringList availableLanguages();

public slots:
    static void setLanguage(const QString& locale);

private:
    static QTranslator* current;
    static Translators translators;
    //static QTranslator* qtTranslator;//test to translate dialog windows
};

#endif // APPLICATION_H

application.cpp :

    #include <QDir>
#include <QFileInfo>
#include <QTranslator>
#include <QLibraryInfo>

#include "application.h"


QTranslator* Application::current = 0;
//QTranslator* Application::qtTranslator = 0;//test to translate dialog windows

Translators Application::translators;

Application::Application(int& argc, char* argv[])
    : QApplication(argc, argv)
{

}

Application::~Application()
{
}

void Application::loadTranslations(const QString& dir)
{
    loadTranslations(QDir(dir));

    QString locale = QLocale::system().name().section('_', 0, 0);
    QString language=locale+ "_" + locale;

    if(!QFile::exists(":Localization/Localization/"+language+".qm"))//if system language is not available, load english version
        setLanguage("en_en");
    else
        setLanguage(language);
}

void Application::loadTranslations(const QDir& dir)
{
    // <language>_<country>.qm
    QString filter = "*_*.qm";
    QDir::Filters filters = QDir::Files | QDir::Readable;
    QDir::SortFlags sort = QDir::Name;
    QFileInfoList entries = dir.entryInfoList(QStringList() << filter, filters, sort);
    foreach (QFileInfo file, entries)
    {
        // pick country and language out of the file name
        QStringList parts = file.baseName().split("_");
        QString language = parts.at(parts.count() - 2);
        QString country  = parts.at(parts.count() - 1);
        // construct and load translator
        QTranslator* translator = new QTranslator(instance());
        if (translator->load(file.absoluteFilePath()))
        {
            QString locale = language + "_" + country;
            translators.insert(locale, translator);
        }
    }
}

const QStringList Application::availableLanguages()
{
    // the content won't get copied thanks to implicit sharing and constness
    return QStringList(translators.keys());
}

void Application::setLanguage(const QString& locale)
{
    //test to translate dialog windows
    /*
    QTranslator qtTranslator;
    QString qTLocale=locale.mid(0,2);
    qtTranslator->load("qt_"+ qTLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    installTranslator(qtTranslator);
    //*/

    // remove previous
    if (current)
    {
        removeTranslator(current);
    }

    // install new
    current = translators.value(locale, 0);
    if (current)
    {
        installTranslator(current);
    }
}

I added the lines commented with "//test to translate dialog Windows" to try the dynamic translation of the dialog Windows but it doesn't work (no error at compilation but the application isn't launched with error message "the program stopped suddenly", I am on Qt Creator). Thanks!

SteveTJS
  • 635
  • 17
  • 32

3 Answers3

2

So I finally got this to work after having the same problems. There are two things which were wrong in my case:

  1. Name of the qt translation file:

    QTranslator qtTranslator;
    qtTranslator.load("qt_de");  // worked in older qt versions
    qtTranslator.load("qtbase_de");  // works for qt5.2
    a.installTranslator(&qtTranslator);
    
  2. Have the correct parent for the QMessageBox. This is obvious after you think about it but pretty easy to miss.

    QMessageBox::information(someChildOfMainWindow, ...);
    

For the latter, if you happen to be in a class which is a QObject but not a QWidget you can also use the following code to access your MainWindow from anywhere:

QMainWindow* mw = 0;
foreach(QWidget* widget, QApplication::topLevelWidgets()) {
    if(widget->objectName() == "<your-main-window-class-name-here>") {
        mw = qobject_cast<QMainWindow>(widget);
    }
}
Bowdzone
  • 3,827
  • 11
  • 39
  • 52
0

Ok Sébastian Lange, so finally I created the box and didn't use the static ones ( QMessageBox::question(..) for example)

QMessageBox quitMessageBox;
quitMessageBox.setWindowTitle(tr("Quit"));
quitMessageBox.setWindowIcon(QIcon("myIcon.jpg"));
quitMessageBox.setIcon(QMessageBox::Question);
quitMessageBox.setText(tr("Quit the application?"));
quitMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
quitMessageBox.setDefaultButton(QMessageBox::No);
quitMessageBox.button(QMessageBox::Yes)->setText(tr("Yes"));
quitMessageBox.button(QMessageBox::No)->setText(tr("No"));

And then

quitMessageBox.exec();

Like that it's ok. Thanks again!

SteveTJS
  • 635
  • 17
  • 32
-2

When providing buttons for the dialog use

tr("Yes")

as for default dialogs, the created .ts-language file (to be edited via QtLinguist) should have default translations included.

The tr() marks the given argument to be translated. This concludes to if you do not know what will be written on a given label, you cannot translate it...

Sebastian Lange
  • 3,879
  • 1
  • 19
  • 38
  • thanks for your answer. I agree with that but it's possible only when you create the dialog box yourself (I think). What I would like is dynamic translation for dialog like QMessageBox::information(this,tr("Quit"),tr("Quit the application?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); the YES and NO buttons in this kind of box. – SteveTJS Sep 24 '13 at 12:04
  • IIRC those are translated by default values. I am not sure right now, but i think the YesRole is implemented using: ``yesButtonText.isEmpty() ? tr("OK") : yesButtonText``, so you should have the posibillity to translate the given Button Text. – Sebastian Lange Sep 24 '13 at 12:20
  • it's ok by creating the box and not using the QMessageBox::information(...) for example. See my answer below. Thanks! – SteveTJS Sep 24 '13 at 15:02