在 Qt 应用程序菜单栏的主菜单中添加和本地化菜单项

Posted

技术标签:

【中文标题】在 Qt 应用程序菜单栏的主菜单中添加和本地化菜单项【英文标题】:Adding and localizing menu items in the main menu of a Qt application menubar 【发布时间】:2015-09-18 18:51:06 【问题描述】:

首先这里是 Evernote 的上述菜单的截图,本地化为法语:

[]

如您所见,主菜单中的所有菜单项(我所说的主菜单是指名称为应用程序名称的菜单项,例如这里是 Evernote)都已本地化为法语。 Evernote 应用程序本身带来了许多菜单项,例如 Évaluez Evernote pour MacRate Evernote for Mac)、Information du compte...帐户信息...)等。此外,还有标准 OS X 提供的菜单项,例如 退出 Evernote、首选项等也已本地化。

我的问题:

    如何在此主菜单中添加新项目?如何访问此菜单以添加项目? 如何根据我的应用本地化对这些项目进行本地化,无论是 OS X 提供的默认项目还是我添加的项目? 在 Evernote 菜单中,除了 服务 菜单选项之外的所有内容似乎都已本地化(但子菜单选项已本地化!)?这也不能本地化吗?

我尝试过的:

fMenuBar = fMainWindow->menuBar();
fMenuFile = fMenuBar->addMenu(QObject::tr(qPrintable(String_Class::FileMenu))); //"File" in English, translated into other languages
fAboutAppAct = new QAction(QObject::tr(qPrintable(String_Class::About_App)), fMainWindow); //prints "About App", localized in all languages
fMenuFile->addAction(fAboutAppAct);
fAboutAppAct->setMenuRole(QAction::AboutRole); //otherwise it sits with the other file menu options in the File menu

//reset UI language slot, called whenver UI language is reset. It retranslates all strings in all menus, except this
void AppMenu::reTranslateUISlot()

    fAboutAppAct->setText(QObject::tr(qPrintable(String_Class::About_App))); 

【问题讨论】:

你试过documentation吗?我知道,这里只是复制粘贴不是你的解决方案,但是步骤很多,教程很详细。 是的,我有,详细的。问题不在于使应用程序支持多语言。它已经是,并且在任何地方都可以正常工作,除了这个。这不是一个孤立的问题,这是我在谷歌上发现的一个非常普遍的问题。不幸的是,我找不到解决方案。该问题主要与 OS X 上的菜单栏有关... 您是否尝试将QMenus 和QActions 与tr() 结合使用? 是的。它在任何地方都可以正常工作,除了这种情况。 尝试在自定义子类中重新实现QTranslator::translate,然后使用QCoreApplication::installTranslator 安装它。这将帮助您查看是否为主菜单项调用了翻译器。 【参考方案1】:

也许您可以在MainWindowAppMenu 中重新实现changeEvent

void MainWindow::changeEvent(QEvent *event)

    if (event->type() == QEvent::LanguageChange) 
        this->retranslateUi(this);
        quickStart->retranslateUi(quickStart);
        //etc...
     else 
        QMainWindow::changeEvent(event);
    

您可以强制小部件重新翻译自己。但是你需要先注册一些QTranslator。

例如,在 MainWindow 的构造函数中(或在某些配置对话框中)是否可以在运行时更改语言(我在我的软件中所做的):

CustomizeOptionsDialog::CustomizeOptionsDialog(QWidget *parent)
    : QDialog(parent, Qt::Tool)

    // Load the language of the application
    customTranslator.load(languages.value( SettingsPrivate::instance()->language()) );

    // Translate standard buttons (OK, Cancel, ...)
    defaultQtTranslator.load("qt_" + SettingsPrivate::instance()->language(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    QApplication::installTranslator(&customTranslator);
    QApplication::installTranslator(&defaultQtTranslator);

其中 language() 返回“fr”、“gb”或“cs”(从在选项中选择新语言时发出的信号初始化)。

/** Change language at runtime. */
void CustomizeOptionsDialog::changeLanguage(const QString &language)

    QString lang = languages.value(language);
    SettingsPrivate *settings = SettingsPrivate::instance();

    // If the language is successfully loaded, tells every widget that they need to be redisplayed
    if (!lang.isEmpty() && lang != settings->language() && customTranslator.load(lang)) 
        settings->setLanguage(language);
        defaultQtTranslator.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
        QApplication::installTranslator(&customTranslator);
        /// TODO: reload plugin UI
        QApplication::installTranslator(&defaultQtTranslator);
     else 
        labelStatusLanguage->setText(tr("No translation is available for this language :("));
    

希望对你有帮助。

【讨论】:

【参考方案2】:

我仍然没有找到问题的完整答案。但是这里有一些我在过去几天中所做的观察:

    为了能够在主菜单中添加菜单项,您必须相应地设置菜单角色,即在将其添加到您想要的任何位置之后(没关系,因为它会移出),您设置菜单像这样的角色:

    fYourAction->setMenuRole(QAction::ApplicationSpecificRole);
    

这将在主菜单中添加菜单项。如果您以这种方式添加多个项目,它们将按照您设置其菜单角色的顺序出现。

    Qt 已经提供了一些特定的角色 - 即 About <app> 项、Quit <app> 项、Preferences... 项等。他们提到了here。 例如,如果您的操作有一个文本“Foo”,并且您将其作为菜单项添加到某处,并将角色设置为

    fFooAction->setMenuRole(QAction:: PreferencesRole);
    

然后它会自动移动到主菜单并显示为Preferences...,您在操作中实际输入的文本将无关紧要。但是,您附加到它的任何插槽作为对 triggered() 信号的响应仍然会正确触发。 QAction::AboutRole 也是如此,无论您在该操作中添加什么文本,它都会移至主菜单并显示为 About <your_app_name>

    QAction::AboutRoleQAction:: PreferencesRole 的问题就像我说的那样,即使您尝试它们也不会本地化。仅当系统区域设置更改时,它们才会被本地化,如果您只是通过安装新的翻译器在应用程序中更改它,它不会改变。解决方法?避免使用它们并将 QAction::ApplicationSpecificRole 用于您希望出现在主菜单中的所有项目。然后它们将根据您的自定义翻译器正确本地化,并尊重您在操作中提供的任何文本,即如果您将 foo 作为操作中的文本,它将显示为 foo 在主菜单中,并相应地进行本地化。再次提醒您,当您添加多个项目时,请按出现的顺序设置项目的角色,即模拟上面的 Evernote 菜单,首先为 about_app 操作设置菜单角色,然后是 preferences 操作。添加它们的位置并不重要,因为它们将被移至新菜单,因此您为项目设置菜单角色的顺序将决定它们在主菜单中出现的顺序。

    上述方法的问题是我不知道如何在主菜单中添加的项目之间插入分隔符。在我们添加的菜单中很容易做到这一点,因为我们可以访问菜单对象,但在这里我们没有访问权限(我们将项目添加到其他地方,并通过设置菜单角色使它们移动到主菜单),所以我还不知道如何在主菜单中添加多个分隔符。

【讨论】:

以上是关于在 Qt 应用程序菜单栏的主菜单中添加和本地化菜单项的主要内容,如果未能解决你的问题,请参考以下文章

如何用Qt的designer添加菜单栏

带有菜单栏的 QT HTML5 像真正的程序

Qt:Mac 菜单栏的怪异之处

如何使用 Qt 在同一个 UI 中添加菜单栏和按钮?

菜单栏的VC菜单

Qt菜单栏和标题栏怎么合一?