Discussions
Categories
- 197K All Categories
- 2.5K Data
- 546 Big Data Appliance
- 1.9K Data Science
- 450.8K Databases
- 221.9K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 552 MySQL Community Space
- 479 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.1K ORDS, SODA & JSON in the Database
- 555 SQLcl
- 4K SQL Developer Data Modeler
- 187.2K SQL & PL/SQL
- 21.4K SQL Developer
- 296.3K Development
- 17 Developer Projects
- 139 Programming Languages
- 293K Development Tools
- 110 DevOps
- 3.1K QA/Testing
- 646.1K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 158 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.2K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 19 Java Essentials
- 162 Java 8 Questions
- 86K Java Programming
- 81 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 205 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 468 LiveLabs
- 39 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 175 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 233 Portuguese
Localized Accelorator Keys
Hi folks,
I have a problem with localization and accelerator keys. I am developing a localized Swing GUI where a user can set his preffered Locale and then all texts are translated.... That's all no prob. The problem is, that in JMenus the accelerator keys for items are displayed not according to the set default locale (e.g., en-US) but are displayed according to the OS user.language (in my case de [German]). Hence, the accel. keys read, e.g., '*Strg-N*' instead of '*Ctrl-N*' as expected for default locale en.
This is just a display problem, the functionality / the keys work fine, of course.
I guess my prob is (somehow) related to the awt.properties. When invoking, e.g.,
Has anybody an idea / workaround how I get these modifier keys displayed localized. Is there perhaps a way to change the awt-property on runtime or, at least, to set the values of these properties, e.g. AWT.control?
Thanks!
I have a problem with localization and accelerator keys. I am developing a localized Swing GUI where a user can set his preffered Locale and then all texts are translated.... That's all no prob. The problem is, that in JMenus the accelerator keys for items are displayed not according to the set default locale (e.g., en-US) but are displayed according to the OS user.language (in my case de [German]). Hence, the accel. keys read, e.g., '*Strg-N*' instead of '*Ctrl-N*' as expected for default locale en.
This is just a display problem, the functionality / the keys work fine, of course.
I guess my prob is (somehow) related to the awt.properties. When invoking, e.g.,
KeyEvent.getKeyModifiersText(keyStroke.getModifiers()(which I assume is called for JMenuItems to display the acc keys) I get the modifier key as string in German. These properties are loaded on startup? according to the OS user language. If i change my user language (e.g., with the jvm switch
-Duser.language=en) everything is fine. When changing this system property inside Java Code (e.g. in my main-method) the awt.properties are already loaded (somehow) with the OS user.language. Hence, this option doesn't work.
Has anybody an idea / workaround how I get these modifier keys displayed localized. Is there perhaps a way to change the awt-property on runtime or, at least, to set the values of these properties, e.g. AWT.control?
Thanks!
Comments
-
Hello Luc,
I just had a look in the sources and found that KeyEvent reads the accelerator text withToolkit.getProperty("AWT.control", "Ctrl")Toolkit, however, has no setProperty method. So that's bad news. At least I have no other idea than to vote for an enhancement at SUNs.
Greetings
J�rg -
Can't you just use one of the KeyStroke#getKeyStroke() methods to return a KeyStroke, and set the JMenuItem's accelerator to that?
-
I just had a look in the sources and found that KeyEvent reads the accelerator text withI just looked at the getProperty(...) method in the Toolkit class and it uses a ResourceBundle to get the string. Here is a comment from the code:
Toolkit.getProperty("AWT.control", "Ctrl")/** * Support for I18N: any visible strings should be stored in * sun.awt.resources.awt.properties. The ResourceBundle is stored * here, so that only one copy is maintained. */ private static ResourceBundle resources;
I have never used a resource bundle so I don't know how to go about creating one, but there is a tutorial on "Internationalization" that may help:
http://java.sun.com/docs/books/tutorial/ -
Well, a ResourceBundle is very similar to a properties file. In I18N you generally create one for each language.
But suppose you want to modify or replace sun.awt.resources.awt.properties, do you know how to do that (find that location)?
If, however, Luc is right with his supposition that the properties are loaded on startup, the file had to be replaced/reloaded at runtime to change the language - another problem. -
The solution would be to set the user language or the locale before the Toolkit class gets loaded. This would generally be VERY early in the startup sequence, say the first lines of your main method. Because as soon as you start using any GUI related classes such as JFrame, the Toolkit class will also get loaded.
In my first attempt to solve your problem it didn't work even though I set the locale on the FIRST line of my main method. The problem was that my test class itself extended from JFrame, so the JFrame class got loaded before the main method executed. And loading JFrame means also loading Component means loading Toolkit means the resources got loaded with the default VM user language.
See the Toolkit class, where you can find the following code (I put a break point on this line):resources = ResourceBundle.getBundle("sun.awt.resources.awt", CoreResourceBundleControl.getRBControlInstance());
Find below a running example which solves your problem:import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.util.Locale; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; public class Accelerators { static void createAndShowGui() { JMenuBar bar = new JMenuBar(); JMenu menu = new JMenu("File"); bar.add(menu); menu.add(new JMenuItem(new AbstractAction() { { putValue(Action.NAME, "Save"); putValue(Action.ACCELERATOR_KEY, KeyStroke .getKeyStroke("ctrl S")); } public void actionPerformed(ActionEvent e) { JOptionPane .showConfirmDialog( null, "Notice language of dialog caption & buttons.\nThese also depend on the user.language"); } })); JFrame f = new JFrame("Accelerators"); f.getContentPane().add(bar, BorderLayout.NORTH); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLocationRelativeTo(null); f.setSize(300, 300); f.setVisible(true); } public static void main(String[] args) { // Locale.setDefault(Locale.US); Locale.setDefault(Locale.GERMAN); // or: // System.setProperty("user.language", "en"); // System.setProperty("user.language", "de"); SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } }
-
Hello Numain,
thank you for your solution. Setting the user language had no effect on the accelerator display at my site (1.6.0_03), but setting the locale worked fine.
So we can set the accelerator text for the predefined locales (10 altogether), but it is not possible to set the text for other (own) locales or change the text at runtime, isn't it? -
Your are right, the property setting does not work for me, either. I guess I haven't tested it... As to your questions, I have asked myself the same things, of course.
So far I have not seen any java program that was able to change these specific strings during runtime (which doesn't mean it's not possible - i'm thinking something like setting the Toolkit.resources field via reflection and then forcing the menu component tree to update its UI - but I wouldn't really go there).
About providing additional localizations:
For testing I created an additional rudimentary resource bundle class "awt_xx" (here the package ist important, or it will not be found by the resource loading mechanism which will look for "sun.awt.resources.awt_xx" class. Just create such a package in your test project.package sun.awt.resources; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.util.ListResourceBundle; import java.util.Locale; import java.util.ResourceBundle; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import sun.util.CoreResourceBundleControl; public class awt_xx extends ListResourceBundle { protected Object[][] getContents() { return new Object[][] { { "AWT.control", "XXX" } }; } public static void main(String[] args) { // what keys are there anyway in this infamous awt bundle? Locale.setDefault(Locale.US); ResourceBundle awtBundle = ResourceBundle.getBundle( "sun.awt.resources.awt", CoreResourceBundleControl .getRBControlInstance()); for (String key : awtBundle.keySet()) { System.out.println(key + "=" + awtBundle.getObject(key)); } // now switch to "dirty dirty location" ;-) Locale.setDefault(new Locale("xx")); JMenuBar bar = new JMenuBar(); JMenu menu = new JMenu("File"); bar.add(menu); Action action = new AbstractAction() { public void actionPerformed(ActionEvent e) { } }; action.putValue(Action.NAME, "Save"); action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl S")); menu.add(new JMenuItem(action)); JFrame f = new JFrame("Accelerators"); f.getContentPane().add(bar, BorderLayout.NORTH); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLocationRelativeTo(null); f.setSize(300, 300); f.setVisible(true); } }
-
Great! So one problem is solved.
-
Great, thank you all for your replies!!!
This discussion has been closed.