二十五、Qt Quick/QML国际化本地化实战:翻译、切换与格式化全指南
本文详解Qt Quick/QML项目国际化本地化全流程,涵盖qsTr字符串翻译、多语言动态切换、日期货币格式化,附实战代码与避坑技巧。
二十五、Qt Quick/QML国际化本地化实战:翻译、切换与格式化全指南-MakerLi

国际化与本地化——字符串翻译(qsTr)、多语言切换、日期/时间/货币格式化


本章概述

在全球化软件市场中,多语言支持与本地化适配是触达全球用户的核心能力。本章带你从零掌握Qt Quick/QML项目的国际化(i18n)与本地化(l10n)实现,覆盖从字符串翻译到复杂数据格式化的完整流程。


学习目标

  • 掌握用qsTr()标记与翻译字符串
  • 理解多语言动态切换的实现逻辑
  • 学会日期、时间、货币的本地化格式化
  • 独立完成多语言QML应用开发




一、字符串翻译(qsTr)

Qt提供了成熟的国际化框架,qsTr()是QML中标记可翻译字符串的核心工具。


1.1 基本用法

在QML中直接用qsTr()包裹需要翻译的文本,支持上下文注释、复数格式等场景:

// 基础翻译
Text { text: qsTr("Hello World") }

// 复数形式:根据itemCount自动匹配单复数翻译
property string countText: qsTr("%n item(s)", "", itemCount)

// 带上下文注释:帮助翻译者理解场景
Button { text: qsTr("Save", "Button text for saving the document") }


1.2 翻译工作流程

翻译需遵循四步标准化流程:

  1. 提取字符串:执行lupdate project.pro命令,生成XML格式的.ts翻译源文件
  2. 翻译编辑:用Qt Linguist(专业翻译工具)或文本编辑器完成.ts文件的内容翻译
  3. 发布翻译:执行lrelease project.pro命令,生成二进制.qm翻译文件(运行时加载)
  4. 加载翻译:通过QTranslator.load()在应用运行时加载对应语言的.qm文件




二、多语言切换实现

多语言切换需要C++端的翻译管理器配合QML界面,核心是通过QTranslator动态加载不同语言的.qm文件并触发界面刷新。


2.1 C++端翻译管理器

创建TranslationManager类统一管理翻译加载与切换:

// TranslationManager.h
#include <QObject>
#include <QTranslator>
#include <QGuiApplication>

class TranslationManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString currentLanguage READ currentLanguage WRITE setLanguage NOTIFY languageChanged)
    
public:
    explicit TranslationManager(QGuiApplication *app, QObject *parent = nullptr);
    QString currentLanguage() const { return m_currentLanguage; }
    void setLanguage(const QString &language);

signals:
    void languageChanged();

private:
    QGuiApplication *m_app;
    QTranslator m_translator;
    QString m_currentLanguage;
};
// TranslationManager.cpp
void TranslationManager::setLanguage(const QString &language)
{
    if (m_currentLanguage == language) return;
    
    // 移除旧翻译
    m_app->removeTranslator(&m_translator);
    
    // 加载新翻译(需确保.qm文件在资源路径中)
    QString qmFile = QString(":/translations/app_%1.qm").arg(language);
    if (m_translator.load(qmFile)) {
        m_app->installTranslator(&m_translator);
        m_currentLanguage = language;
        emit languageChanged(); // 触发界面刷新
    }
}

注意:需在main.cpp中注册该类到QML,才能在界面中调用:

qmlRegisterType<TranslationManager>("com.example.translation", 1, 0, "TranslationManager");


2.2 QML端集成

在QML中导入翻译管理器,实现语言切换控件与翻译文本的绑定:

import QtQuick 2.15
import QtQuick.Controls 2.15
import com.example.translation 1.0

ApplicationWindow {
    id: window
    width: 800
    height: 600

    // 实例化翻译管理器
    TranslationManager { id: transManager }

    // 语言切换下拉框
    ComboBox {
        id: languageCombo
        anchors.top: parent.top
        anchors.right: parent.right
        model: ["zh_CN", "en_US", "ja_JP", "de_DE"]
        onCurrentTextChanged: transManager.setLanguage(currentText)
    }

    // 绑定翻译文本
    Column {
        anchors.centerIn: parent
        spacing: 20

        Text { text: qsTr("Welcome to My Application"); font.pixelSize: 24 }
        Button {
            text: qsTr("Click Me")
            onClicked: console.log(qsTr("Button clicked!"))
        }
    }
}






三、日期/时间/货币格式化

本地化不仅是语言翻译,还要适配不同地区的数据显示习惯,Qt的Locale类可轻松实现这一点。


