Isolating Locale-specific Text in International Java Applications | WebReference

Isolating Locale-specific Text in International Java Applications

By Rob Gravelle


One thing that GUI-based programs have in common is that they all display and/or manipulate text in some form or another. Java's Locale object allows you to display and manage data in a way that conforms to the rules of a particular geographical region, but only the formatting of the data, not the content itself because the String and related classes are not locale-sensitive. To handle those, the Java programming language provides a number of other classes. I'll explore those in this article.

Place Text in Properties Files to Separate Them from Source Code

A Properties file contains translatable text for a specific locale. The idea behind Properties files is that they are a convenient place to house text, which is separate from compiled Java classes. They are also easy to modify and update in any text editor. If you've ever worked with .ini files in Windows, the idea is very much the same except that Properties files are not used to initialize the application, but they can be accessed by it at any time.

Items in Properties files are treated as an array of key-value pairs, and they are always Strings. To create the ResourceBundle, invoke the getBundle() method, specifying the base name and Locale:

The getBundle() method looks for a Properties file that matches the base name and the Locale. When the getBundle() method locates the correct Properties file, it returns a PropertyResourceBundle object containing the key-value pairs from the Properties file. Here is a sample of what the contents of a Properties file might look like:

The key is on the left side of the equals sign and the value is on the right. You can create key-value pairs using any text you like, but keep in mind that the keys should be unique and that you should never change them after they are in use, unless you are certain that they are not referenced by the application.

To retrieve the translated value from the ResourceBundle, simply call the getString() method, passing it the unique key identifier:

Note that if getBundle() fails to find a match, it throws a MissingResourceException. To avoid this exception, you should always provide a default Properties file. The name of this file would begin with the base name of your ResourceBundle and end with the .properties suffix. In the code example above, which created the labels ResourceBundle, the default Properties file would be called

Creating Properties Files for Different Locales

Typically, the default file will contain text that matches your own locale, or perhaps one that is very common, such as US English. To support an additional locale, all you need to do is create a Properties file that contains the translated values, using the same keys. Here is the French Canadian version of the Properties file in the previous section:

ResourceBundle Naming

It's helpful to think of each ResourceBundle as a set of related subclasses that share the same base name. The characters following the base name indicate the language code, country code, and variant of a Locale. Hence, LabelsBundle_de_DE would describe the above bundle for German (de) and the country code for Germany (DE). The following would all be valid names for Properties files:

If a ResourceBundle file for the specified locale does not exist, getBundle() tries to find the closest match. For example, if LabelsBundle_fr_CA_UNIX is the desired class and the default Locale is en_US, getBundle() will look for Properties files in the following order:

Use the ListResourceBundle Class to Work with More Complex Data Types

The ListResourceBundle class manages resources in a convenient list form. Each ListResourceBundle is backed by a proper class instead of a Properties file. Using a class allows you to store any locale-specific object in a ListResourceBundle. The downside to using ListResourceBundles is that you have to redeploy your application whenever you change a value. You also have to create another Java source file and compile it into a class file to add support for an additional locale. For these reasons you should use a ListResourceBundle only if there is no way to store your data values as Strings.

Like Property files, the class name is constructed by appending the language and country codes to the base name of the ListResourceBundle. The key-value pairs are stored in a private two-dimensional array variable. The contents of the array are retrieved using a standard getter() method. Here is a typical ListResourceBundle class: