使用Qt的国际化,则翻译"dynamic"内容
Translation of "dynamic" content if using Internationalization with Qt
我目前正在评估C++框架Qt v.4.1。目前我尝试用Qt来理解和应用国际化。
我通过文章的帮助如何创建一个可以切换的多语言应用程序运行时的语言?我知道如何使用Qt语言学家翻译源(.ts)文件以及如何生成Qt-Linguist Message(.qm)文件。我使用构建系统CMake可以自动生成,效果非常好。
在我的项目中,翻译是从Qt资源集合(.qrc)加载的文件编译到应用程序中。我知道如何通过成员函数CCD_ 1和CCD_。
现在是棘手的部分:我想在应用程序发展的同时添加语言。目前我有以下两个.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
通过CCD_ 9将该文件编译成可执行文件。
申报文件中的相关源代码(.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()));
}
}
源代码已经在注释中描述了我遇到的问题。
- 如果应用程序已启动,则使用当前系统区域设置重新翻译UI。这很有效,我可以看到菜单中的项目
QObject::tr()
0出现在德语中(这两项我都翻译过在.ts文件中)。但当我通过菜单将语言从德语切换到英文,两个项目标签都不会被翻译 - 这种方法通常不是最优的,因为我不想修改源代码(上面的
QT_TR_NOOP
),如果将新的人类语言添加到应用最佳工作流程为:- 将所有支持的语言以其正确的语言添加到所有.ts文件中
- 动态转换菜单项
我想我误解了什么,但我找不到解决办法在WWW上搜索一段时间。
更新2015-04-01:我认为我使用了错误的方法。重要的是Languages菜单是在成员函数CreateLanguageMenu()
中动态创建的。我需要一个如何翻译动态创建的菜单项的问题的答案。所以这都是关于函数中的QAction* action{new QAction{kIcon, tr(QLocale::languageToString(kLocale.language()).toStdString().c_str()), this}};
行。我想我需要一些在编译时可用的查找功能。。。
正如您已经提到的,您需要一个实时查找功能。我建议这样的破解:创建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()));
}
}
}
- 不同翻译单元中不可重载的非内联函数定义
- 需要将一行代码从C++ Qt翻译成PyQt
- 为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- 在没有 API 的情况下使用谷歌翻译文本
- 如何执行 cppcheck 交叉翻译单元 (CTU) 静态分析?
- 模板变量是否允许在多个翻译单元中并有效合并?
- 是否允许类在程序中的不同翻译单元之间具有不同的定义?
- C++类中的二维"dynamic"数组?
- 我怎样才能代替使用新的使用malloc翻译
- 为什么具有静态存储持续时间的同一内联变量在包含在 VS2017 编译的两个翻译单元中时会构造和销毁两次
- 如何将 'in' 关键字从 python 翻译成 c++?
- 为什么不同的翻译单元没有独立和沙盒的内存空间?
- 如何用c语言翻译openssl命令pbkdf2
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- 静态变量在同一个翻译单元中被静态方法使用时是否保证被初始化?
- protobuf in C++ with dynamic binding for google::protobuf::M
- 如何翻译这个给定代码中的 ::* 运算符和member_fn?
- 来自不同翻译单元的函数会干扰吗?
- 使用Qt的国际化,则翻译"dynamic"内容