Qt 编写应用支持多语言版本--一个GUI应用示例

本人喜欢用代码来写布局,而不是用 Qt Designer 来设计布局,手写布局比 Qt Desiner 布局有以下优点:

手工布局,所想即所见,

源代码方式修改布局非常方便,只需要拷贝代码、注释代码就行,如果用 Qt Designer 修改原有布局,简直要人老命,拖放一下 widget 就会打乱了原有的 layout;

本文示例程序是一个GUI应用,手写布局,在工具栏中添加两个 QAction,可以切换中文、英文界面,主界面一个标签显示文本,一个按钮用来退出应用。

英文界面如下:

Qt 编写应用支持多语言版本--一个GUI应用示例

中文界面如下:

Qt 编写应用支持多语言版本--一个GUI应用示例

开发环境及步骤

VS 版本: vs2017 社区版
Qt 版本: 5.11.1
Qt VS tools: 2.3.2

第一步 新建 HelloQt 工程

默认的会创建 UI 文件,直接编译工程,复制编译产生的 ui_HelloQt.h 文件,重命名为 myUI_HelloQt.h 以这个文件为模板,手工布局。

第二步 在 setupUI() 中实现布局

使用MVC编程模型,只在 myUI_HelloQt.h 文件中实现GUI,这里虽然新建了两个 QAction 和一个 QPushButton ,但是没有连接信号和槽函数。

布局完成调试看看是否布局合理。

第三步 翻译并添加到资源

新建翻译文件 helloqt_zh.ts

用工具 lupdate 提取字符串,并语言家来翻译;

用工具 lrelease 发布 QM 文件,即 helloqt_zh.qm 文件;

在资源文件 HelloQt.qrc 中添加 QM 文件,并把资源重命名为 :/translations/helloqt_zh
如图所示:

Qt 编写应用支持多语言版本--一个GUI应用示例


上面的步骤只是准备了翻译字符串,实际上应用程序并不能切换语言,还需要执行下面的步骤:

新建一个成员变量 QTranslator *language_zh;,并在主窗口的构造方法中加载对应的QM文件, language_zh->load(":/translations/helloqt_zh");

加载了 QM 文件还不能切换多语言,需要安装才行。到底何时安装呢?这时候想起了前面的两个 QAction,只有点击了对应的工具条才切换对应的语言,在主窗口的构造方法中连接信号和槽函数:

// signals and slots QObject::connect(ui.act_language_zh, SIGNAL(triggered(bool)), this, SLOT(on_trigger_language_zh(bool))); QObject::connect(ui.act_language_en, SIGNAL(triggered(bool)), this, SLOT(on_trigger_language_en(bool))); QObject::connect(ui.btn_quit, SIGNAL(clicked(bool)), this, SLOT(on_btn_quit_clicked(bool)));

分别实现 action 对应的槽函数,加载中文时安装 QTranslation,加载英文时卸载,如下面的代码所示:

void HelloQt::on_trigger_language_zh(bool checked) { qDebug() << tr("Chinese") << endl; qApp->installTranslator(language_zh); } void HelloQt::on_trigger_language_en(bool checked) { qDebug() << tr("English") << endl; qApp->removeTranslator(language_zh); }

执行完上一步你就急着编译查看结果,点击两个工具栏你却发现并不能切换语言,为什么呢?因为切换语言的事件还没有处理呢。覆盖 changeEvent() 即可:

void HelloQt::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) { ui.retranslateUi(this); } else { QMainWindow::changeEvent(event); } }

至此两个工具栏终于可以正常地切换语言显示了。

深入一点

你可以看到工程中至少出现了3次 retranslateUi() 函数,一次是定义,两次是调用,第一次调用是在UI 初始化中,第二次调用是 changeEvent() 中切换语言,它所做的工作就是把UI widgets 上显示的字符串替换为特定语言的字符串。例如给主窗口设定窗口标题 HelloQtClass->setWindowTitle(QApplication::translate("HelloQtClass", "HelloQt", nullptr)); 最关键的是里面的 [static] QString QCoreApplication::translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1),这个函数才是负责翻译语言的。

第一个参数 context 理解为上下文,什么是上下文,Qt 助手说它就是一个类名。不同的字符串会分配到不同的上下文。分配规则是 tr() 是用哪个类名来限定的,如下面的代码,分别调用 QObject::tr("install Chinese"),HelloQt::tr("install English") 那么就有两个上下文,分别是 QObject 和 HelloQt,这一点也可以从语言家看到。

void HelloQt::on_trigger_language_zh(bool checked) { qDebug() << QObject::tr("install Chinese") << endl; qApp->installTranslator(language_zh); } void HelloQt::on_trigger_language_en(bool checked) { qDebug() << HelloQt::tr("install English") << endl; qApp->removeTranslator(language_zh); }

语言家界面的显示:

Qt 编写应用支持多语言版本--一个GUI应用示例

Qt 编写应用支持多语言版本--一个GUI应用示例

第二个参数 sourceText 就是源代码中以 tr() 括起来的字符串。

后面的两个参数暂时没有用到,忽略。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdyff.html