Реклама

Qt/C++ - Урок 049. QTranslator - динамический перевод мультиязычного приложения на Qt

РуководствоQtQt, Linguist, QTranslator1474

Рано или поздно разработчик приложений на Qt встречается с необходимостью поддержки мультиязычности в своём приложении. Вот тогда на помощь и приходит класс QTranslator и специализированное приложение для создания переводов Qt Linguist .

Объект класса QTranslator используется для загрузки переводов из специального файла с расширением .qm, который является шестнадцатеричным файлом переводов. Данный файл компилируется из файла переводов в XML формате, который имеет расширение ts и прописывается в pro файле проекта. Данный файл содержит все строки приложения, которые были заключены в функцию tr(). Рекомендую задавать весь интерфейс приложения на английском языке, который будет языком по умолчанию, а переводы уже с нужным языком подгружать из файлов переводов. Если нужный файл перевода не будет найден, то автоматически будет загружен перевод на английском языке. Хотя Вы, конечно, можете применить и другой язык в качестве языка по умолчанию.

Пример загрузки перевода

Структура имени файла перевода играет важную роль в работе с QTranslator. Разберём минимальный пример.

#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTranslator qtLanguageTranslator;
    qtLanguageTranslator.load(QString("QtLanguage_") + QString("ru_RU"));
    qApp->installTranslator(&qtLanguageTranslator);

    MainWindow w;
    w.show();

    return a.exec();
}

В данном примере создаётся объект класса QTranslator, в который загружается интересующий нас файл с указанием языка. В данном случае полное название файла переводов следующее QtLanguage_ru.qm. То есть дано общее для файла переводов название QtLanguage, а также префикс языка перевода _ru . Но вы уже заметили, что в качестве аргумента для метода load формируется строка QtLanguage_ru_RU. Это делается для того, чтобы определить нужный диалект языка, например американский (en_US) или британский (en_GB) английский. Но если в названии файла перевода нет указания диалекта, то будет выбран файл без уточнения диалекта, то есть QtLanguage_ru.qm.

После того, как файл перевода загружен, его необходимо установить в приложение. В данном случае использован глобальный указатель на приложение qApp->installTranslator(&qtLanguageTranslator).

Создание файла перевода

После того, как мы разобрались с минимальным способом установки перевода в приложение, давайте разберёмся с тем, а как вообще можно создать перевод. Для создания перевода необходимо пользоваться функциями tr(), trUtf8(), translate() в приложении и т.д. То есть весь текст, который будет требовать перевода необходимо обрамлять именно в эти функции, чтобы потом создать файл перевода. Выглядеть это может следующим образом:

label->setText(QApplication::translate("MainWindow", "Select Language", 0));
label_2->setText(tr("Hello"));
label_3->setText(trUtf8("Hello world"));

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

  1. lupdate - программа для формирования файла перевода из поля TRANSLATIONS в pro файле, а также обновления информации о всех новых строках в приложении, требующих перевода.
  2. lrelease - программа для сборки итогового файла переводов, который будет использоваться в приложении.
  3. Qt Linguist - непосредственно сам пакет для создания переводов.

Первым шагом, который необходимо будет сделать, после того, как в приложении уже прописаны строки, требующие перевода, это добавить файл для перевода в pro файл проекта. Возможно, Вы также захотите указать информацию о кодировке, которая применяется для перевода.

TRANSLATIONS += QtLanguage_ru.ts

CODECFORSRC     = UTF-8

Далее необходимо воспользоваться утилитой lupdate для создания файла QtLanguage_ru.ts. В Qt Creator ищите здесь: Инструменты -> Внешние -> Linguist -> lupdate .

lupdate сообщит о результате поиска строк для перевода.

Запускается внешняя утилита «D:\Qt\5.6\mingw49_32\bin\lupdate.exe» D:/AndroidQT/QTProjects/QtLanguage/QtLanguage.pro
Updating 'QtLanguage_ru.ts'...
    Found 4 source text(s) (0 new and 4 already existing)

«D:\Qt\5.6\mingw49_32\bin\lupdate.exe» завершилась

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

После создания перевода сохраните файл и скомпилируйте шестнадцатеричный файл перевода, воспользовавшись утилитой lrelease. Её можно найти в Qt Creator там же, где и lupdate, либо запустить из Qt Linguist: File -> Release.

Для применения файла необходимо будет поместить его в каталог с исполняемым файлом приложения, а в коде прописать путь к этому файлу.

Динамический перевод приложения

Загрузка перевода приложения - это хорошо, но что если необходимо менять перевод динамически? Давайте рассмотрим небольшой пример, в котором имеется QComboBox с указанием двух языков: английского и русского, по изменению которого будет происходить смена перевода в приложении.

Структура проекта

  • QtLanguage.pro - профайл проекта;
  • main.cpp - файл проекта с функцией main
  • mainwindow.h - заголовочный файл главного окна приложения;
  • mainwindow.cpp - файл исходных кодов главного окна приложения;
  • mainwindow.ui - файл формы главного окна приложения.

mainwindow.ui

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

В данном окне имеется:

  • label
  • label_2
  • comboBox

С переводом которых мы и будем работать. Удобство графического дизайнера заключается также и в том, что он автоматически формирует метод retranslateUi(), который используется для изменения перевода всех подписей, которые используются в приложении, хотя можно и самим прописать вручную подобный метод, но лично я не хочу терять время на то, что отлично может быть создано автоматически. Например в данном уроке он выглядит следующим образом:

void retranslateUi(QMainWindow *MainWindow)
{
    MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
    label_2->setText(QApplication::translate("MainWindow", "The QTranslator class provides internationalization support for text output.An object of this class contains a set of translations from a source language to a target language. QTranslator provides functions to look up translations in a translation file. Translation files are created using Qt Linguist.", 0));
    label->setText(QApplication::translate("MainWindow", "Select Language", 0));
} // retranslateUi

QtLanguage.pro

Как говорилось выше, указываем имя файла перевода в профайле проекта.

#-------------------------------------------------
#
# Project created by QtCreator 2016-05-22T14:34:42
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QtLanguage
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

TRANSLATIONS = QtLanguage_ru.ts

CODECFORSRC     = UTF-8

main.cpp

А вот в этом файле ничего не будем менять.

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

В заголовочном файле главного окна приложения необходимо объявить объекта класса QTranslator и переопределить метод changeEvent(QEvent *event) , в котором будет определяться событие смены языка приложения.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTranslator>
#include <QEvent>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    // Метод получения событий в главном окне приложения
    // В нём будет производиться проверка события смены перевода приложения
    void changeEvent(QEvent * event) override;

private:
    Ui::MainWindow *ui;
    QTranslator qtLanguageTranslator;   // Выделяем перевод в отдельном поле, иначе ничего работать не будет
};

#endif // MAINWINDOW_H

mainwindow.cpp

Логика работы приложения будет следующей: при смене пункта в комбобоксе будет меняться перевод приложения.

Примечание. Не забудьте положить файл перевода с расширением qm рядом с исполняемым файлом приложения и собрать необходимые dll , иначе не заработает.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Задаём два пункта с текстом локалей в комбобоксе
    ui->comboBox->addItems(QStringList() << "ru_RU" << "en_US");

    // подключаем к сигналу изменения пункта комбобокса лямбда функцию,
    // в которой будет изменяться перевод приложения
    // Здесь имеется интересный момент. Поскольку QComboBox имеет перегрузку сигнатуры сигнала,
    // то нам необходимо скастовать сигнал к нужной сигнатуре.
    // В данном случае будем использовать название пункта при его изменении
    connect(ui->comboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
            [=](const QString &str){
        qtLanguageTranslator.load("QtLanguage_" + str, ".");   // Загружаем перевод
        qApp->installTranslator(&qtLanguageTranslator);        // Устанавливаем перевод в приложение
    });

    // Сделаем первоначальную инициализацию перевода для окна прилоежния
    qtLanguageTranslator.load(QString("QtLanguage_") + QString("ru_RU"));
    qApp->installTranslator(&qtLanguageTranslator);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *event)
{
    // В случае получения события изменения языка приложения
    if (event->type() == QEvent::LanguageChange) {
        ui->retranslateUi(this);    // переведём окно заново
    }
}

Итог

В результате Вы получите приложение с поддержкой двух язык в своём графическом интерфейсе.

Скачать пример приложения с QTranslator

Видеоурок

Реклама
Реклама

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
Реклама
Последние комментарии
  • EVILEG
  • 24 апреля 2017 г. 20:44
Подключение вашего Qt приложения к сервисам Google, используя OAuth 2.0

У меня пока мыслей на этот счёт нет ((

Подключение вашего Qt приложения к сервисам Google, используя OAuth 2.0

Пробовал играться с шарком, либо я криво смотрел, либо почему-то POST запросы на oauth.yandex.ru не летят, хотя должны постом лететь, я и исходники QOAuth2AuthorizationCodeFlow ковырял на пред

  • EVILEG
  • 24 апреля 2017 г. 13:39
Подключение вашего Qt приложения к сервисам Google, используя OAuth 2.0

Возможно, стоит Wireshark`ом запросы посмотреть. В чём отличие идёт аякс запроса от запроса из библиотеки. Возможно, что не хватает какой-нибудь заголовочной информации.

Сейчас обсуждают на форуме
  • EVILEG
  • 28 апреля 2017 г. 20:02
Qt Installer Framework. Вызов программы при деинсталляции.

А. Вон оно как. Ну хорошо, что оказалось так просто.

  • EVILEG
  • 28 апреля 2017 г. 17:01
QTWebEngineView

На самом деле всё гораздо проще. у QWebEngineView есть сигнал urlChanged() . Вот его и нужно использовать, чтобы получить новый url страницы. Заголовочный файл #...

  • EVILEG
  • 28 апреля 2017 г. 9:30
Другой ToolBar

Если ToolBar все должны находиться внутри окна mainwindow, то создайте необходимое количество ToolBar`ов и часть из них сделайте скрытыми. А когда открываете диалог, то показывайте скрытые Too...

  • EVILEG
  • 28 апреля 2017 г. 9:13
Ошибка

Заголовочный файл класса StyleHelper не подключили в файл реализации mainwindow.cpp

Реклама