gpt4 book ai didi

c++ - 如果在 Qt 中使用国际化,则翻译 "dynamic"内容

转载 作者:行者123 更新时间:2023-11-28 06:20:31 27 4
gpt4 key购买 nike

我目前正在评估 C++ 框架 Qt v5.4.1。目前我是试图理解和应用Internationalization with Qt .

我通过文章帮助How to create a multi lingual application that can switchthe 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()));
}
}

源码已经在评论中描述了我遇到的问题。

  1. 如果应用程序启动,则使用当前系统区域设置重新翻译用户界面。这有效,我可以看到菜单中的项目Languages 以德语人类语言出现(我已经翻译了这两个项目在 .ts 文件中)。但是当我通过菜单将语言从德语切换到英语,两个项目标签得到翻译。
  2. 该方法通常不是最优的,因为我不想修改源代码(QT_TR_NOOP 上面),如果一种新的人类语言被添加到应用。最佳工作流程是:
    1. 将所有支持的语言以其正确的语言添加到所有 .ts 文件中。
    2. 动态翻译菜单项。

我想我误解了什么,但我找不到解决办法在 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");

在 Language Change 事件上调用一些方法来重新定义这个 Action

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 中使用国际化,则翻译 "dynamic"内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29376918/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com