输入关键词开始搜索

Qt 资源系统与国际化

Qt 资源系统 (.qrc)

把图片、图标、QSS、配置文件编译进可执行文件。

<!-- resources.qrc -->
<RCC>
    <qresource prefix="/icons">
        <file>icons/save.png</file>
        <file>icons/open.png</file>
    </qresource>
    <qresource prefix="/styles">
        <file>styles/dark.qss</file>
    </qresource>
    <qresource prefix="/">
        <file>config.json</file>
    </qresource>
</RCC>
// 代码中使用
QPixmap(":/icons/save.png");           // prefix + 文件名
QIcon(":/icons/open.png");
setStyleSheet(loadFile(":/styles/dark.qss"));

// 路径规则::/前缀/文件名
// ⚠️ 路径大小写敏感

CMake 配置

qt_add_resources(MyApp "app_resources"
    PREFIX "/"
    FILES
        resources.qrc
)

国际化 (i18n) 三步走

第一步:代码中用 tr()

// 所有用户可见字符串用 tr() 包裹
label->setText(tr("Hello World"));
button->setText(tr("Save"));

// tr() 支持参数
statusBar()->showMessage(tr("%1 files processed").arg(count));

// 处理复数
tr("%n file(s) saved", "", n);  // n=1 时显示 "1 file saved"

// QObject 子类自动有 tr();非 QObject 用 QCoreApplication::translate()
QCoreApplication::translate("MyClass", "Hello");

第二步:生成 .ts 翻译文件

# 在 .pro 文件中声明
TRANSLATIONS = myapp_zh_CN.ts myapp_ja.ts

# 或用 lupdate 命令行
lupdate main.cpp widget.cpp -ts myapp_zh_CN.ts

生成的 .ts 文件结构:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
    <name>MainWindow</name>
    <message>
        <source>Hello World</source>
        <translation>你好,世界</translation>
    </message>
</context>
</TS>

第三步:编译 .qm 并加载

# 用 Qt Linguist 编辑 .ts → 或用 lrelease 编译
lrelease myapp_zh_CN.ts   # 生成 myapp_zh_CN.qm
#include <QTranslator>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QTranslator translator;
    if (translator.load(":/myapp_zh_CN.qm")) {
        app.installTranslator(&translator);
    }

    // ...
    return app.exec();
}

运行时语言切换

class LanguageManager {
    QMap<QString, QTranslator *> m_translators;
public:
    void install(const QString &lang, const QString &qmPath) {
        auto *t = new QTranslator(this);
        if (t->load(qmPath)) {
            qApp->installTranslator(t);
            m_translators.insert(lang, t);
        }
    }

    void switchTo(const QString &lang) {
        // 移除所有旧翻译
        for (auto *t : m_translators)
            qApp->removeTranslator(t);

        // 安装目标语言
        auto *t = m_translators.value(lang);
        if (t) qApp->installTranslator(t);

        // 通知所有控件刷新
        emit languageChanged();
    }
signals:
    void languageChanged();
};

控件刷新

// QWidget 重写 changeEvent
void MainWindow::changeEvent(QEvent *event) override {
    if (event->type() == QEvent::LanguageChange) {
        // Qt 自动刷新通过 UI 文件创建的控件
        // 手动设置的文字需要在这里重新设置
        ui->retranslateUi(this);  // 重新翻译 UI 文件
        updateDynamicTexts();      // 手动更新的文字
    }
    QMainWindow::changeEvent(event);
}

void MainWindow::updateDynamicTexts() {
    m_statusLabel->setText(tr("Ready"));
    setWindowTitle(tr("My Application"));
}

常见问题

// ❌ 不要用 #define 或 const char * 存可翻译字符串
const char *msg = "Hello";  // lupdate 扫描不到宏定义

// ✅ 直接用 tr()
label->setText(tr("Hello"));

// ❌ 字符串拼接会破坏翻译查找
label->setText(tr("Hello " + name));  // 不好

// ✅ 用 %1 占位符
label->setText(tr("Hello %1").arg(name));

文件组织建议

project/
├── resources.qrc
├── icons/              # 图标 → 编译进 .qrc
│   ├── save.png
│   └── open.png
├── styles/             # QSS → 编译进 .qrc
│   ├── light.qss
│   └── dark.qss
└── translations/       # .ts/.qm — 不编译进 .qrc(太大)
    ├── myapp_zh_CN.ts
    ├── myapp_zh_CN.qm
    ├── myapp_ja.ts
    └── myapp_ja.qm