You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Qt桌面应用基础语言切换及tr()翻译字符串替换方案咨询

我来帮你解答这两个Qt桌面应用的国际化相关问题,都是实际项目里很常见的需求:

问题1:如何切换Qt桌面应用的基础语言

Qt的国际化支持核心靠QTranslator类加载编译好的翻译文件(.qm格式),具体分两种场景来说:

启动时加载指定语言

通常在main()函数里初始化翻译器,示例代码很直观:

#include <QApplication>
#include <QTranslator>
#include <QLocale>
#include <QDebug>

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

    QTranslator translator;
    // 这里假设你的英文翻译文件叫app_en.qm,放在资源文件或者可访问的本地路径
    QString targetLang = "en"; // 可以改成读取系统语言、配置文件或者用户选择的语言
    if (translator.load(QString("app_%1.qm").arg(targetLang))) {
        app.installTranslator(&translator);
        qDebug() << "英文翻译加载成功";
    } else {
        qDebug() << "英文翻译加载失败,会 fallback 到源代码里的字符串";
    }

    MainWindow w;
    w.show();

    return app.exec();
}

运行时动态切换语言

如果要做应用内切换语言的功能,步骤稍微多一点:

  1. 卸载当前的翻译器(如果有的话)
  2. 加载新的.qm文件并重新安装
  3. 触发所有UI控件刷新翻译——Qt Designer生成的UI类自带retranslateUi()方法,手动写的控件需要发送QEvent::LanguageChange事件

示例代码片段:

void MainWindow::switchToEnglish() {
    // 先清理旧的翻译器
    QTranslator* oldTrans = qApp->findChild<QTranslator*>();
    if (oldTrans) {
        qApp->removeTranslator(oldTrans);
        delete oldTrans;
    }

    // 加载新的英文翻译
    QTranslator* newTrans = new QTranslator(this);
    if (newTrans->load("app_en.qm")) {
        qApp->installTranslator(newTrans);
        // 刷新主窗口的UI翻译
        this->retranslateUi(this);
        // 子窗口或者自定义控件也要触发刷新,比如给它们发LanguageChange事件
        QEvent langEvent(QEvent::LanguageChange);
        QCoreApplication::sendEvent(childWidget, &langEvent);
    }
}
问题2:替换源代码中tr()的芬兰语字符串为英文的推荐方案

强烈不建议用正则表达式直接替换!别踩这个坑——Qt的tr()调用可能带上下文(比如tr("Close", "Window button")用来区分不同场景的相同字符串)、转义字符、复数形式(tr("%n file(s)", "", count)),正则根本没法准确识别这些情况,要么误替换,要么漏替换,后期排查起来头大。

符合Qt惯例的标准流程应该是这样:

第一步:用lupdate准确提取所有芬兰语字符串

Qt官方工具lupdate是专门干这个的,能精准识别所有tr()QT_TR_NOOP()等翻译标记,还能保留上下文信息。运行命令:

# 假设你的项目是用.pro文件管理的
lupdate your_app.pro -ts fi_source.ts

生成的fi_source.ts文件会包含源代码里所有芬兰语翻译字符串,以及它们所在的类、注释等元信息,绝对比正则靠谱。

第二步:用Qt Linguist把芬兰语翻译成英文

打开Qt Linguist(Qt自带的工具),导入fi_source.ts,把每个芬兰语条目翻译成对应的英文,保存文件。这一步确保翻译的准确性,还能处理复数、上下文这些特殊情况。

第三步:用脚本批量替换源代码里的tr内容

写个简单的脚本(比如Python)读取.ts文件里的翻译映射,然后遍历源代码替换tr()里的内容。这样既保证准确,又能处理大量文件。

给你个Python脚本的思路(需要安装lxml库解析XML格式的.ts文件):

from lxml import etree
import os

# 解析生成的.ts文件
tree = etree.parse("fi_source.ts")
root = tree.getroot()

# 构建「上下文+芬兰语」到「英文」的映射,避免同字符串不同上下文的冲突
trans_map = {}
for context in root.findall("context"):
    ctx_name = context.find("name").text
    for msg in context.findall("message"):
        finnish = msg.find("source").text
        english = msg.find("translation").text
        if finnish and english:
            trans_map[(ctx_name, finnish)] = english

# 遍历源代码目录,替换.cpp和.h文件里的tr内容
def update_tr_in_file(file_path):
    with open(file_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    # 先处理带上下文的tr调用,再处理不带的,避免冲突
    for (ctx, fin), eng in trans_map.items():
        content = content.replace(f'tr("{fin}", "{ctx}")', f'tr("{eng}", "{ctx}")')
        content = content.replace(f'tr("{fin}")', f'tr("{eng}")')
    
    with open(file_path, "w", encoding="utf-8") as f:
        f.write(content)

# 递归遍历src目录下的所有源文件
for dirpath, _, filenames in os.walk("./src"):
    for fname in filenames:
        if fname.endswith(".cpp") or fname.endswith(".h"):
            update_tr_in_file(os.path.join(dirpath, fname))

第四步:重新初始化国际化流程

替换完成后,运行lupdate生成新的以英文为源语言的.ts文件,之后就可以正常用Qt的国际化工具链(lupdate→Linguist→lrelease)做其他语言的翻译了:

lupdate your_app.pro -ts en_source.ts

内容的提问来源于stack exchange,提问作者Olli Savolainen

火山引擎 最新活动