这似乎是一个愚蠢的问题,但是我很难在QT 5.12中使国际化顺利进行。
我至少要做两件事:
关于第一点,我知道要安装系统本地语言的翻译,可以使用Translator.load("qt_" + QLocale::system().name(),QLibraryInfo::location(QLibraryInfo::TranslationsPath))
之类的东西。
第二点,我找到了一个解决方案,但是它要求我在发布/调试文件夹中放置一个名称为translation
的文件夹(在这种情况下),在其中放置单个.qm
文件。
我将提供一个到目前为止我发现的简单示例:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QFontDatabase>
#include <QFont>
#include <QtQml>
#include "trans.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QTranslator Translator;
Translator.load(":/translations/translating-qml_ru.qm");
app.installTranslator(&Translator);
QQmlApplicationEngine engine;
// object of our class with "magic" property for translation
Trans trans(&engine);
// make this object available from QML side
engine.rootContext()->setContextProperty("trans", &trans);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
main.qml
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
ApplicationWindow {
id: root
width: 800
minimumWidth: 500
height: 600
minimumHeight: 600
visible: true
title: "Translating QML application"
Column {
width: parent.width * 0.95
spacing: 15
padding: 15
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
Button {
Layout.preferredWidth: 76
Layout.preferredHeight: 53
text:"EN"
onClicked: {
onClicked: trans.selectLanguage("en");
}
}
Rectangle
{
Layout.preferredWidth: 2
Layout.fillHeight: true
Layout.margins: 10
color: "black"
}
Button {
text: "RU"
Layout.preferredWidth: 76
Layout.preferredHeight: 53
onClicked: {
onClicked: trans.selectLanguage("ru");
}
}
Rectangle
{
Layout.preferredWidth: 2
Layout.fillHeight: true
Layout.margins: 10
color: "black"
}
Button {
text: "NO"
Layout.preferredWidth: 76
Layout.preferredHeight: 53
onClicked: {
onClicked: trans.selectLanguage("no");
}
}
Rectangle
{
Layout.preferredWidth: 2
Layout.fillHeight: true
Layout.margins: 10
color: "black"
}
Button {
text: "DE"
Layout.preferredWidth: 76
Layout.preferredHeight: 53
onClicked: {
onClicked: trans.selectLanguage("de");
}
}
}
Label {
font.pixelSize: 16
text: qsTr("I woke up after midnight and realised - <b>IT DOES</b>!<br/>"
+ "Everything goes according to the plan.")
}
}
}
trans.cpp
#include "trans.h"
Trans::Trans(QQmlEngine *engine)
{
_translator = new QTranslator(this);
_engine = engine;
}
void Trans::selectLanguage(QString language)
{
QString languagesArray[] = { "en", "pt", "es", "br", "de", "dk", "fi", "fr", "it", "lt", "no", "ro", "tr", "hu" };
QDir dir = QDir(qApp->applicationDirPath()).absolutePath();
for(int i=0;i<languagesArray->length();i++){
if(languagesArray[i] != language){
_translator->load(QString("Lang-%1").arg(languagesArray[i]),QString("%1/translation").arg(dir.path()));
qApp->removeTranslator(_translator);
}
}
if (!_translator->load(
QString("translating-qml_%1").arg(language),
// look for the file in translations folder within working directory
QString("%1/translations").arg(dir.path())
)
)
{
qDebug() << "Failed to load translation file, falling back to English";
}
// it's a global thing, we can use it anywhere (after #including <QGuiApplication>)
qApp->installTranslator(_translator);
_engine->retranslate();
emit languageChanged();
}
trans.h
#ifndef TRANS_H
#define TRANS_H
#include <QObject>
#include <QTranslator>
#include <QDebug>
#include <QGuiApplication>
#include <QDir>
#include <QQmlEngine>
class Trans : public QObject
{
Q_OBJECT
public:
Trans(QQmlEngine *engine);
Q_INVOKABLE void selectLanguage(QString language);
signals:
void languageChanged();
private:
QTranslator *_translator;
QQmlEngine *_engine;
};
#endif // TRANS_H
我想逐步了解要使该系统完全正常运行所需要做的事情,因为我发现网上的信息(包括qt docs)使我感到困惑。
答案 0 :(得分:1)
首先将以下指令添加到.pro:
TRANSLATIONS = /path/of/some_name1.ts \
/path/of/some_name2.ts \
/path/of/some_name3.ts
在我的示例中,我使用以下结构:
TARGET = AppTranslations
# ...
TRANSLATIONS = i18n/$${TARGET}_en.ts \
i18n/$${TARGET}_de.ts \
i18n/$${TARGET}_no.ts \
i18n/$${TARGET}_ru.ts
然后,您必须在.pro所在的文件夹中打开终端或CMD并执行以下命令:
lupdate your_project.pro
这会在您指定的位置生成.ts,然后您必须使用Qt语言学家来编辑该文件进行翻译。
然后使用以下命令将.ts转换为.qm:
lrelease your_project.pro
然后,您可以将.qm添加到嵌入应用程序中的qresource中,但就我而言,我更喜欢将其放在可执行文件侧面的文件夹中,这样可执行文件不会占太大空间,并且可以添加更多翻译而无需重新编译项目,并使其自动化,将下一个命令复制到可执行文件的一侧。
COPY_CONFIG = $$files(i18n/*.qm, true)
copy_cmd.input = COPY_CONFIG
copy_cmd.output = i18n/${QMAKE_FILE_IN_BASE}${QMAKE_FILE_EXT}
copy_cmd.commands = $$QMAKE_COPY_DIR ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy_cmd.CONFIG += no_link_no_clean
copy_cmd.variable_out = PRE_TARGETDEPS
QMAKE_EXTRA_COMPILERS += copy_cmd
因此,构建文件夹最终将具有以下结构:
├── AppTranslations
├── i18n
│ ├── AppTranslations_de.qm
│ ├── AppTranslations_en.qm
│ ├── AppTranslations_no.qm
│ └── AppTranslations_ru.qm
│ ...
现在您有了.qm,将实现在应用程序中使用它的逻辑。在Qt 5.10之前,您必须技巧一下,添加一个空字符串以使翻译正常工作,但是最新版本不需要。
在我的情况下,我实现了获取.qm的逻辑,因此由于我使用默认格式,所以可用的语言为:
{Name_Of_Application}_{lang}.qm
该逻辑的另一部分与您的相似,因此我将不做过多详细介绍,而是向您展示代码:
translator.h
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include <QDir>
#include <QObject>
#include <QQmlEngine>
#include <QTranslator>
class Translator : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList languages READ languages NOTIFY languagesChanged)
Q_PROPERTY(QString currentLanguage READ currentLanguage NOTIFY currentLanguageChanged)
public:
explicit Translator(QQmlEngine *engine, QObject *parent = nullptr);
Q_INVOKABLE void selectLanguage(const QString & language);
QStringList languages() const;
QString currentLanguage() const;
Q_INVOKABLE static QString languageByCode(const QString & code);
signals:
void languageChanged();
void languagesChanged();
void currentLanguageChanged();
private:
const QString extension = ".qm";
QQmlEngine *m_engine;
QTranslator *m_translator;
QStringList m_languages;
QString m_currentLanguage;
QDir m_dir;
};
#endif // TRANSLATOR_H
translator.cpp
#include "translator.h"
#include <QGuiApplication>
#include <QDirIterator>
#include <QSettings>
Translator::Translator(QQmlEngine *engine, QObject *parent) :
QObject(parent),
m_engine(engine)
{
m_translator = new QTranslator(this);
m_dir = QDir(QGuiApplication::applicationDirPath(),
"*"+extension,
QDir::Name|QDir::IgnoreCase,
QDir::Files);
m_dir.cd("i18n");
m_languages.clear();
for(QString entry: m_dir.entryList()){
entry.remove(0, QGuiApplication::applicationName().length()+1);
entry.chop(extension.length());
m_languages.append(entry);
}
emit languagesChanged();
QSettings settings;
QString lang =settings.value("Language/current", QLocale::system().bcp47Name()).toString();
selectLanguage(lang);
}
QStringList Translator::languages() const
{
return m_languages;
}
QString Translator::currentLanguage() const
{
return m_currentLanguage;
}
QString Translator::languageByCode(const QString &code)
{
QLocale lo(code);
return QLocale::languageToString(lo.language());
}
void Translator::selectLanguage(const QString &language)
{
qApp->removeTranslator(m_translator);
if(m_languages.contains(language)){
QString file = QString("%1_%2%3").arg(QGuiApplication::applicationName()).arg(language).arg(extension);
if(m_translator->load(m_dir.absoluteFilePath(file))){
m_currentLanguage = language;
QSettings settings;
settings.setValue("Language/current", language);
emit currentLanguageChanged();
}
}
qApp->installTranslator(m_translator);
m_engine->retranslate();
emit languageChanged();
}
然后将其应用于您的项目:
main.cpp
#include "translator.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setOrganizationName("Translations INC");
QCoreApplication::setOrganizationDomain("translations.com");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Translator trans(&engine);
engine.rootContext()->setContextProperty("trans", &trans);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
ApplicationWindow {
id: root
width: 800
minimumWidth: 500
height: 600
minimumHeight: 600
visible: true
title: "Translating QML application"
Column {
width: parent.width * 0.95
spacing: 15
padding: 15
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
Repeater{
model: trans.languages
Button{
id: btn
property string code: modelData
text: trans.languageByCode(code)
onClicked: trans.selectLanguage(btn.code)
Layout.preferredWidth: 100
Layout.preferredHeight: 50
highlighted: code == trans.currentLanguage
}
}
}
Label {
font.pixelSize: 16
text: qsTr("I woke up after midnight and realised - <b>IT DOES</b>!<br/>"
+ "Everything goes according to the plan.")
}
}
}
找到完整的示例here。