QT 工程中快速实现中英文切换(含动态切换)

在 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 格式,存储 "原始字符串 - 目标语言字符串" 的映射,生成步骤:

  1. 打开 QT Creator 的 终端(或系统终端,切换到工程根目录);

  2. 执行以下命令生成 / 更新.ts 文件:

    复制代码
    # 生成ts文件(首次执行)
    lupdate -pro 你的工程名.pro -ts translations/zh_CN.ts translations/en_US.ts
    # 后续修改代码后,更新ts文件(同步新增的tr()字符串)
    lupdate 你的工程名.pro

执行后,translations目录下会生成zh_CN.tsen_US.ts文件。

四、编辑翻译文件(填写对应语言的字符串)

用 QT 自带的 Linguist(翻译工具) 打开.ts 文件,填写翻译内容:

  1. 打开 QT Linguist(QT Creator 中:工具 → 外部 → Qt Linguist → Qt Linguist);
  2. 分别打开zh_CN.tsen_US.ts,按以下规则编辑:
    • 若原始字符串是中文(比如tr("确定")):
      • zh_CN.ts:保持翻译为中文(或补充更精准的表述);
      • en_US.ts:将 "确定" 翻译为 "OK","加载完成" 翻译为 "Loaded successfully";
    • 若原始字符串是英文:反之,中文.ts 文件填写对应中文翻译。
  3. 编辑完成后,点击 Linguist 工具栏的 保存 (Ctrl+S),再点击 发布 (Ctrl+Shift+R),生成二进制翻译文件 .qm(最终程序加载的是.qm 文件)。

快捷方式:QT Creator 中右键.ts 文件 → 选择 "发布",可直接生成.qm 文件。

五、实现动态语言切换(核心逻辑)

通过 QTranslator 加载不同语言的.qm 文件,实现 "一键切换" 且无需重启程序。

1. 新建语言管理类(单例模式,方便全局调用)

新建 LanguageManager.hLanguageManager.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);
    }
}

六、部署与测试

  1. 确认 qm 文件路径 :程序运行时,translations目录需和可执行文件在同一级目录(或通过绝对路径加载);
    • QT Creator 中可在 "项目 → 构建步骤 → 部署" 中添加 "复制文件",将translations目录复制到构建目录;
  2. 测试切换功能:运行程序,点击 "切换语言" 按钮,观察所有控件文本是否实时切换为中文 / 英文;
  3. 排查问题
    • 若文本未切换:检查字符串是否用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 文件即可。

相关推荐
fpl111610 小时前
npm :无法加载文件 D:\...\nodejs\npm.ps1,因为在此系统上禁止运行脚本
前端·vscode·npm·node.js·命令模式
ZouZou老师1 天前
C++设计模式之命令模式:以家具生产为例
c++·设计模式·命令模式
雨中飘荡的记忆6 天前
设计模式之命令模式详解
设计模式·命令模式
小生不才yz6 天前
设计模式 - 命令模式
设计模式·命令模式
开心香辣派小星7 天前
23种设计模式-13命令模式
设计模式·命令模式
太阳以西阿8 天前
【VTK 】 02 锥体旋转起来获取到相机位置
数码相机·命令模式
ZHE|张恒12 天前
设计模式(十八)命令模式 —— 将操作封装成对象,实现撤销、队列等扩展
设计模式·命令模式
q***188414 天前
SpringDoc和Swagger使用
命令模式
明洞日记15 天前
【设计模式手册013】命令模式 - 请求封装的优雅之道
java·设计模式·命令模式