概述:支持国际化是软件发布的基本项。Qt 提供了完整的国际化解决方案。

0x01、Qt 国际化概述

Qt 安装时,带了一个 Qt Linguist 的软件,这是 Qt 用来实现软件翻译的工具。Qt 内置的字体引擎可以在同一时间正确绘制包含不同书写系统字符的文本。

国际化流程

源码中使用 tr() → 修改 .pro 文件 → 生成 .ts 文件 → 使用 Linguist 翻译 → 发布 .qm 文件 → 运行时加载

0x02、使用 tr() 函数

基本用法

// 所有需要翻译的字符串都用 tr() 包裹
label->setText(tr("Hello World"));
button->setText(tr("Save"));
 
// 带上下文
tr("File", "菜单项");  // "菜单项" 是上下文,帮助翻译者理解

格式化字符串

// 使用 %1, %2 等占位符
QString msg = tr("Processing %1 of %2 files").arg(current).arg(total);
 
// 复数形式
QString msg = tr("%n file(s) found", nullptr, count);

不需要翻译的字符串

// 使用 QStringLiteral 或 QLatin1String
const char* version = "1.0.0";  // 不需要翻译
QString url = QStringLiteral("https://example.com");  // 不需要翻译

0x03、修改 .pro 文件

# 添加翻译文件
TRANSLATIONS += \
    translations/myapp_zh_CN.ts \
    translations/myapp_en_US.ts \
    translations/myapp_ja_JP.ts
 
# 指定编码
CODECFORSRC = UTF-8

0x04、生成和更新翻译文件

使用命令行

# 生成/更新 .ts 文件
lupdate myapp.pro
 
# 指定输出目录
lupdate src -ts translations/myapp_zh_CN.ts
 
# 发布 .qm 文件
lrelease translations/myapp_zh_CN.ts

使用 Qt Creator

  1. 菜单:工具 → 外部 → Qt语言家 → 更新翻译 (lupdate)
  2. 翻译完成后:工具 → 外部 → Qt语言家 → 发布翻译 (lrelease)

0x05、使用 Qt Linguist

  1. 打开 .ts 文件
  2. 选择需要翻译的字符串
  3. 输入翻译内容
  4. 标记为”已完成”
  5. 保存并发布

0x06、运行时切换语言

加载翻译文件

#include <QTranslator>
#include <QLocale>
 
class LanguageManager : public QObject
{
    Q_OBJECT
public:
    static LanguageManager* instance()
    {
        static LanguageManager manager;
        return &manager;
    }
    
    bool loadLanguage(const QString &language)
    {
        // 移除旧翻译器
        if (m_translator) {
            qApp->removeTranslator(m_translator);
            delete m_translator;
        }
        
        m_translator = new QTranslator();
        
        QString translationFile = QString(":/translations/myapp_%1.qm")
                                    .arg(language);
        
        if (m_translator->load(translationFile)) {
            qApp->installTranslator(m_translator);
            m_currentLanguage = language;
            emit languageChanged();
            return true;
        }
        
        delete m_translator;
        m_translator = nullptr;
        return false;
    }
    
    QString currentLanguage() const { return m_currentLanguage; }
    
signals:
    void languageChanged();
    
private:
    LanguageManager() : m_translator(nullptr) {}
    QTranslator *m_translator;
    QString m_currentLanguage;
};

动态切换语言

// 切换语言
void MainWindow::switchLanguage(const QString &language)
{
    if (LanguageManager::instance()->loadLanguage(language)) {
        // 刷新界面
        retranslateUi();
    }
}
 
// 刷新界面文本
void MainWindow::retranslateUi()
{
    m_label->setText(tr("Hello World"));
    m_button->setText(tr("Save"));
    // ... 刷新所有需要翻译的控件
}
 
// 重写 changeEvent
void MainWindow::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::LanguageChange) {
        retranslateUi();
    }
    QMainWindow::changeEvent(event);
}

0x07、完整示例

// main.cpp
#include <QApplication>
#include <QTranslator>
#include <QLocale>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    // 自动加载系统语言
    QTranslator translator;
    QString locale = QLocale::system().name();  // 如 "zh_CN"
    if (translator.load(QString(":/translations/myapp_%1.qm").arg(locale))) {
        a.installTranslator(&translator);
    }
    
    MainWindow w;
    w.show();
    
    return a.exec();
}
 
// mainwindow.cpp
#include "mainwindow.h"
#include <QMenu>
#include <QAction>
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    createMenus();
    retranslateUi();
}
 
void MainWindow::createMenus()
{
    m_fileMenu = menuBar()->addMenu("");
    
    m_newAction = new QAction(this);
    m_openAction = new QAction(this);
    m_saveAction = new QAction(this);
    m_exitAction = new QAction(this);
    
    m_fileMenu->addAction(m_newAction);
    m_fileMenu->addAction(m_openAction);
    m_fileMenu->addAction(m_saveAction);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_exitAction);
    
    // 连接信号槽
    connect(m_exitAction, &QAction::triggered, this, &MainWindow::close);
}
 
void MainWindow::retranslateUi()
{
    m_fileMenu->setTitle(tr("&File"));
    m_newAction->setText(tr("&New"));
    m_openAction->setText(tr("&Open"));
    m_saveAction->setText(tr("&Save"));
    m_exitAction->setText(tr("E&xit"));
}
 
void MainWindow::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::LanguageChange) {
        retranslateUi();
    }
    QMainWindow::changeEvent(event);
}
 
// 切换语言
void MainWindow::onLanguageChanged(const QString &language)
{
    LanguageManager::instance()->loadLanguage(language);
}

0x08、常见问题

翻译不生效

  1. 检查 .qm 文件路径是否正确
  2. 确保 installTranslator() 在界面创建之前调用
  3. 检查字符串是否使用 tr() 包裹

动态切换后界面不更新

  1. 重写 changeEvent 处理 LanguageChange 事件
  2. 手动调用 retranslateUi() 刷新界面

中文乱码

  1. 确保源文件编码为 UTF-8
  2. 在 .pro 中添加 CODECFORSRC = UTF-8
  3. 使用 QString::fromUtf8() 处理非 tr 包裹的中文字符串

更新时间: 2026-03-27