Evgenii Legotckoi
Evgenii Legotckoi05 червня 2016 р. 12:43

QML - Урок 025. Динамічний переклад багатомовного додатка на QML

Після того, як ми ознайомилися з перекладами інтерфейсу програми на Qt/C++ , настав час вивчити можливості динамічного перекладу програми, інтерфейс якого написаний на * QML. *

При розробці на QML є пара моментів, які потрібно врахувати, на відміну від стандартної програми на QWidgets, а саме:

  1. Потрібне додаткове налаштування .pro файлу проекту;
  2. Сам процес завантаження перекладів для потрібної мови здійснюється у C++ шарі;
  3. Переініціалізація перекладу інтерфейсу здійснюється в QML шарі за допомогою функції qsTr();
  4. Після завантаження перекладу, потрібно відправити сигнал з C++ шару QML шар, щоб заново перевести інтерфейс програми, що аналогічно і для С++ програми, але вимагає налаштування взаємодії С++ шару з QML шаром.

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

Створюємо проект, куди входять такі файлы:

  • QmlLanguage.pro - профайл проекту;
  • deployment.pri - файл налаштування деплою, що створюється за замовчуванням;
  • main.cpp - файл вихідних кодів із функцією main;
  • qmltranslator.h - заголовний файл класу завантаження перекладу;
  • qmltranslator.cpp - файл вихідних кодів класу завантаження перекладу;
  • main.qml - основний файл QML шару.

QmlLanguage.pro

Створення файлу перекладу буде аналогічним тому, як це робиться під час створення перекладів для Qt/C++ програми. Тобто потрібно підключити файл перекладу, з яким працюватиме Qt Linguist :

# Добавляем файл переводов,
# который является по сути файлом "исходных кодов" для нашего перевода
TRANSLATIONS += QmlLanguage_ru.ts

Далі запускаємо утиліту lupdate, щоб створити файл перекладів, редагуємо його в Qt Linguist , і запустимо утиліту lrelease створюємо бінарний файл перекладу, який буде підключатися в додаток.

Докладніше про це Ви можете прочитати у попередній статті з використання QTranslator .

Найважливішим моментом для роботи з перекладами в QML є те, що потрібно підключити всі файли QML як вихідні дані, як звичайні C++ файли. Але з позначкою, що лише для використання lupdate_only.

lupdate_only {
    SOURCES += main.qml
}

Нижче повний листинг .pro файл проекту.

TEMPLATE = app

QT += qml quick widgets

CONFIG += c++11

SOURCES += main.cpp \
    qmltranslator.cpp

# Для того, чтобы создать файл переводов со строками из ресурсов qml
# понадобится включить файл qml в качестве обычных исходников в pro файле
# но только для использования утилиты lupdate, чтобы она могла узнать,
# какие строки нуждаются в переводе
lupdate_only {
    SOURCES += main.qml
}

RESOURCES += qml.qrc \
    translations.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

# Добавляем файл переводов,
# который является по сути файлом "исходных кодов" для нашего перевода
TRANSLATIONS += QmlLanguage_ru.ts

HEADERS += \
    qmltranslator.h

main.cpp

Оскільки підключення файлів перекладів здійснюється в C++ шарі, то потрібно зареєструвати об'єкт класу перекладів у контексті QML. з якими ми могли б працювати через QML.*

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "qmltranslator.h"

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

    // Создаём объект для работы с переводами ...
    QmlTranslator qmlTranslator;

    QQmlApplicationEngine engine;
    // и регистрируем его в качестве контекста в Qml слое
    engine.rootContext()->setContextProperty("qmlTranslator", &qmlTranslator);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

qmltranslator.h

У класі є метод встановлення перекладу, в який передається префікс мови перекладу. А з даного методу буде випускатися сигнал про зміну перекладу, щоб була можливість перевести весь інтерфейс з новим перекладом.

Метод установки перекладу необхідно помітити макросом Q_INVOKABLE, щоб була можливість використовувати його в шарі *QML.

#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H

#include <QObject>
#include <QTranslator>

class QmlTranslator : public QObject
{
    Q_OBJECT

public:
    explicit QmlTranslator(QObject *parent = 0);

signals:
    // Сигнал об изменении текущего языка для изменения перевода интерфейса
    void languageChanged();

public:
    // Метод установки перевода, который будет доступен в QML
    Q_INVOKABLE void setTranslation(QString translation);

private:
    QTranslator m_translator;
};

#endif // QMLTRANSLATOR_H

qmltranslator.cpp

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

QmlTranslator::QmlTranslator(QObject *parent) : QObject(parent)
{

}

