1 Qt语言家
Qt针对世界各个地区不同国家不同语言,给出了统一的国际化解决方案,那就是Qt语言家(如图1所示),英文名叫Linguist。在我们日常编码中,经常在代码中会出现一些字符串,在不同的语言环境下,可能会需要显示不同语言对应的文本。针对多语言切换的需求,Qt提供的解决方案是,在所有需要翻译的字符串处都使用QObject::tr()函数,Qt提取出所有QObject::tr()函数的参数,使用Qt语言家对其进行翻译后发布,Qt程序可以在运行时加载发布的翻译文件以更新文本字符串。Qt语言家不仅可以解决翻译的问题,同样也可以解决字符串乱码的问题。
注意:在使用MSVC编译器时,会有一些中文字符编译不通过,建议所有代码中的文本源字符以英文为首选,中文为翻译文本,这样就可以避免编译不通过或者字符串乱码等问题。
2 更新翻译
2.1 使用QtCreater更新翻译
若使用QtCreater进行开发应用程序,如图2所示,先在Qt的工程Pro文件中加入你需要生成的翻译文件,然后可以点击工具中的Qt语言家进行更新翻译,则Qt将会对源代码中使用QObject::tr()函数包裹的字符串以及UI界面上的字符串进行更新翻译。
点击更新翻译后会在指定的目录下生成TS文件,如图3所示,并使用语言家打开其中的文件,其实TS文件是一个XML格式的文件,里面包含有源文本,翻译文本以及注释,每一种语言的翻译对应一个TS文件。
2.2 使用命令行更新翻译
不管是使用命令行还是使用可视化工具,其使用的都是同一个东西,lupdate命令,如图4所示,用于更新翻译使用的,和上述所示是一样的,会生成两个TS文件
另外我们可以不使用Linguist进行翻译文本,可以直接打开TS文件,在对应的节点中写入要翻译的文本以及需要注释的文本即可,如图5所示,需要翻译的文本写入translation节点内,source为源字符串,location为需要翻译的文本所在代码中的位置。
3 发布翻译
3.1 使用QtCreater发布翻译
将TS文件翻译完成后,就剩下发布翻译了,发布翻译会生成两个QM文件,如图6所示,将该QM文件读取到Qt的翻译器中就可以进行国际化翻译了。具体可以参考QTranslator类。
3.2 使用命令行发布翻译
命令行发布翻译使用的命令为lrelease,如图7所示,其他内容和上述一样。
4 具体使用
新建国际化翻译类,每个语言对应一个翻译文件和枚举,在切换语言时,指定切换的语言枚举即可,另外,要做到实时切换,则需要在每个界面文件中重载changeEvent事件,调用retranslateUi(this)函数,进行重新载入。
注意:retranslateUi函数是在编译后生成的函数,不是Qt封装好的函数,需要在重新载入翻译文件时,手动调用,若不调用,则界面不会改变。
// 头文件
#ifndef TRANSLATERSINGLETON_H
#define TRANSLATERSINGLETON_H
#include <QObject>
#include <QTranslator>
#include <QMutex>
#include <QMap>
class TranslaterSingleton : public QObject
{
Q_OBJECT
public:
enum LanguageType
{
CHINESE_LANGUAGE,
ENGLISH_LANGUAGE,
MAX_LANGUAGE,
};
static TranslaterSingleton *getInstance();
bool switchLanguage(LanguageType languageType);
private:
explicit TranslaterSingleton(QObject *parent = nullptr);
void initValue();
private:
static QMutex m_mutex;
QTranslator m_translater;
QMap<LanguageType, QString> m_mapLanguage;
};
#endif // TRANSLATERSINGLETON_H
// 源文件
#include "translatersingleton.h"
#include <QApplication>
QMutex TranslaterSingleton::m_mutex;
TranslaterSingleton::TranslaterSingleton(QObject *parent) : QObject(parent)
{
this->initValue();
}
void TranslaterSingleton::initValue()
{
m_mapLanguage[CHINESE_LANGUAGE] = ":/translation/chinese.qm";
m_mapLanguage[ENGLISH_LANGUAGE] = ":/translation/english.qm";
}
TranslaterSingleton *TranslaterSingleton::getInstance()
{
QMutexLocker mutexLocker(&m_mutex);
static TranslaterSingleton instance;
return &instance;
}
bool TranslaterSingleton::switchLanguage(LanguageType languageType)
{
if (!m_mapLanguage.contains(languageType)) return false;
if (m_translater.load(m_mapLanguage.value(languageType)))
{
return qApp->installTranslator(&m_translater);
}
return false;
}
// 调用
TranslaterSingleton::getInstance()->switchLanguage(TranslaterSingleton::ENGLISH_LANGUAGE);
void changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
}