作者:小 琛
欢迎转载,请标明出处
需求分析
在Windows下,根据Windows操作系统当前的默认语言匹配对应语音包,实现国际化
Qt中的QTranslator模块
QTranslator,头文件<qtranslator.h>
源码:
class Q_CORE_EXPORT QTranslator : public QObject
{
Q_OBJECT
public:
explicit QTranslator(QObject *parent = nullptr);
~QTranslator();
virtual QString translate(const char *context, const char *sourceText,
const char *disambiguation = nullptr, int n = -1) const;
virtual bool isEmpty() const;
QString language() const;
QString filePath() const;
bool load(const QString & filename,
const QString & directory = QString(),
const QString & search_delimiters = QString(),
const QString & suffix = QString());
bool load(const QLocale & locale,
const QString & filename,
const QString & prefix = QString(),
const QString & directory = QString(),
const QString & suffix = QString());
bool load(const uchar *data, int len, const QString &directory = QString());
private:
Q_DISABLE_COPY(QTranslator)
Q_DECLARE_PRIVATE(QTranslator)
};
源码中实现了常用的一些内容,比如加载qm文件的接口load,这里不做具体讲述,实际使用的时候查阅即可
.qm:该文件是使用Qt语言家翻译后得到的文件
具体操作流程
这里直接上干货,究竟如何实现多语言。
- 将代码中所有文本内容用tr()包裹
- 自定义一个CLinguist类,继承QObject即可。根据个人需要进行封装,例如,为了在每个窗口都可以使用,我将它封装为单例。
enum Language {
zh_cn,
en_us,
undefined
};
class CLinguist :public QObject {
Q_OBJECT
private:
CLinguist();
public:
void changeLanguage(Language lan);
static CLinguist* getLinguistInstance();
private:
static CLinguist* m_pLinguist;
QTranslator* m_pTrans;
Language m_currentLanguage = Language::undefined;
signals:
void languageChaned();
};
- 类内成员包括QTranslator的指针,后续的操作均使用这个类成员
- m_currentLanguage 来记录当前语言,这里采用枚举的方式,我实现了英语和中文
- languageChaned()是一个信号,在语言改变时触发,其它界面绑定这个信号即可
enum Language {
zh_cn,
en_us,
undefined
};
类的实现:
#include "Linguist.h"
#include <qcoreapplication.h>
CLinguist* CLinguist::m_pLinguist = nullptr;
CLinguist::CLinguist() {
m_pTrans = new QTranslator;
}
CLinguist* CLinguist::getLinguistInstance() {
if (nullptr == m_pLinguist) {
m_pLinguist = new CLinguist;
}
return m_pLinguist;
}
void CLinguist::changeLanguage(Language lan) {
if (lan == this->m_currentLanguage || lan == Language::undefined) {
return;
}
bool ret = false;
switch (lan) {
case zh_cn:
if (nullptr != m_pTrans) {
qApp->removeTranslator(m_pTrans);
}
ret = m_pTrans->load(":/file/file/Translation_zh.qm");
if (ret) {
bool install = qApp->installTranslator(m_pTrans);
if (install == false) {
MyLogger::Log::error("install translator error");
}
} else {
MyLogger::Log::error("load translation file error");
}
break;
case en_us:
if (nullptr != m_pTrans) {
qApp->removeTranslator(m_pTrans);
}
ret = m_pTrans->load(":/file/file/Translation_en.qm");
if (ret) {
bool install = qApp->installTranslator(m_pTrans);
if (install == false) {
MyLogger::Log::error("install translator error");
}
} else {
MyLogger::Log::error("load translation file error");
}
break;
default:
break;
}
if (ret) {
this->m_currentLanguage = lan;
emit languageChaned();
}
}
-
将该窗口内所有的设置文本类内容,封装成一个槽函数,在类的构造函数中,将该槽函数和languageChaned()绑定
-
在工程的翻译文件下添加->Qt->Translation File->选择自己的语言
随后,右击该文件,lupdate lrelease
打开拓展->Qt vs Tools->Launch Qt Linguist
文件->打开刚刚新建的ts文件,对文本进行翻译->文件 发布
即可得到想要的qm文件
一定要注意,这里的qm文件路径,要和CLinguist::changeLanguage中加载的路径对应,否则加载失败是不能翻译的 -
我们来简单测试一下,页面上加一个comboBox,让用户可以自主选择语言。这里控件的代码就不贴了,具体根据自己情况而定,仅贴切换使用的槽函数
void Uninstall::onChangeLanguage(int index) {
CLinguist* lin = CLinguist::getLinguistInstance();
switch (index) {
case 0:
lin->changeLanguage(Language::zh_cn); break;
case 1:
lin->changeLanguage(Language::en_us); break;
default:
break;
}
}
- 在main中设置一下初始语言
CLinguist* lin = CLinguist::getLinguistInstance();
lin->changeLanguage(Language::zh_cn);
大功告成:
Windows下语言类接口
前面实现的功能,做到了根据用户选择实时切换,那么设置初始的默认语言就更简单了,只需要判断当前操作系统语言是什么,调用封装好的接口,加载就行了,唯一要讲述的,是Windows操作系统下的语言类API
推荐使用unsigned short GetUserDefaultUILanguage();
返回值对应不同的语言,下面是常用的语言标准,直接用16进制判断就可以,当然也可以宏定义一下
/*
{0x0804, “CN”, “zh”, “zh_CN”},//中国
{0x0409, “US”, “en”, “en_US”},//美国
{0x0412, “KR”, “ko”, “ko_KR”},//韩国
{0x0411, “JP”, “ja”, “ja_JP”},//日本
{0x0421, “ID”, “en”, “en_ID”},//印度尼西亚
{0x0407, “DE”, “de”, “de_DE”},//德国
{0x040c, “FR”, “fr”, “fr_Fr”},//法国
{0x0410, “IT”, “it”, “it_IT”},//意大利
{0x0416, “BR”, “pt”, “pt_BR”},//葡萄牙
{0x0c0a, “ES”, “es”, “es_Es”},//西班牙
{0x0419, “RU”, “ru”, “ru_RU”},//俄国
{0x041f, “TR”, “tr”, “tr_TR”},//土耳其
{0x042a, “VI”, “vi”, “vi_VI”},//越南
{0x041e, “TH”, “en”, “en_TH”},//泰国
{0x0809, “GB”, “en”, “en_US”},//英国
*/
CLinguist* lin = CLinguist::getLinguistInstance();
unsigned short type = GetUserDefaultUILanguage();
if (type == zh_CN) {
lin->changeLanguage(Language::zh_cn);
} else {
lin->changeLanguage(Language::en_us);
}
部分源码
注意:里面的Log.h是我自己的日志系统,写代码注意保留日志,使用删除即可
CLinguist.h
#pragma once
#include <QObject>
#include <qtranslator.h>
#include "Log.h"
enum Language {
zh_cn,
en_us,
undefined
};
#define zh_CN 0x0804
#define zh_Us 0x0809
/*
{0x0804, "CN", "zh", "zh_CN"},//中国
{0x0409, "US", "en", "en_US"},//美国
{0x0412, "KR", "ko", "ko_KR"},//韩国
{0x0411, "JP", "ja", "ja_JP"},//日本
{0x0421, "ID", "en", "en_ID"},//印度尼西亚
{0x0407, "DE", "de", "de_DE"},//德国
{0x040c, "FR", "fr", "fr_Fr"},//法国
{0x0410, "IT", "it", "it_IT"},//意大利
{0x0416, "BR", "pt", "pt_BR"},//葡萄牙
{0x0c0a, "ES", "es", "es_Es"},//西班牙
{0x0419, "RU", "ru", "ru_RU"},//俄国
{0x041f, "TR", "tr", "tr_TR"},//土耳其
{0x042a, "VI", "vi", "vi_VI"},//越南
{0x041e, "TH", "en", "en_TH"},//泰国
{0x0809, "GB", "en", "en_US"},//英国
*/
class CLinguist :public QObject {
Q_OBJECT
private:
CLinguist();
public:
void changeLanguage(Language lan);
static CLinguist* getLinguistInstance();
private:
static CLinguist* m_pLinguist;
QTranslator* m_pTrans;
Language m_currentLanguage = Language::undefined;
signals:
void languageChaned();
};
CLinguist.cpp
```cpp
#include "Linguist.h"
#include <qcoreapplication.h>
CLinguist* CLinguist::m_pLinguist = nullptr;
CLinguist::CLinguist() {
m_pTrans = new QTranslator;
}
CLinguist* CLinguist::getLinguistInstance() {
if (nullptr == m_pLinguist) {
m_pLinguist = new CLinguist;
}
return m_pLinguist;
}
void CLinguist::changeLanguage(Language lan) {
if (lan == this->m_currentLanguage || lan == Language::undefined) {
return;
}
bool ret = false;
switch (lan) {
case zh_cn:
if (nullptr != m_pTrans) {
qApp->removeTranslator(m_pTrans);
}
ret = m_pTrans->load(":/file/file/Translation_zh.qm");
if (ret) {
bool install = qApp->installTranslator(m_pTrans);
if (install == false) {
MyLogger::Log::error("install translator error");
}
} else {
MyLogger::Log::error("load translation file error");
}
break;
case en_us:
if (nullptr != m_pTrans) {
qApp->removeTranslator(m_pTrans);
}
ret = m_pTrans->load(":/file/file/Translation_en.qm");
if (ret) {
bool install = qApp->installTranslator(m_pTrans);
if (install == false) {
MyLogger::Log::error("install translator error");
}
} else {
MyLogger::Log::error("load translation file error");
}
break;
default:
break;
}
if (ret) {
this->m_currentLanguage = lan;
emit languageChaned();
}
}