setting.h
#pragma once
#pragma execution_character_set("utf-8") // 编译时把程序里的字符串使用 UTF-8 进行处理
#include <QTranslator>
#include <QWidget>
#include <QMutex>
#include "ui_setting.h"
#include "vanxkr/config/config.h"
class Setting : public QWidget {
Q_OBJECT
public:
inline static Setting *Setting::getInstance() {
if (Q_NULLPTR == instance) {
QMutexLocker lock(&mutex);
if (Q_NULLPTR == instance) {
Setting *instance_ = new Setting();
instance = instance_;
}
}
return instance;
}
// 常量
const QMap<QString, QString> cLanguageMap = {
{"中文", "zh"},
{"English", "en"},
};
inline QTranslator& getTranslator() {
return translator;
}
public slots:
inline void setLanguage(const QString &language) {
ui.comboBox_language->blockSignals(true);
ui.comboBox_language->setCurrentText(language);
on_comboBox_language_currentTextChanged(language);
ui.comboBox_language->blockSignals(false);
}
protected:
void changeEvent(QEvent *event);
private:
Setting(QWidget *parent = Q_NULLPTR);
~Setting();
static Setting *instance;
static QMutex mutex;
class GC { // GC 机制 自动回收
public:
~GC() { // 可以在这里销毁所有的资源
if (Q_NULLPTR != instance) {
instance->deleteLater();
instance = Q_NULLPTR;
}
}
static GC gc; // 用于释放单例
};
// 常量
const QString cQmPrefix = ":/qm/";
Ui::Setting ui;
Config* config = Config::getInstance();
QString language = Q_NULLPTR;
QTranslator translator;
singnals:
void languageChanged(); // 直接发送语言切换 其他类不需要再写 changeEvent
private slots:
void initWidget(); //
void retranslateUi();
void setLanguagePrivate(const QString &language);
void on_comboBox_language_currentTextChanged(const QString &text);
};
setting.cpp
#pragma execution_character_set("utf-8") // 编译时把程序里的字符串使用 UTF-8 进行处理
#include <QDebug>
#include "setting.h"
Setting *Setting::instance = Q_NULLPTR;
QMutex Setting::mutex;
void Setting::changeEvent(QEvent *event) {
if (QEvent::LanguageChange == event->type()) {
emit languageChanged(); //
retranslateUi();
}
QWidget::changeEvent(event);
}
Setting::Setting(QWidget *parent)
: QWidget(parent) {
setWindowModality(Qt::ApplicationModal); // 打开子窗口 锁定父窗口
setWindowFlags(Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint); // 设置窗口只保留关闭按钮 且 固定大小
ui.setupUi(this);
initWidget();
}
Setting::~Setting() {
}
void Setting::initWidget() { //
QStringList languageList;
for (auto i = cLanguageMap.cbegin(); i != cLanguageMap.cend(); ++i) { // 只读
languageList.append(i.key());
}
ui.comboBox_language->blockSignals(true);
ui.comboBox_language->addItems(languageList);
ui.comboBox_language->blockSignals(false);
}
void Setting::retranslateUi() {
ui.retranslateUi(this);
}
void Setting::setLanguagePrivate(const QString &language) {
if (this->language != language) { //
this->language = language;
QString qm = cQmPrefix + cLanguageMap[language];
bool ret = translator.load(qm);
if (ret) { // 成功了才写入
config->iniWrite("Setting/language", language);
}
}
}
void Setting::on_comboBox_language_currentTextChanged(const QString &text) {
setLanguagePrivate(text);
}
translate.h
#pragma once
#pragma execution_character_set("utf-8") // 编译时把程序里的字符串使用 UTF-8 进行处理
#include <QtWidgets/QMainWindow>
#include "ui_translate.h"
#include "setting.h"
class Translate : public QMainWindow {
Q_OBJECT
public:
inline static Translate *Translate::getInstance() {
if (Q_NULLPTR == instance) {
QMutexLocker lock(&mutex);
if (Q_NULLPTR == instance) {
Translate *instance_ = new Translate();
instance = instance_;
}
}
return instance;
}
protected:
void changeEvent(QEvent *event);
private:
Translate(QWidget *parent = 0);
~Translate();
static Translate *instance;
static QMutex mutex;
class GC { // GC 机制 自动回收
public:
~GC() { // 可以在这里销毁所有的资源
if (Q_NULLPTR != instance) {
delete instance;
instance = Q_NULLPTR;
}
}
static GC gc; // 用于释放单例
};
Ui::Translate ui;
Setting* setting = Setting::getInstance();
QAction* actionSetting = new QAction();
private slots:
void retranslateUi();
void initWidget(); //
void initConnect();
};
translate.cpp
#pragma execution_character_set("utf-8") // 编译时把程序里的字符串使用 UTF-8 进行处理
#include <QDebug>
#include "translate.h"
Translate *Translate::instance = Q_NULLPTR;
QMutex Translate::mutex;
void Translate::changeEvent(QEvent *event) {
if(QEvent::LanguageChange == event->type()) {
retranslateUi();
}
QMainWindow::changeEvent(event);
}
Translate::Translate(QWidget *parent)
: QMainWindow(parent) {
ui.setupUi(this);
initWidget();
initConnect();
}
Translate::~Translate() {
delete actionSetting;
}
void Translate::retranslateUi() {
ui.retranslateUi(this);
actionSetting->setText(tr("设置(Setting)"));
}
void Translate::initWidget() { //
ui.menuBar->addAction(actionSetting);
}
void Translate::initConnect() {
connect(actionSetting, &QAction::triggered, this, [&]() {
setting->show();
});
}
main.cpp
#pragma execution_character_set("utf-8") // 编译时把程序里的字符串使用 UTF-8 进行处理
#include <QtWidgets/QApplication>
#include <QTextCodec>
#include <QDebug>
#include <QDir>
#include "translate.h"
Translate::GC Translate::GC::gc; // 单例
Setting::GC Setting::GC::gc; // 单例
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); // 使用 UTF-8 的运行时环境
QDir::setCurrent(QCoreApplication::applicationDirPath()); // 设置当前目录为 app所在目录
Setting* setting = Setting::getInstance();
a.installTranslator(&Setting::getInstance()->getTranslator());
setting->setLanguage(
Config::getInstance()->iniRead(
"Setting/language",
setting->cLanguageMap.cbegin().key()
).toString()
); // 加载配置文件语言
Translate::getInstance()->show();
return a.exec();
}
(╯#-_-)╯~~PS
动态翻译的关键在于:
- 对用户可见的文本信息全部使用
tr()
进行封装 (中文是可以的 此处反驳一下那些说不能用tr()
包中文的人 (#‵′)凸) - 使用
lupdate
导出项目翻译文件:.ts
(要多少种语言就导出多少种 项目使用的原始语言也要导出 只是在翻译时不需要进行任何翻译直接发布即可) - 使用
Qt Linguist
对.ts
文件进行翻译并发布成为.qm
- 项目中实现语言切换功能 顺序很重要:
- 先
QApplication
安装QTranslator
- 再使用
QTranslator::load
翻译文件.qm
(一定要记得要是上面安装的那个QTranslator
) - 以上操作成功即会给所有界面发送
changeEvent(QEvent::LanguageChange)
事件 - 在每一个对用户可见的文本信息显示的类里面实现并在以上的事件响应
retranslateUi()
操作 (ui文件已帮你实现retranslateUi(Ui::Class)翻译Ui自带的翻译内容 记得调用哦 (→_→))
- 先
以上<( ̄︶ ̄)>
有更好的方案欢迎骚扰 []~( ̄▽ ̄)~* vanxkr@qq.com(链接是打开QQ小窗)
ฅ(• - •)ฅ 喜欢就留个赞啵~ ฅʕ•̫͡•
补充 - 2021-3-2 17:29:37
在每一个界面写一次 void changeEvent(QEvent *event);
相对麻烦点
这里有一个方案
我是这么做的
- 在
setting.cpp
的void changeEvent(QEvent *event);
里面emit languageChanged();
信号 - 在其他界面
connect(setting, &Setting::languageChanged, this, &Class::retranslateUi);
即可