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

Adding and localizing menu items in the main menu of a Qt application menubar

所以首先这里是 Evernote 的所述菜单的屏幕截图,已本地化为法语:

[]

如您所见,主菜单中的所有菜单项(主菜单我指的是名称为应用程序名称的菜单项,例如这里是 Evernote)本地化为法语。 Evernote 应用程序本身带来了很多菜单项,例如 Évaluez Evernote pour Mac (Rate Evernote for Mac), 填写信息... (账户信息... ), 等等。此外还有标准的 OS X 提供的菜单项,例如 Quit Evernote, Preferences, 等等这也是本地化的。

我的问题:

  1. 如何在此主菜单中添加新项目?如何访问此菜单以添加项目?
  2. 如何根据我的应用程序本地化来本地化这些项目,OS X 提供默认项目和我添加的项目?
  3. 在 Evernote 菜单中,除了 Services 菜单选项外,所有内容似乎都已本地化(但子菜单选项已本地化!)?这也不能本地化吗?

我尝试过的:

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))); 
}

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

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

您可以强制 Widgets 重新翻译自己。但是你需要先注册一些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);
}

Where language() returns "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 :("));
    }
}

希望对您有所帮助。

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

  1. 为了能够在主菜单中添加菜单项,您必须相应地设置菜单角色,即添加到您想要的任何位置之后(这无关紧要,因为它会移动out),你可以这样设置菜单角色:

    fYourAction->setMenuRole(QAction::ApplicationSpecificRole);
    

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

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

    fFooAction->setMenuRole(QAction:: PreferencesRole);
    

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

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

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