简 述: 准备将我写的悬浮网速窗口上面支持国际化(多语言);记录一下通过 CMake
+ Qt
来对项目设置国际化。
[TOC]
本文初发于 “偕臧的小站“,同步转载于此。
编程环境: 💻 uos20 amd64
📎 Qt 5.11.3
📎 cmake 3.13.4
📎 gdb8.0
国际化原理
Qt
实现多语言的关键原理如图,先扫描所有的源码文件 .cpp
、.ui
文件,找到被 tr()
包裹的字符串(多国语言混合也可),然后人使用到 Qt5 Lingust
程序来对每一个 .ts
文件进行翻译,再次编译生成所需的 .qm
文件。
操作步骤
因为要对自己的程序完成国际化,先在 CMakeLists.txt
添加如下代码,标明使用 LinguistTools
来生成 *.ts
文件
set(TS_FILES
./translations/zh_CN.ts
./translations/zh_TW.ts)
find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} LinguistTools REQUIRED)
qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES})
后对项目执行 CMake
、编译后,会根据 .cpp
和 .ui
文件里面字符串扫描(字符串可以同时为几国语言混合,但必须使用 tr()
包裹); 会在源码路径的 ./translations/
下生成两个 zh_CN.ts、zh_TW.ts
文件;使用 Qt5 Lingust
,手工对源文件翻译本国语言保存。
再次编译一遍,在 build-xxx
文件夹中得到 *.qm
文件,一般而言,然后在源码里面加上如下,即完成。若是没生效的话,则可能没执行 ui->retranslateUi(this);
函数
QTranslator trans;
trans.load("./" + QLocale().name() + ".qm");
QCoreApplication::installTranslator(m_trans);
但实际其中最后一步要修改一下,结合实际项目,将多语言按钮写在 QComboBox
控件中;在其中添加
QStringList listLang;
QStringList listData;
listLang << "English" << "简体中文" << "繁體中文(台湾)";
listData << "es_US" << "zh_CN" << "zh_TW";
for (int i = 0; i < listLang.count(); ++i)
ui->comboBoxLanguage->addItem(listLang[i], listData[i]);
对该控件添加对应的槽函数
void WinSetting::onComboBoxLanguage(int index)
{
QString language("zh_CN");
language = ui->comboBoxLanguage->itemData(index).toString();
bool ok = m_trans->load("./" + language + ".qm");
qDebug()<< "---------@1--->" << language << ok;
QCoreApplication::installTranslator(m_trans);
}
其中每次运行 installTranslator()
的时候,都会触发 QEvent::LanguageChange
事件信号;故需要在事件过滤器中,添加对应的处理,响应更新界面更新文字。还要在该 QcomboBox 控件中安装此事件过滤器; 此时就已经完成了,可以不关闭程序切换多语言了。
bool WinSetting::eventFilter(QObject *watched, QEvent *event)
{
if (watched == ui->comboBoxLanguage) {
if (event->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
return true;
}
}
return QWidget::eventFilter(watched, event);
}
注意
若在
QtCreator
中,点击 “清理”,会删除/translations
下的所有.ts
文件,再次编译后的生成是空的未翻译的.ts
文件;坑坑坑!!!一般使用设计器来设计的界面 UI,也就是程序源码中我们看到的 *.ui文件,在载入翻译器后,我们应该调用 ui->retranslateUi() ,这个函数实际上就是把 界面 控件的text重新载入一遍,可以在 ui_*.cpp 中看到该函数的实现。
当语言进行切换时,需要调用
ui->retranslateUi(this);
更新主窗口。 如果非主窗口,则这个installTranslator
函数会触发void changeEvent(QEvent *e)
事件。原因如下:系统调用完
installTranslator
函数之后,系统会自动给程序中所有的QWidget
以及其子类发送QEvent::LanguageChange()
信号,并告知changeEvent
槽event
产生。所以,在要切换语言的每个窗体中都要重写接受QEvent::LanguageChange()
信号的changeEvent
函数,从而实现了语言的动态切换。注意:加载主程序与子插件程序翻译文件时的别名或者路径不要相同,否则子插件程序翻译有可能不生效。
项目提交
在 lfxNet 的实时网速程序中,实际提交代码可提供大家参考
- 在
Cmake
添加调用LinguistTools
的代码: #948522d8b - 更新翻译
.ts
文件: #9602aa3e3 和 #4e659fe13 - 设置多语言切换: #31b2561bd
参考
系列地址:
欢迎 star
和 fork
这个系列的 QT / DTK
学习,附学习由浅入深的目录。