void QmlTranslator::setTranslation(QString translation)
{
    m_translator.load(":/QmlLanguage_" + translation, "."); // Загружаем перевод
    qApp->installTranslator(&m_translator);                 // Устанавливаем его в приложение
    emit languageChanged();                                 // Сигнализируем об изменении текущего перевода
}

main.qml

Інтерфейс програми буде виглядати так:

Логіка програми наступна: при зміні мови в комбобоксі змінюватиметься мова програми.

Оскільки ми зареєстрували qmlTranslator у контексті QML шару, то в обробнику зміни тексту в комбобоксі будемо викликати метод зміни мови в об'єкті qmlTranslator. А щоб відстежувати сигнал зміни мови, необхідно за допомогою типу Connections підключити до цього сигналу та написати обробник, в якому буде викликатися функція retranslateUi(). У функції retranslateUi() винесені всі текстові властивості всіх об'єктів, які необхідно передати. Зроблено це для спрощення логіки та зменшення надлишкового коду.

import QtQuick 2.6
import QtQuick.Controls 1.5

ApplicationWindow {
    id: applicationWindow
    visible: true
    width: 640
    height: 480

    Label {
        id: helloLabel
        height: 50
        anchors {
            top: parent.top
            left: parent.left
            right: parent.horizontalCenter
            margins: 10
        }
    }

    ComboBox {
        id: comboBox
        anchors {
            top: parent.top
            left: parent.horizontalCenter
            right: parent.right
            margins: 10
        }

        model: ["ru_RU", "en_US"]

        // При изменении текста, инициализируем установку перевода через С++ слой
        onCurrentTextChanged: {
            qmlTranslator.setTranslation(comboBox.currentText)
        }
    }

    Label {
        id: labelText
        wrapMode: Text.Wrap
        anchors {
            top: helloLabel.bottom
            left: parent.left
            right: parent.right
            margins: 10
        }
    }

    // Подключаемся к объекту переводчика
    Connections {
        target: qmlTranslator   // был зарегистрирован в main.cpp
        onLanguageChanged: {    // при получении сигнала изменения языка
            retranslateUi()     // инициализируем перевод интерфейса
        }
    }

    // Функция перевода интерфейса
    function retranslateUi() {
        applicationWindow.title = qsTr("Hello World")
        helloLabel.text = qsTr("Hello World")
        labelText.text = qsTr("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.")
    }

    // Запускаем перевод приложения, когда окно приложения было создано
    Component.onCompleted: {
        retranslateUi();
    }
}

Підсумок

У цілому нині динамічний переклад програми на Qt/QML мало чим відрізняється від перекладу програми з використанням лише Qt/C++. Ключовим моментом є те, що потрібно правильно підключити сигнали та слоти та правильно викликати методи для ініціалізації перекладу.

Завантажити QML програму з динамічним перекладом

Відеоурок

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

ДЧ
  • 31 січня 2019 р. 05:25
  • (відредаговано)

Всё отлично :)
Только у меня вопрос: а как вместо ru_RU и en_US написать в ComboBox'e Russian и English чтобы сохранить функцию смены языка :)

UPD Разобрался
В comboBox model я пишу так:

model: ["English", "Russian"]

И перед отправкой кода ru_RU или en_US в С++ делаю проверку

onCurrentTextChanged: {
            if(comboBox.currentText === "Russian")
                qmlTranslator.setTranslation("ru_RU")
            if(comboBox.currentText === "English")
                qmlTranslator.setTranslation("en_US")
        }
zloi
  • 15 липня 2019 р. 05:32

В Qt 5.10 была добавлена новая функция по переводу qml файлов. Теперь не нужно писать класс оболочку, достаточно вызвать функцию engine.retranslate(); и все обновится само.

Evgenii Legotckoi
  • 15 липня 2019 р. 05:35

Это хорошая новость!!!!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
Дмитрий

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:60бали,
  • Рейтинг балів-1
Дмитрий

C++ - Тест 003. Условия и циклы

  • Результат:92бали,
  • Рейтинг балів8
d
  • dsfs
  • 26 квітня 2024 р. 16:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
Останні коментарі
k
kmssr09 лютого 2024 р. 07:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 14:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 23:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 21:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 грудня 2023 р. 10:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
G
George1307 травня 2024 р. 12:27
добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
BlinCT
BlinCT05 травня 2024 р. 17:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
PS
Peter Son04 травня 2024 р. 05:57
Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
Evgenii Legotckoi
Evgenii Legotckoi03 травня 2024 р. 02:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 квітня 2024 р. 16:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Слідкуйте за нами в соціальних мережах