이번편은 다국어를 처리하여 어플리케이션을 원하는 언어로 표기할 수 있게 만든 방법을 설명하려고 합니다.
다국어를 처리하기 위해서는 pro파일에 설정을 잡아줍니다.
아래 코드를 확인합니다.
untitld.pro
CONFIG += lrelease
QMAKE_LRELEASE_FLAGS += -idbased
TRANSLATIONS += \
lang/lang_kr.ts\
lang/lang_jp.ts\
lang/lang_en.ts
위 설정 코드를 보면
CONFIG에 lrelease옵션을 주었는데 이 옵션의 의미는 TRANSLATIONS에 나열된 ts파일을 빌드하여 .qm 파일(qt에서 인식할 인식할 수 있는 언어파일)로 생성한다.
QMAKE_LRELEASE_FLAGS는 lrelease 옵션설정이라고 보면 됩니다. -idbased는 메시지 키입력을 위해 소스 문자열 대신 ID를 사용하라는 의미이며 lrelease 옵션들중 하나입니다.
현재 한글,일본어,영어 3가지의 언어의 파일을 설정에 올려놨습니다.
ts파일은 xml형식입니다.
lang_en.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<message id="TRID_HEELO">
<source>안녕</source>
<translation>Hello</translation>
</message>
<message id="TRID_LANGAUGE_SETTING">
<source>언어 설정</source>
<translation>Language Settings</translation>
</message>
<message id="TRID_KOREAN">
<source>한글</source>
<translation>Korean</translation>
</message>
<message id="TRID_JAPAN">
<source>일어</source>
<translation>Japanese</translation>
</message>
<message id="TRID_ENGLISH">
<source>영어</source>
<translation>English</translation>
</message>
<message id="TRID_MSG1">
<source>안녕하세요 다국어 테스트 입니다.</source>
<translation>Hello, this is a multilingual test.</translation>
</message>
</context>
</TS>
message id를 지정해주며 source에는 대상 문장 translation에는 source에 있는 문장에 대해 번역한 문장을 넣어준다.
enumClass.h
#ifndef ENUMCLASS_H
#define ENUMCLASS_H
#include <QObject>
class EnumClass : public QObject
{
Q_OBJECT
public:
enum Trinfo
{
TRINFO_KOR,
TRINFO_JP,
TRINFO_ENG
};
Q_ENUMS(Trinfo)
};
#endif // ENUMCLASS_H
enumclass에 언어에대한 enum값을 지정해줍니다.
mainclass.h
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "translationclass.h"
#include "enumClass.h"
class MainClass : public QObject
{
Q_OBJECT
public:
explicit MainClass(QObject *parent = nullptr);
MainClass(QQmlApplicationEngine *engine, QGuiApplication *app);
int load();
signals:
public slots:
private:
QGuiApplication *_app;
QQmlApplicationEngine *_engine;
TranslationClass *_trClass;
};
#endif // MAINCLASS_H
mainclass.cpp
#include "mainclass.h"
#include <QDebug>
MainClass::MainClass(QObject *parent) : QObject(parent)
{
}
MainClass::MainClass(QQmlApplicationEngine *engine, QGuiApplication *app)
{
_app = app;
_engine = engine;
_trClass = new TranslationClass(_engine, _app);
}
int MainClass::load()
{
qmlRegisterType<EnumClass>("qml.register", 1, 0, "EnumClass");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(_engine, &QQmlApplicationEngine::objectCreated,
_app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
_engine->rootContext()->setContextProperty("trClass", _trClass);
_trClass->setLanguage(EnumClass::Trinfo::TRINFO_KOR);
_engine->load(url);
return _app->exec();
}
위의 소스코드에서 qml을 로드하기 전에 번역관련된 trclass를 통해 초기 언어를 설정해주고 qml에서 사용할 수 있게 property화 시킨다.
그럼 번역관련 trclass를 한번 보겠습니다.
translationclass.h
#ifndef TRANSLATIONCLASS_H
#define TRANSLATIONCLASS_H
#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QTranslator>
#include <QDebug>
#include "enumClass.h"
class TranslationClass : public QObject
{
Q_OBJECT
Q_PROPERTY(int language READ language WRITE setLanguage NOTIFY languageChanged)
public:
explicit TranslationClass(QObject *parent = nullptr);
TranslationClass(QQmlApplicationEngine *engine, QGuiApplication *app);
void setLanguage(int lang);
int language() const;
signals:
void languageChanged();
public slots:
private:
QGuiApplication *_app;
QQmlApplicationEngine *_engine;
QTranslator _translator;
int _language;
};
#endif // TRANSLATIONCLASS_H
translationclass.cpp
#include "translationclass.h"
TranslationClass::TranslationClass(QObject *parent) : QObject(parent)
{
}
TranslationClass::TranslationClass(QQmlApplicationEngine *engine, QGuiApplication *app)
{
_engine = engine;
_app = app;
_language = -1;
}
void TranslationClass::setLanguage(int lang)
{
if(lang == _language)
return ;
bool ret = false;
switch (lang)
{
case EnumClass::Trinfo::TRINFO_KOR:
ret = _translator.load("lang_kr.qm", _app->applicationDirPath());
break;
case EnumClass::Trinfo::TRINFO_JP:
ret = _translator.load("lang_jp.qm", _app->applicationDirPath());
break;
case EnumClass::Trinfo::TRINFO_ENG:
ret = _translator.load("lang_en.qm", _app->applicationDirPath());
break;
}
if(ret)
{
_app->installTranslator(&_translator);
}
else
{
qDebug() << "set language fail";
return ;
}
_language = lang;
emit languageChanged();
_engine->retranslate();
}
int TranslationClass::language() const
{
return _language;
}
위의 소스코드에서 qml에서 선택된 언어에 맞게mTranslator.load를 통해 해당 언어qm파일을 로드합니다.
이제 qml에서 어떤 방식으로 선택하게끔 처리하는지 아래 코드를 확입합니다.
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 1.4
import qml.register 1.0
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: qsTrId("TRID_HEELO")
ColumnLayout {
width: parent.width
height: parent.height
ComboBox {
Layout.preferredWidth: 100
Layout.preferredHeight: 30
Layout.alignment: Qt.AlignTop
model: ListModel {
id: listModel
ListElement { text: qsTrId("TRID_KOREAN"); idx: EnumClass.TRINFO_KOR }
ListElement { text: qsTrId("TRID_JAPAN"); idx: EnumClass.TRINFO_JP }
ListElement { text: qsTrId("TRID_ENGLISH"); idx: EnumClass.TRINFO_ENG }
}
onCurrentIndexChanged: {
trClass.language = listModel.get(currentIndex).idx
}
}
Text {
id: txt
text: qsTrId("TRID_MSG1")
Layout.fillHeight: true
Layout.fillWidth: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 20
}
}
}
ts파일에 지정했던 ID값을 qml에서 제공하는 qsTrId function을 사용해 ID값을 호출하면 언어 설정에 맞게 UI에 보일 수 있게 처리합니다.
그리고 메뉴탭에 언어 선택시 trClass에 선언한 language property를 변경하여 trclass setlanguage function을 호출하여 선택된 언어를 load하게 합니다.
맨위에 영상처럼 언어 선택시 유동적으로 UI에 언어가 바뀌는 것을 볼 수 있습니다.