Spotlight for Help in localized Java Swing applications on macOS

♀尐吖头ヾ 提交于 2019-12-23 10:06:45

问题


In Java Swing applications on macOS, Cocoa automatically binds a search field called Spotlight for Help to the first menu labelled “Help” in a frame’s menu bar, when using the macOS look and feel and a screen menu bar.

System.setProperty("apple.laf.useScreenMenuBar", "true");

try {
  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
  e.printStackTrace();
}

JFrame frame = new JFrame();
JMenuBar menuBar = new JMenuBar();
JMenu helpMenu = new JMenu("Help");
menuBar.add(helpMenu);
frame.setJMenuBar(menuBar);

However my application is localized and the English string “Help” translates in other locales into

  • Aide” in French;
  • Aiuto” in Italian;
  • Ayuda” in Spanish;
  • Ajuda” in Portuguese;
  • Hilfe” in German;
  • Hulp” in Dutch;
  • Hjälp” in Swedish.

In these cases, the Spotlight for Help field is not supplied to the help menu by Cocoa.

How could I still get this search field?


回答1:


Solution

  1. Bundle the .class files and resources (image, sound, video, localization files, etc.) of your application in a .jar file with Oracle's Java Archive.
  2. Bundle your .jar file in an .app directory with Oracle's AppBundler (for Java 7+, which replaces the old Apple's JarBundler for Java 6).
  3. Add to the .app directory the Contents/Resources/<locale>.lproj directories for each locale that should be supported by your application (you can let the locale directories empty since the localization files can be already in the .jar file).
  4. Launch your application (double-click on the application icon in Finder or type open <application>.app in Terminal).

The search field Spotlight for Help will appear.

Explanation

I'm going to make a guess and it's that you're executing the .class files directly (from an IDE, for instance) or the .jar file, because from what I know this should be working.

Although what most sources say, Swing is deeply rooted on system calls and thus relies on the OS for many features, like in this case. Ideally, this should be covered by the method setHelpMenu(JMenu) but as you'll notice this has never been implemented.

If you check first, you'll notice that there's no extra component added in your JMenuBar and you have no control over that. If you try using AWT's MenuBar instead you'll see the behavior is exactly the same although, insterestingly enough, the method setHelpMenu(Menu) it is really implemented but doesn't add the search field if the menu is named something different from "Help".

At this point I found a workaround and it's setting the menu label to "Help" and once displayed (don't use ComponentListener.componentShown(ComponentEvent), this won't work, use AncestorListener.ancestorAdded(AncestorEvent)) changing the menu label to the localized one. This will add the search field to the help menu. However the search field will in English, with the label "Search".

Checking the API, it's more than clear that in Swing this feature is not implemented and fully relies on AWT. AWT on the other hand has partly implemented the native calls to the OS, but it's not wired to be invokable. Reaching this point and knowing that the search field does appear in our application and that in other ones running in Java it's properly localized lets us hint that this is a trait of the OS itself (I might be wrong at this point and it's really AWT doing the dirty job, but wasn't able to find any piece of code that does it directly, although in Objective C you can define any).

Reading the documentation about how to localize a Java application in MacOS, we note that:

  • it's a requirement that the application be bundled in an .app directory and contain the Contents/Resources/<os-locale>.lproj directory, so that the OS recognizes the OS locale as supported by the application, and consequently expects a menu labeled with the OS-localized "Help" string in order to add the OS-localized search field to that menu;
  • otherwise, the OS treats the application as en_US localized, and consequently expects a menu labeled with the en_US-localized "Help" string in order to add the en_US-localized search field to that menu.

Now you can type open <application>.app in Terminal and your application will be launched with the OS-localized search field added to the help menu.

Note that Apple has its own mechanism for forcing the application to use another locale than the OS locale, and it's using the -AppleLanguages option (open <application>.app --args -AppleLanguages "(<locale>)"). The Language Switcher utility does the same under the hood. Again, the appropriate Contents/Resources/<locale>.lproj directory should exist, otherwise the OS will treat the application as en_US localized.

How you make an .app directory from the .class files and resources (image, sound, video, localization files, etc.) of your application is beyond the scope of this question because it varies depending on the platform you're using, but Oracle provides the Java Archive (to make the intermediary .jar file) and AppBundler (to make the .app directory) utilities.

Screenshot

The OS is localized in Spanish in this screenshot but the application is localized in French, because it's been launched with the -AppleLanguages "(fr)" option.




回答2:


I have just found out another way. No need to add empty Contents/Resources/<locale>.lproj directories in the .app directory, just adding these two lines (key-value pair) in the Contents/Info.plist file of the .app directory works:

<key>CFBundleAllowMixedLocalizations</key>
<true />

And the new way to make an .app bundle is to use Oracle's JavaPackager command-line utility, which is part of the J.D.K. It generates an .app directory with a Contents/Info.plist that has the above two lines by default (no need to pass the key-value pair as an option of javapackager in the command-line). And forcing another locale with the open <application>.app --args -AppleLanguages "(<locale>)" command really works with the <application>.app directory generated by Oracle's JavaPackager, contrary to the one generated by Oracle's AppBundler.



来源:https://stackoverflow.com/questions/42620642/spotlight-for-help-in-localized-java-swing-applications-on-macos

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!