3.1 使用Locale进行格式化

QML中通过Qt.locale()获取系统区域设置,或手动指定地区,调用格式化方法:

import QtQuick 2.15

Item {
    // 获取系统默认区域,也可手动指定:Qt.locale("de_DE")
    property var locale: Qt.locale()

    // 日期格式化(ShortFormat/ LongFormat)
    function formatDate(date) {
        return date.toLocaleDateString(locale, Locale.ShortFormat)
    }

    // 时间格式化
    function formatTime(date) {
        return date.toLocaleTimeString(locale, Locale.ShortFormat)
    }

    // 货币格式化
    function formatCurrency(amount) {
        return Number(amount).toLocaleCurrencyString(locale)
    }

    // 数字千位分隔符格式化
    function formatNumber(num) {
        return Number(num).toLocaleString(locale)
    }
}


3.2 各地区格式化规则差异

不同地区的显示习惯差异明显:

  • 中文(中国):日期2023-12-25,时间14:30:45,货币¥1,234.56,数字1,234,567.89
  • 英语(美国):日期12/25/2023,时间2:30:45 PM,货币$1,234.56,数字格式同中文
  • 德语(德国):日期25.12.2023,时间14:30:45,货币1.234,56 €,数字1.234.567,89
  • 日语(日本):日期2023/12/25,时间14:30:45,货币¥1,234.56,数字格式同中文

3.3 完整示例:本地化信息面板

整合翻译与格式化的实战示例:

import QtQuick 2.15
import QtQuick.Layouts 1.15

Rectangle {
    width: 400
    height: 300
    color: "#f0f8ff"
    border.color: "#2c3e50"
    radius: 10

    property date currentDate: new Date()
    property real amount: 1234567.89
    property int itemCount: 5

    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        Text {
            text: qsTr("Localized Information Panel")
            font.bold: true
            font.pixelSize: 20
            color: "#2c3e50"
            Layout.alignment: Qt.AlignHCenter
        }

        GridLayout {
            columns: 2
            columnSpacing: 20
            rowSpacing: 10

            Text { text: qsTr("Current Date:") }
            Text { text: currentDate.toLocaleDateString(Qt.locale(), Locale.LongFormat); color: "#2f4f4f" }

            Text { text: qsTr("Current Time:") }
            Text { text: currentDate.toLocaleTimeString(Qt.locale(), Locale.LongFormat); color: "#2f4f4f" }

            Text { text: qsTr("Amount:") }
            Text { text: Number(amount).toLocaleCurrencyString(Qt.locale()); color: "#27ae60"; font.bold: true }

            Text { text: qsTr("Item Count:") }
            Text { text: qsTr("%n item(s)", "", itemCount); color: "#2f4f4f" }

            Text { text: qsTr("Formatted Number:") }
            Text { text: Number(amount).toLocaleString(Qt.locale()); color: "#2f4f4f" }
        }

        Button {
            text: qsTr("Refresh Data")
            Layout.alignment: Qt.AlignHCenter
            onClicked: {
                currentDate = new Date()
                amount = Math.random() * 1000000
                itemCount = Math.floor(Math.random() * 10) + 1
            }
        }
    }
}






四、最佳实践与注意事项

4.1 翻译最佳实践

  • 上下文明确:给翻译字符串添加场景注释,帮助翻译者理解语境
  • 避免字符串拼接:不要动态拼接文本,改用qsTr("%n item(s)", "", count)这类带占位符的格式
  • 预留UI空间:不同语言文本长度差异大,UI布局要留足弹性空间
  • 全语言测试:在所有支持的语言下测试UI布局与功能,避免显示异常

4.2 常见问题解决

  • 翻译不生效:多因.qm文件路径错误或未正确加载,可先用绝对路径调试
  • 界面未刷新:语言切换后需确保TranslationManager发出languageChanged信号,触发QML界面更新
  • 特殊字符乱码:保证所有文件使用UTF-8编码,避免编码不一致问题
  • 复数处理错误:需严格遵循qsTr("%n item(s)", "", count)格式,让Qt自动处理单复数翻译




五、实战练习

  1. 开发支持中英文切换的简单计算器应用,所有按钮文本、提示信息均用qsTr()标记
  2. 实现多语言天气预报界面,结合Locale格式化日期、时间与温度显示
  3. 开发支持货币格式转换的购物车界面,适配不同地区的货币符号与数字格式
  4. 为现有QML项目添加德语、日语翻译支持,用Qt Linguist完成翻译工作

提示:Qt Linguist提供翻译记忆、模糊匹配等专业功能,能大幅提升翻译效率,推荐优先使用。