Qt 多国语言国际化


简述:Qt 提供了一种国际化方案,在程序使用过程中,不需要重启应用程序就可以实现语言的动态切换


1、实现语言国际化步骤 


要实现语言国际化,需要执行以下步骤:


A.  对用户可见的文本信息全部使用 tr()进行封装 

注意源码 utf-8 字符集;源码中需要翻译的字符串必须用英文,以防出现乱码


B.  创建语言文件 


打开 .pro文件,加入语言文件

TRANSLATIONS = $$PWD/i18n/Lidar_fr.ts \
        $$PWD/i18n/Lidar_en.ts \
        $$PWD/i18n/Lidar_ja.ts \
        $$PWD/i18n/Lidar_zh.ts


利用lupdate工具从源代码中扫描并提取需要翻译的字符串,生成 " .ts " 文件,即:

菜单栏 "工具"-> "外部-> "Qt语言家-> "更新翻译(lupdate)",将生成语言文件Lidar_fr.ts,Lidar_en.ts,Lidar_ja.ts,Lidar_zh.ts

或者,打开 Qt 5.7 for Desktop (MinGW 5.3.0 32bit) 命令行窗口,并进入 " .pro " 工程目录,执行命令:

lupdate  XXX.pro,便可生成 ".ts"翻译文件


C.编辑翻译语言文件 


利用 Linguist 工具 (Qt语言家) 来协助完成翻译工作。即启动Linguist 工具后,打开前面用 lupdate 生成的 " .ts "文件,对其中的字符串逐条进行翻译保存,主要是将源文对应的译文填写上。

另:由于 " .ts "文件用用了XML格式,所以也可以使用其他编辑器来打开 ".ts "文件并翻译


D.发布翻译文件


当翻译全部完成后,利用lrelease工具处理翻译好的 " .ts "文件,生成格式更为紧凑的 ".qm"文件,只有QTranslator能够正确识别它,即:

菜单栏 "工具"-> "外部" -> "Qt语言家" -> "发布翻译(lrelease)",便可生成对应的.qm "文件。


E.  加载翻译文件


    QTranslator translator;
    if (translator.load("Lidar_en.qm", ":/translations")) { // 可以不带".qm"后缀名
        qApp->installTranslator(&translator);
    }

还可以使用别名

    QTranslator translator;
    if (translator.load("en", ":/translations")) { 
        qApp->installTranslator(&translator);
    }


Qt 多国语言国际化_第1张图片

F.  切换语言


method 1:

void MainWindow::Refresh()
{
    ui->listWidget->addItem(tr("item1"));
    ui->listWidget->addItem(tr("item2"));
    ui->listWidget->addItem(tr("item3"));
}


void MainWindow::actionEnglishToggled(bool state)
{
    if (state) {
        qApp->removeTranslator(&translator);
        if (translator.load("Lidar_en.qm", ":/translations")) {
            qApp->installTranslator(&translator);
            this->Refresh();
        }
    }
}

void MainWindow::actionFrancaisToggled(bool state)
{
    if (state) {
        qApp->removeTranslator(&translator);
        if (translator.load("Lidar_fr.qm", ":/translations")) {
            qApp->installTranslator(&translator);
            this->Refresh();
        }
    }
}

void MainWindow::actionJapaneseToggled(bool state)
{
    if (state) {
        qApp->removeTranslator(&translator);
        if (translator.load("Lidar_ja.qm", ":/translations")) {
            qApp->installTranslator(&translator);
            this->Refresh();
        }
    }
}


void MainWindow::actionChineseToggled(bool state)
{
    if (state) {
        qApp->removeTranslator(&translator);
        if (translator.load("Lidar_zh.qm", ":/translations")) {
            qApp->installTranslator(&translator);
            this->Refresh();
        }
    }
}


method 2:

当语言进行切换时,需要调用 ui->retranslateUi(this); 更新主窗口。 如果非主窗口,则这个 installTranslator 函数会触发void changeEvent(QEvent *e) 事件。原因如下:

系统调用完 installTranslator 函数之后,系统会自动给程序中所有的 QWidget 以及其子类发送 QEvent::LanguageChange()信号,并告知changeEventevent产生。所以,在要切换语言的每个窗体中都要重写接受QEvent::LanguageChange()信号的changeEvent函数,从而实现了语言的动态切换。

注意加载主程序子插件程序翻译文件时的别名或者路径不要相同,否则子插件程序翻译有可能不生效。

/*********************************************
 * changeEvent一般是当前widget状态改变后触发的
 * 如字体改变、语言改变之类的。
 * 该方法主要捕获改变事件,当语言改变后,执行相关操作。
********************************************/
void PlotViewerPlugin::changeEvent(QEvent* e) //重写的事件处理方法
{
    QWidget::changeEvent(e);   //让基类执行事件处理方法
    switch (e->type()) {
        case QEvent::LanguageChange:   //如果是语言改变事件
            if(ui) ui->retranslateUi(this); //更新UI的语言
            break;
        default:
            break;
    }
}


注意:需要更新翻译,便重复" C " ~ " D " 步骤


2、样例


Qt 多国语言国际化_第2张图片

LangSwitch.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = LangSwitch
TEMPLATE = app


SOURCES += main.cpp\
        langswitch.cpp

HEADERS  += langswitch.h
TRANSLATIONS = lang_en.ts \
               lang_zh.ts \
               lang_la.ts


main.cpp

#include "langswitch.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    LangSwitch w;
    w.show();
    
    return a.exec();
}


langswitch.h

#ifndef LANGSWITCH_H
#define LANGSWITCH_H

#include 
#include 
#include 

class LangSwitch : public QWidget
{
    Q_OBJECT
    
public:
    LangSwitch(QWidget *parent = 0);
    ~LangSwitch();
private slots:
    void changeLang(int index);

private:
    void createScreen();
    void changeTr(const QString& langCode);
    void refreshLabel();

    QComboBox* combo;
    QLabel* label;
};

#endif // LANGSWITCH_H


langswitch.cpp

#include "langswitch.h"
#include 
#include 
#include 
#include 

LangSwitch::LangSwitch(QWidget *parent)
    : QWidget(parent)
{
    createScreen();
}

LangSwitch::~LangSwitch()
{
    
}

void LangSwitch::createScreen()
{
    combo = new QComboBox;
    combo->addItem("English", "en");
    combo->addItem("Chinese", "zh");
    combo->addItem("Latin", "la");

    label = new QLabel;
    refreshLabel();

    QVBoxLayout* layout = new QVBoxLayout;
    layout->addWidget(combo, 1);
    layout->addWidget(label, 5);

    setLayout(layout);

    connect(combo, SIGNAL(currentIndexChanged(int)),this,SLOT(changeLang(int)));
    changeLang(0);
}

void LangSwitch::refreshLabel()
{
    label->setText(tr("TXT_HELLO_WORLD", "Hello World"));
}

void LangSwitch::changeLang(int index)
{
    QString langCode = combo->itemData(index).toString();
    changeTr(langCode);
    refreshLabel();
}

void LangSwitch::changeTr(const QString& langCode)
{
    static QTranslator* translator;

    if (translator != NULL)
    {
        qApp->removeTranslator(translator);
        delete translator;
        translator = NULL;
    }
    translator = new QTranslator;
    QString qmFilename = "lang_" + langCode;
    qDebug() << qmFilename;
    if (translator->load(QString("E:/.../LangSwitch/")+qmFilename))
    {
        qApp->installTranslator(translator);
    }
}


你可能感兴趣的:(Qt)