Можно ли динамически переводить приложения Qt без дублирования кода?

Я интегрировал QTranslator класс в моем проекте. Пока все работает и при перезапуске программы все текстовые поля переводятся. Теперь я хотел бы обеспечить динамический перевод, чтобы пользователям не нужно было перезапускать приложение.

В моих исследованиях я обнаружил, что необходимо переопределить changeEvent() функционировать так:

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

(Источник: http://doc.qt.io/qt-5/internationalization.html#dynamic-translation)

Для приложений, написанных с помощью Qt designer, кажется, что можно просто вызвать

ui->retranslateUi(this);

в пределах changeEvent() функция и все текстовые поля будут переведены.
Но для всех других текстов в приложении текст должен быть установлен как в примере выше. Что мне больно, потому что мне всегда нужно обновлять текст в двух местах, когда я что-то меняю (в changeEvent функция и в основной части моей программы).
С большим количеством текстовых полей может легко что-то пропустить.

Есть ли способ обновить эти текстовые поля без необходимости дублировать «text-setting-method»?

3

Решение

Я не уверен, зачем вам нужно дублировать текстовые сеттеры.

Основная идея состоит в том, чтобы установить переводимые тексты один раз в changeEvent() обработчик и вручную Отправить LanguageChange событие, как указано в документы. Это также вызовет событие для дочерних виджетов.

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
titleLabel = new QLabel(this);
okPushButton = new QPushButton(this);
// Fire the LanguageChange event - the event handler will set the texts:
QEvent languageChangeEvent(QEvent::LanguageChange);
QCoreApplication::sendEvent(this, &languageChangeEvent);
}

void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
titleLabel->setText(tr("Document Title"));
okPushButton->setText(tr("&OK"));
} else {
QWidget::changeEvent(event);
}
}

Вы также можете использовать некоторые начальные QCoreApplication::installTranslator(), Это уволит LanguageChange событие и не нужно будет публиковать его вручную.


Другой подход — использовать свои собственные функции вместо событий. Этот подход, как правило, тот же, за исключением того, что вам нужно вызывать свою функцию вручную для дочерних виджетов.

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
titleLabel = new QLabel(this);
okPushButton = new QPushButton(this);
myChildWidget = new MyChildWidget(this);
retranslate();
}

void MyWidget::retranslate()
{
titleLabel->setText(tr("Document Title"));
okPushButton->setText(tr("&OK"));
myChildWidget->retranslate();
}
2

Другие решения

В общем случае нет, вы не можете избежать этого.

Один вариант — вместо того, чтобы код приложения непосредственно устанавливал текст, подключите сигнал к лямбда-выражению, устанавливающему текст, а затем запустите сигнал. Затем обработчик событий просто должен запустить сигнал.

Пример:

MyWidget::someCalculation() {
// Some stuff
disconnect(this, &MyWidget::updateText, button, Q_NULLPTR);
connect(this, &MyWidget::updateText, button, [someLocalString](){ button->setText(tr("Button Text %1").arg(someLocalString)); });
// More stuff
emit updateText();
}

// Other methods

void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
emit updateText();
} else {
QWidget::changeEvent(event);
}
}
1

По вопросам рекламы [email protected]