GUI Elements and I18N
Perhaps one of the most impressive Java I18N features is that it allows you to change GUI element labels without recompiling. To illustrate this capability, I've cobbled together a little one-button Swing program called I18NSwingDemo.java. The program can be invoked for either French or U.S. locales.
To run in French mode, you simply type the following from a DOS console:
java I18NSwingDemo fr FR
The two parameters represent language (French) and region (France), respectively. The program invocation produces the GUI displayed in Figure 1.
Figure 1 An I18N-enabled Swing program running in a French locale
To run the program in U.S. mode, you type this simple command:
java I18NSwingDemo en US
This produces the GUI displayed in Figure 2.
Figure 2 An I18N-enabled Swing program running in a U.S. locale
Achieving this little Swing program is very straightforward. The to-do list is as follows:
- Create a property file called Messages_fr_FR.properties.
- Create a second property file called Messages_en_US.properties.
- Edit Messages_fr_FR.properties and insert this pidgin French line: exitMessage=Cliquez pour terminer.
- Edit Messages_en_US.properties and insert this line: exitMessage=Click to exit.
- Save the two property files.
- Compile the Java class I18NSwingDemo.java.
- Run the program with the command-line parameters described above.
The code is illustrated here in excerpted form:
language = new String(args); country = new String(args); JFrame firstWindow = new JFrame(); firstWindow.setSize(WIDTH, HEIGHT); firstWindow.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE); Locale locale = new Locale(language, country); ResourceBundle captions = ResourceBundle.getBundle("Messages", locale); element1Caption = captions.getString("exitMessage"); JButton endButton = new JButton(element1Caption); EndingListener buttonEar = new EndingListener(); endButton.addActionListener(buttonEar); firstWindow.add(endButton); firstWindow.setVisible(true);
You can see how the JButton label is read in from the ResourceBundle in a locale-specific fashion.
It's easy to see how this scheme can be extended to I18N-enable a large application. Clearly, Java helps you solve the static text substitution problem.
But what about dynamic text substitution and formatting of things such as dates and currencies? In many cases, these data items are calculated at runtime, meaning you can't read them in from disk. To I18N-enable such data entities, you have to modify the source code—with all the attendant risks of changing legacy code. The example described in the next section is pretty trivial, but it's not hard to think of examples where date and currency calculations could become complex. To take one case, you might want to code an I18N-enabled projection algorithm for the future value of a multicurrency investment. As you'll see, AOP can be employed to solve this part of the I18N problem and to ameliorate the risk level.