
在 QT 工程中快速实现中英文切换(含动态切换),核心是 QT 国际化机制(i18n) + 动态语言切换逻辑,无需大幅修改原有代码,步骤如下(兼容 QT 5/6):
一、前期准备:工程配置(确保支持国际化)
首先确认工程文件(.pro)已启用国际化模块,若没有则添加:
# 启用QT国际化模块
QT += core gui widgets
TRANSLATIONS += \
translations/zh_CN.ts # 中文版翻译文件
translations/en_US.ts # 英文版翻译文件
# 可选:指定翻译文件输出目录(自动创建)
TRANSLATIONS_DIR = translations
添加后重新构建工程(qmake + 构建),确保translations目录自动生成。
多语言切换同理:
修改工程文件(
.pro),添加所有需要支持的语言翻译文件(按语言代码.ts命名,遵循 ISO 639-1 标准):pro
QT += core gui widgets # 启用国际化模块 TRANSLATIONS += \ translations/zh_CN.ts # 中文(中国大陆) translations/en_US.ts # 英文(美国) translations/ja_JP.ts # 日文(日本) translations/ko_KR.ts # 韩文(韩国) translations/fr_FR.ts # 法文(法国) # 可选:自动创建翻译目录 TRANSLATIONS_DIR = translations # 可选:指定生成qm文件的目录(与ts同目录) QMAKE_LRELEASE_FLAGS += -silent添加后执行 qmake + 构建 ,确保
translations目录自动生成。
二、替换所有硬编码字符串(关键步骤)
将工程中所有直接写死的中文 / 英文,替换为 QT 国际化宏 tr()(UI 文件和代码文件分别处理):
1. UI 文件(.ui)中的字符串
用 Qt Designer 打开 UI 文件,直接在控件的 text 属性 中写原始字符串(比如中文 "确定"、英文 "OK" 均可,后续翻译覆盖),QT 会自动将 UI 中的字符串纳入翻译体系(无需手动加tr())。
2. 代码文件(.cpp/.h)中的字符串
所有用户可见的字符串,必须用 tr() 包裹:
// 错误示例(硬编码)
QPushButton *btn = new QPushButton("确定");
statusBar()->showMessage("加载完成");
// 正确示例(支持国际化)
QPushButton *btn = new QPushButton(tr("确定"));
statusBar()->showMessage(tr("加载完成"));
- 注意:
tr()是QObject的成员函数,非 QObject 子类需手动添加Q_OBJECT宏并运行 qmake。 - 建议:原始字符串统一用 中文 或 英文(比如中文作为基准),后续翻译另一种语言。
三、生成翻译文件(.ts)
翻译文件(.ts)是 XML 格式,存储 "原始字符串 - 目标语言字符串" 的映射,生成步骤:
-
打开 QT Creator 的 终端(或系统终端,切换到工程根目录);
-
执行以下命令生成 / 更新.ts 文件:
# 生成ts文件(首次执行) lupdate -pro 你的工程名.pro -ts translations/zh_CN.ts translations/en_US.ts # 后续修改代码后,更新ts文件(同步新增的tr()字符串) lupdate 你的工程名.pro
执行后,translations目录下会生成zh_CN.ts和en_US.ts文件。
四、编辑翻译文件(填写对应语言的字符串)
用 QT 自带的 Linguist(翻译工具) 打开.ts 文件,填写翻译内容:
- 打开 QT Linguist(QT Creator 中:工具 → 外部 → Qt Linguist → Qt Linguist);
- 分别打开
zh_CN.ts和en_US.ts,按以下规则编辑:- 若原始字符串是中文(比如
tr("确定")):zh_CN.ts:保持翻译为中文(或补充更精准的表述);en_US.ts:将 "确定" 翻译为 "OK","加载完成" 翻译为 "Loaded successfully";
- 若原始字符串是英文:反之,中文.ts 文件填写对应中文翻译。
- 若原始字符串是中文(比如
- 编辑完成后,点击 Linguist 工具栏的 保存 (Ctrl+S),再点击 发布 (Ctrl+Shift+R),生成二进制翻译文件
.qm(最终程序加载的是.qm 文件)。
快捷方式:QT Creator 中右键.ts 文件 → 选择 "发布",可直接生成.qm 文件。
五、实现动态语言切换(核心逻辑)
通过 QTranslator 加载不同语言的.qm 文件,实现 "一键切换" 且无需重启程序。
1. 新建语言管理类(单例模式,方便全局调用)
新建 LanguageManager.h 和 LanguageManager.cpp:
// LanguageManager.h
#ifndef LANGUAGEMANAGER_H
#define LANGUAGEMANAGER_H
#include <QObject>
#include <QTranslator>
#include <QApplication>
class LanguageManager : public QObject
{
Q_OBJECT
public:
// 单例模式,全局唯一实例
static LanguageManager* instance();
// 切换语言(参数:"zh"=中文,"en"=英文)
void switchLanguage(const QString& lang);
signals:
// 语言切换完成信号(用于UI刷新)
void languageChanged();
private:
LanguageManager(QObject *parent = nullptr);
~LanguageManager() = default;
QTranslator m_translator; // 翻译器对象
static LanguageManager* m_instance; // 单例实例
};
#endif // LANGUAGEMANAGER_H
// LanguageManager.cpp
#include "LanguageManager.h"
#include <QDir>
LanguageManager* LanguageManager::m_instance = nullptr;
LanguageManager::LanguageManager(QObject *parent) : QObject(parent)
{
// 初始化时加载默认语言(比如中文)
switchLanguage("zh");
}
LanguageManager* LanguageManager::instance()
{
if (!m_instance) {
m_instance = new LanguageManager();
}
return m_instance;
}
void LanguageManager::switchLanguage(const QString& lang)
{
// 移除之前加载的翻译器
qApp->removeTranslator(&m_translator);
// 加载对应语言的qm文件(路径需和实际qm文件一致)
QString qmPath = QString("translations/%1_US.qm").arg(lang == "en" ? "en" : "zh_CN");
if (m_translator.load(qmPath)) {
qApp->installTranslator(&m_translator); // 安装翻译器
} else {
qWarning() << "加载翻译文件失败:" << qmPath;
}
// 发送语言切换信号,通知UI刷新
emit languageChanged();
}
2. UI 刷新逻辑(关键:让控件重新读取翻译)
QTranslator 安装后,已创建的控件不会自动刷新文本,需监听 languageChanged 信号,手动更新 UI:
方式 1:在主窗口中刷新(适合简单 UI)
在主窗口的构造函数中连接信号,并重写 changeEvent 事件:
// MainWindow.cpp
#include "MainWindow.h"
#include "LanguageManager.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 连接语言切换信号,刷新UI
connect(LanguageManager::instance(), &LanguageManager::languageChanged, this, [=](){
ui->retranslateUi(this); // 刷新UI文件中的控件文本(核心)
// 手动刷新代码中创建的控件文本(如果有)
refreshCustomWidgets();
});
// 绑定"切换语言"按钮(比如UI中有一个btn_switch)
connect(ui->btn_switch, &QPushButton::clicked, this, [=](){
// 切换语言(当前是中文则切英文,反之亦然)
static bool isChinese = true;
isChinese = !isChinese;
LanguageManager::instance()->switchLanguage(isChinese ? "zh" : "en");
});
}
// 刷新代码中创建的控件(示例)
void MainWindow::refreshCustomWidgets()
{
// 假设代码中创建了一个btn_custom
btn_custom->setText(tr("确定"));
statusBar()->showMessage(tr("加载完成"));
}
// 可选:监听系统语言变化(如果需要)
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this); // 系统语言变化时也刷新UI
refreshCustomWidgets();
}
}
MainWindow::~MainWindow()
{
delete ui;
}
方式 2:自定义控件自动刷新(适合复杂 UI)
如果有自定义控件,在控件中重写 changeEvent:
void MyCustomWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
// 刷新控件自身的文本
this->setText(tr("自定义控件文本"));
// 刷新子控件(如果有)
ui->retranslateUi(this);
}
}
六、部署与测试
- 确认 qm 文件路径 :程序运行时,
translations目录需和可执行文件在同一级目录(或通过绝对路径加载);- QT Creator 中可在 "项目 → 构建步骤 → 部署" 中添加 "复制文件",将
translations目录复制到构建目录;
- QT Creator 中可在 "项目 → 构建步骤 → 部署" 中添加 "复制文件",将
- 测试切换功能:运行程序,点击 "切换语言" 按钮,观察所有控件文本是否实时切换为中文 / 英文;
- 排查问题 :
- 若文本未切换:检查字符串是否用
tr()包裹、qm 文件是否正确生成并加载、UI 是否调用了retranslateUi; - 若 qm 文件加载失败:打印
qmPath,确认路径是否正确(比如相对路径、大小写是否匹配)。
- 若文本未切换:检查字符串是否用
七、简化版实现(无需单例类,适合简单工程)
如果工程较小,可直接在主窗口中实现切换逻辑,无需单独的LanguageManager:
// MainWindow.cpp
#include <QTranslator>
QTranslator translator;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始加载中文
translator.load("translations/zh_CN.qm");
qApp->installTranslator(&translator);
// 切换按钮绑定
connect(ui->btn_switch, &QPushButton::clicked, this, [=](){
static bool isEn = false;
qApp->removeTranslator(&translator);
if (isEn) {
translator.load("translations/zh_CN.qm");
} else {
translator.load("translations/en_US.qm");
}
qApp->installTranslator(&translator);
ui->retranslateUi(this); // 刷新UI
isEn = !isEn;
});
}
总结
核心步骤:tr()包裹字符串 → 生成 ts 文件 → 翻译并发布为 qm 文件 → 加载 qm 文件 + UI 刷新。该方案支持动态切换(无需重启) ,兼容性好,且后续可扩展更多语言(如日文、韩文),只需新增对应的 ts/qm 文件即可。