简述: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); }
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()信号,并告知changeEvent槽event产生。所以,在要切换语言的每个窗体中都要重写接受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、样例
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 <QApplication> 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 <QWidget> #include <QComboBox> #include <QLabel> 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 <QVBoxLayout> #include <QTranslator> #include <QApplication> #include <QDebug> 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); } }
3、语言代码表