LINUX.ORG.RU

Не работает перевод интерфейса до старта QApplication. Можно это как-то обойти?

 , , ,


0

1

Перед тем, как будет стартовать объект QApplication (метод exec()), мне нужно подготовить определенные файлы, которые нужны для корректного старта, чтобы приложение могло их найти.

Подготовка файлов требует пользовательского выбора с вопросом «где разместить нужные файлы?». Соответственно нужно открыть окно, в котором будет интерфейс выбора. Окно такое есть, оно унаследовано от QDialog, оно работает даже до запуска основного приложения.

Но вот проблема: в этом окне есть код автоматического определения языка системы. И он работает, и он определяет язык, и устанавливает его приложению, и этот код запускается самым первым в конструкторе окна:

// Автоматическое определение языка системы
void InstallDialog::setupAutoLangTranslation()
{
    QString lang=QLocale().system().name().split('_').first().toLower();
    QStringList availableLang={"en", "ru"};

    if( !availableLang.contains(lang) )
    {
        lang="en";
    }

    qDebug() << "Auto detect lang in installator: " << lang;

    // Подключение перевода интерфейса
    QString langFileName=":/resource/translations/mytetra_"+lang+".qm";
    qDebug() << "Lang file: " << langFileName;

    QTranslator langTranslator;
    bool loadResult=langTranslator.load(langFileName);

    if(loadResult)
    {
        qDebug() << "Success load translation file";
        qApp->installTranslator(&langTranslator); // Транслятор устанавливается в объекте приложения
    }
    else
    {
        qDebug() << "Can't load translation file";
    }
}

Все установки строк в классе этого окна происходят _после_ данного кода. Естественно, все строки обернуты в tr(), сделаны lupdate, linguist, lrelease.

Однако перевода интерфейса не происходит.

Я думал, что перевод не работает из-за того, что настройка языка делается в конструкторе окна. Однако, внутри класса окна есть вызов еще одного диалогового окна QMessageBox, создаваемом на месте вызова на стеке:
void InstallDialog::onAccepted()
{
    if( !ui->m_radioButtonStandart->isChecked() and
        !ui->m_radioButtonPortable->isChecked() )
    {
        QMessageBox msgBox;
        msgBox.setText(tr("Please select one of install mode."));
        msgBox.exec();
    }
    else
    {
        this->accept();
    }
}

И в этом окне тоже перевод не работает.

Я сейчас грешу только на то, что перевод не работает из-за того, что объект приложения создан, но его основной цикл не запущен. А применение перевода сделано где-то в глубинах запуска основного цикла.

Вопрос в том, можно ли как-то выйти из этой проблемы, и заставить работать систему локализации Qt? Может быть, есть какой-то вызов, который обновит систему локализации без запуска основного цикла приложения? Или, может быть, есть какой-то другой метод?

Очень не хотелось бы в корне переделывать все приложение из-за такой вот особенности Qt.

Исходники: https://github.com/xintrea/mytetra_dev

Места в исходниках:

* /app/src/views/installDialog/InstallDialog.h
* /app/src/views/installDialog/InstallDialog.cpp
* /app/src/libraries/GlobalParameters.cpp, метод initWorkDirectory()
* /app/src/main.cpp, функция main(), вызов globalParameters.init();

Примечание: Чтобы появилось проблемное окно, не должно существовать директории ~/.config/mytetra

★★★★★

А почему именно ДО вызова exec() ? И я не очень представляю, будет ли у тебя вообще нормально работать диалоговое окно ДО запуска цикла обработки событий. По моему, не проблема сразу запускать вспомогательное диалоговое окно а из него уже создавать основное (Разумеется все это делать при запущенном цикле обработки событий).

rumgot ★★★★★ ()
Последнее исправление: rumgot (всего исправлений: 3)
Ответ на: комментарий от rumgot

А почему именно ДО вызова exec() ? И я не очень представляю, будет ли у тебя вообще нормально работать диалоговое окно ДО запуска цикла обработки событий.

Будет. То что ты называешь «цикл обработки событий» на самом деле называется «цикл обработки событий объекта приложения», не более того.


По моему, не проблема сразу запускать вспомогательное диалоговое окно а из него уже создавать основное (Разумеется все это делать при запущенном цикле обработки событий).

Это ты что-то странное написал. Потенциально рабочий вариант - это создать MainWindow как основной управляющий элемент приложения и запустить app.exec(), а в конструкторе MainWindow вызвать вышеописанное разворачивание с пользовательским диалогом. Возможно, так будет работать. Но это значит, что нужно весь старт программы переделывать.

Xintrea ★★★★★ ()
Ответ на: комментарий от anonymous

Может этот метод надо руками вызвать в конструкторе твоего диалогового окна?

А вот это что в топике:

    if(loadResult)
    {
        qDebug() << "Success load translation file";
        qApp->installTranslator(&langTranslator); // Транслятор устанавливается в объекте приложения
    }


?

И рядом написано «и этот код запускается самым первым в конструкторе окна».

Xintrea ★★★★★ ()

Кароч, ларчик просто открывался: QTranslator устанавливался в QApplication, но сразу же удалялся при выходе из setupAutoLangTranslation(), потому что лежал на стеке.

Достаточно его сделать как свойство InstallDialog, чтобы он существовал все время работы окна, и перевод начинает работать.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Это ты что-то странное написал. Потенциально рабочий вариант - это создать MainWindow как основной управляющий элемент приложения и запустить app.exec(), а в конструкторе MainWindow вызвать вышеописанное разворачивание с пользовательским диалогом. Возможно, так будет работать. Но это значит, что нужно весь старт программы переделывать.

Ничего странного. Рабочий вариант. Собственно твой тоже пойдет.

rumgot ★★★★★ ()
Ответ на: комментарий от Xintrea

Будет. То что ты называешь «цикл обработки событий» на самом деле называется «цикл обработки событий объекта приложения», не более того.

Лингвист туев. Зачем это писать было.

rumgot ★★★★★ ()
Ответ на: комментарий от Xintrea

Будет. То что ты называешь «цикл обработки событий» на самом деле называется «цикл обработки событий объекта приложения», не более того.

А вот и нет. Но у модальных диалоговых окон и правда есть свой цикл обработки событий, так что работать будет. Как-то.

А вот использовать функции приложения до его запуска - тут нужно либо крестик надеть, либо трусы спустить.

pon4ik ★★★★★ ()