我目前正在评估C ++框架Qt v5.4.1。目前我是 试图了解并应用Internationalization with Qt。
我在运行时成功实现了人类语言的切换 文章How to create a multi lingual application that can switch the language at runtime?的帮助,我知道如何使用Qt Linguist Translation 源(.ts)文件以及如何生成Qt Linguist Message(.qm)文件。我用 构建系统CMake以自动化生成,并且它非常好用。
在我的项目中,翻译是从Qt资源集合(.qrc)加载的
文件编译到应用程序中。我知道如何通过转换“静态”字符串
成员函数QObject::tr()
和QObject::translate()
。
现在出现了棘手的部分:我想在应用程序发展的同时添加语言。 目前我有以下两个.ts文件:
foo_ui_de_DE.ts
foo_ui_en_US.ts
这些通过构建通过lrelease
编译到以下两个.qm文件中
过程:
foo_ui_de_DE.qm
foo_ui_en_US.qm
构建过程会自动生成.qrc文件translations.qrc
和
通过rcc
将该文件编译到可执行文件中。
声明文件(.h)中的相关源代码:
#include <QMainWindow>
#include <QLocale>
#include <QString>
#include <QTranslator>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
/**
* Initializes a new instance of the MainWindow class with the given parent.
*
* @param parent The parent.
*/
explicit MainWindow(QWidget* parent = 0);
private slots:
/**
* Loads a language by the given language shortcut (e.g. `de_DE`, `en_US`).
*/
void LoadLanguage(QLocale const& kLocale);
void SwitchTranslator(QTranslator& translator,
QString const& kLocale,
QString const& kFilename);
/**
* Creates the language menu dynamically.
*/
void CreateLanguageMenu();
protected:
/**
* Handler which is activated when a new translator is loaded or the system
* language is changed.
*/
void changeEvent(QEvent* event);
protected slots:
/**
* Slot which is called by the language menu actions.
*/
void slotLanguageChanged(QAction* action);
private:
/**
* The translations for this application.
*/
QTranslator translator_;
/**
* The translations for the Qt Widgets used in this application.
*/
QTranslator qt_translator_;
/**
* Contains the currently loaded locale.
*/
QLocale locale_;
/**
* The main window of the application.
*/
Ui::MainWindow* ui_;
};
定义文件(.cc)中的相关源代码:
#include <QLibraryInfo>
#include "main_window.h"
#include "ui_main_window.h"
MainWindow::MainWindow(QWidget* the_parent)
: QMainWindow{the_parent},
ui_{new Ui::MainWindow} {
ui_->setupUi(this);
CreateLanguageMenu();
}
MainWindow::~MainWindow() {
delete ui_;
}
void MainWindow::LoadLanguage(QLocale const& kNewLocale) {
QLocale::setDefault(kNewLocale);
QString const kLanguageName{QLocale::languageToString(kNewLocale.language())};
SwitchTranslator(translator_, "qt_" + kNewLocale.bcp47Name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
SwitchTranslator(qt_translator_,
qApp->applicationName() + '_' + kNewLocale.name(),
":/translations");
statusBar()->showMessage(
tr("Language changed to %1").arg(kLanguageName));
locale_ = kNewLocale;
}
void MainWindow::SwitchTranslator(QTranslator& translator,
QString const& kLocale,
QString const& kFilename) {
qApp->removeTranslator(&translator);
if (translator.load(kLocale, kFilename)) {
qApp->installTranslator(&translator);
}
}
void MainWindow::CreateLanguageMenu() {
// TODO(wolters): This is not optimal, since it does not work automatically
// with the .qm files added as a resource to the application.
//: Translation for the human language German.
QT_TR_NOOP("German");
//: Translation for the human language English.
QT_TR_NOOP("English");
QActionGroup* language_group{new QActionGroup(ui_->menuLanguage)};
language_group->setExclusive(true);
connect(language_group, SIGNAL(triggered(QAction*)), this,
SLOT(slotLanguageChanged(QAction*)));
QLocale const kDefaultLocale{QLocale::system()};
QDir const kDirectory{QApplication::applicationDirPath() + "/.."};
QStringList const kFileNames{kDirectory.entryList(QStringList("*.qm"))};
for (QString const& kFileName : kFileNames) {
QLocale const kLocale{QFileInfo{kFileName}.completeBaseName().replace(
qApp->applicationName() + "_", "")};
QString const kCountryCode{
kLocale.name().toLower().mid(kLocale.name().lastIndexOf('_') + 1)};
QIcon const kIcon{":/icons/flags/" + kCountryCode + ".png"};
QAction* action{new QAction{
kIcon,
// TODO(wolters): This does not work.
tr(QLocale::languageToString(kLocale.language()).toStdString().c_str()),
this}};
action->setCheckable(true);
action->setData(kLocale);
ui_->menuLanguage->addAction(action);
language_group->addAction(action);
if (kDefaultLocale == kLocale) {
action->setChecked(true);
}
}
}
void MainWindow::changeEvent(QEvent* the_event) {
if (nullptr != the_event) {
switch (the_event->type()) {
// QEvent::LanguageChange is send if a translator is loaded.
case QEvent::LanguageChange:
ui_->retranslateUi(this);
break;
// QEvent::LocaleChange is send, if the system language changes.
case QEvent::LocaleChange:
LoadLanguage(QLocale::system());
break;
default:
break;
}
}
QMainWindow::changeEvent(the_event);
}
void MainWindow::slotLanguageChanged(QAction* action) {
if (nullptr != action) {
LoadLanguage(qvariant_cast<QLocale>(action->data()));
}
}
源代码已经描述了我在评论中遇到的问题。
Languages
出现在德语人类语言中(我翻译了两个项目
在.ts文件中)。但是当我通过菜单从德语切换到语言时
英语,两个项目标签不得到翻译。QT_TR_NOOP
),如果添加了新的人类语言
应用。最佳工作流程是:
我认为我误解了一些东西,但我找不到解决方案 搜索WWW一段时间。
更新2015-04-01:我认为我使用了错误的方法。重要的是, Languages 菜单是在成员函数CreateLanguageMenu()
中动态创建的。我需要回答如何翻译动态创建的菜单项的问题。所以关于该函数中的行QAction* action{new QAction{kIcon, tr(QLocale::languageToString(kLocale.language()).toStdString().c_str()), this}};
。我想在编译时可以使用某种查找功能...
答案 0 :(得分:1)
正如您已经提到的,您需要实时查找功能。 我建议这样的黑客: 在创建QAction对象时,使用对象名称作为语言标识
QT_TR_NOOP("LANG_ENG")
QAction* langAction = ...;
langAction->setObjectName("LANG_ENG");
在语言更改事件中调用一些方法来撤消此操作
void retranslateLangActions()
{
QList<QAction*> widgetActions = this->findChildren<QAction*>();
foreach(QAction* act, widgetActions) // qt foreach macro
{
QString objName = act->objectName();
if (objName.startsWith("LANG_"))
{
act->setText(tr(objName.toStdString().c_str()));
}
}
}