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
AD

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

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

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

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

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

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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