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

4

首先,这里是Evernote菜单的一张截图,翻译成了法语:

[enter image description here]

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

我的问题:

  1. 我如何在此主菜单中添加新项?如何访问此菜单以添加项目?
  2. 如何根据我的应用程序本地化本地化这些项目,包括 OS X 提供的默认项目和我添加的项目?
  3. 在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))); 
}

你尝试过文档了吗?我知道,仅仅在这里复制粘贴不是你的解决方案,但是有很多步骤,而且教程非常详细。 - Gombat
是的,我详细地看过了。问题不在于制作多语言应用程序。它已经是多语言的,并且在其他地方都运行正常,除了这个问题。而且这不是一个孤立的问题,正如我在谷歌上发现的那样,这是一个相当普遍的问题。不幸的是,我找不到解决办法。问题主要与 OS X 上的菜单栏有关... - SexyBeast
你是否尝试使用实际字符串与tr()结合来添加QMenu和QAction? - Gombat
是的。它在任何地方都能正常工作,除了这种情况。 - SexyBeast
1
尝试在自定义子类中重新实现QTranslator::translate,然后使用QCoreApplication::installTranslator安装它。这将帮助您查看是否为主菜单项调用了翻译器。 - hank
2个回答

4

我仍未找到解决我的问题的完整答案。但以下是我在过去几天中做出的一些观察:

  1. To be able to add menu items in the main menu, you have to set the menu role accordingly, i.e after adding it wherever you want to (it won't matter, because it will move out), you set the menu role like this:

    fYourAction->setMenuRole(QAction::ApplicationSpecificRole);
    

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

  1. There are few specific roles Qt already provides - i.e for the About <app> item, Quit <app> item, Preferences... item, etc. They are mentioned here. For example, if your action has a text "Foo", and you add it somewhere as a menu item, and set the role like

    fFooAction->setMenuRole(QAction:: PreferencesRole);
    
然后它会自动移动到主菜单并显示为“Preferences...”,无论您在操作中放置什么文本,都不重要。只要你将其附加到triggered()信号的响应槽仍然会正确触发。对于QAction :: AboutRole也是同样的道理,无论您在该操作中添加什么文本,它都会移动到主菜单并显示为“About <your_app_name>”。
  • The problem with QAction::AboutRoleQAction:: PreferencesRole就像我说的,即使您尝试,它们也不会本地化。只有在系统语言环境改变时,它们才会本地化,如果您通过安装新的翻译器来更改语言环境,则不会改变。解决问题的方法?避免使用它们,并为您想要出现在主菜单中的所有项目使用QAction :: ApplicationSpecificRole。那么它们将根据您的自定义翻译器得到适当的本地化,并将遵守您在操作中提供的任何文本,即如果您在操作中给出foo作为文本,它将出现在主菜单中,并相应地进行本地化。同样,要注意的是,当您添加多个项目时,请按照它们的外观顺序设置项目角色,即模拟上面的Evernote菜单,首先为about_app操作设置菜单角色,然后是preferences操作。由于它们将被移动到新菜单中,因此您添加它们的位置并不重要,因此您为项目设置菜单角色的顺序将确定它们出现在主菜单中的顺序。
  • 以上方法的问题是我不知道如何在我正在添加到主菜单中的项目之间插入分隔符。在我们添加的菜单中很容易做到这一点,因为我们可以访问菜单对象,但是在这里我们没有访问权限(我们将项目添加到其他地方,并通过设置菜单角色使它们移动到主菜单),因此我还不知道如何在主菜单中添加多个分隔符。

  • 4
    也许你可以在MainWindow或者AppMenu中重新实现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 :("));
        }
    }
    

    我希望这对你有所帮助。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接