My file menu is not full of eels Or, why do my menus behave oddly on macOS when translated?
This is the story of a bug in an open-source project I maintain; as the maintainer I review and sometimes fix bug reports from the community. Last week, a user reported that the ‘File’ menu of the application was not appearing on macOS. Some investigation showed this didn’t happen when using the default translation (i.e English), but a bit more investigation showed that it only happened when the language in use was Dutch.
At this point I’d like to make it clear that I like the Dutch and especially gevulde koeken, a type of almond cookie you can only get in the Netherlands. When passing through Amsterdam Schiphol, I take care to stock up at the supermarket on the main concourse. If you’re passing through Schiphol and wonder why they’ve been cleaned out of cookies, it was me.
Anyway, it was weird that the menu code I had written seemed to dislike the Dutch. Actually, as part of investigating the defect, I needed to switch my system language to Dutch. So I just did that for a week, and got to learn most of the macOS UI in Dutch. Lekker!
It turns out, the File menu (or actually, the ‘Bestand’ menu) was missing for a very sensible reason: it contained zero items. In this particular application, the menu is quite simple and contains:
- load configuration file…
- save configuration file…
If you’ve used Qt on macOS, you’ll know the ‘Quit’ item is moved to the application menu (the one with name of the software) automatically. What you may not know is that Qt will, by default, move some other items:
All of these items have special locations on macOS. The default way to detect if a menu item should be moved this way, is based on a heuristic. A heuristic is a rule which works some of the time and goes wrong when your customer / manager is using the software. The default rule is to do this based on a string search of the (translated) menu item name. In this case, the Dutch translation of ‘Preferences’ is … ‘Configuration’. Therefore, both the first and second items in my file menu get treated as the application preferences item. Hence, the file menu ends up empty and is therefore made invisible.
Fortunately, the fix is simple: rather than accepting the default TextHeuristic MenuRole on your QActions, just set a role explicitly, such as Qt::NoRole. This disables the text heuristic and Dutch users can once again see the Bestand menu in all its glory.
QMenuBar* mb = new QMenuBar(); QAction* openAction = new QAction(tr("Open saved configuration...")); openAction->setMenuRole(QAction::NoRole); // change from Qt::TextHeuristicRole QAction* saveAction = new QAction(tr("Save configuration as...")); saveAction->setMenuRole(QAction::NoRole); // change from Qt::TextHeuristicRole QMenu* fileMenu = mb->addMenu(tr("File")); fileMenu->addAction(openAction); fileMenu->addAction(saveAction);
Now I just need to get some more of those cookies.
If you’re confused about the title of this post, kindly Google the ‘Hungarian phrasebook’ sketch by Monty Python — only maybe not on a work computer.