Isolating Locale-specific Text in International Java Applications [con't]
The following code gets the ResourceBundle for the current locale and retrieves the literacy rate by invoking getObject()
with the "Literacy"
key parameter. Because getObject()
returns an Object, we have to cast it to a Double
:
Creating Your Own ResourceBundle
You can write your own ResourceBundle by subclassing ResourceBundle. The only method that you must override is handleGetObject()
. The following is a very simple example, for a small number of objects (for a larger number you would probably use a Hashtable
). It features a getKeys()
function that returns them as a StringTokenizer
object:
There are a few key points to take note of in the above code:
- You must include code to deal with the event in which the key is not found. Two options are either to return null or to throw a
nullPointerException
. - You don't need to supply a value if a parent ResourceBundle handles the same key with the same value.
Loading Resource Bundles with the ResourceBundle.Control Class
ResourceBundle.Control
class allows you to specify how to locate and instantiate resource bundles. To do that, it relies on a set of callback methods that are invoked by the ResourceBundle.getBundle()
factory methods during the bundle-loading process. Instead of invoking the two-argument ResourceBundle.getBundle()
method we invoked earlier, we'll now call the same method that includes a third parameter for the specified Control. Without a ResourceBundle.Control
argument, the getBundle()
method always tries to find a Java class first before attempting to load a Properties file if an appropriate class cannot be located. We can instruct getBundle()
to look for a Java class only or a Properties file only, or change the order in which it searches. Here is how to make the getBundle()
method locate a Java class only:
The getCandidateLocales()
method returns a list of Locale objects as candidate locales for the base name and locale. We can override it to implement the specific behavior that we want. The following call to getBundle()
drives the process of searching the Chinese locales by passing in a new ResourceBundle.Control
class:
Properties files and class ResourceBundleLists are a fairly efficient means of managing translatable text in your Java applications, but they are not without limitations. We already touched upon some of the problems with ResourceBundleLists, including that you have to redeploy your application whenever you change a value or add a new locale. On the other hand, Properties files can be cumbersome to manage if you have many languages to support. Finally, some businesses already have a lot of text in other formats, such as XML. It would be a great timesaver to be able to work with those XML files directly. In fact, Java does provide a mechanism for doing just that. More on that in the next article....
Have a suggestion for an article topic? Do you have a product or service that you'd like reviewed? Email it to Rob .
Rob Gravelle combined his love of programming and music to become a software guru and accomplished guitar player. He created systems that are used by Canada Border Services, CSIS and other Intelligence-related organizations. As a software consultant, Rob has developed Web applications for many businesses and recently created a MooTools version of PHPFreechat for ViziMetrics. Musically, Rob recently embarked on a solo music career, after playing with Ivory Knight since 2000. That band was rated as one Canada's top bands by Brave Words magazine (issue #92) and released two CDs. Rob's latest release is called "The Rabbit of Seville". Loosely based on Rossini's The Barber of Seville overture, Rob's amazing rendition includes a full orchestra and numerous guitar tracks. It is sold on his site as a high bitrate MP3 for only $0.99 cents! Rob is available for short-term software projects and recording session work. to inquire, but note that, due to the volume of emails received, he cannot respond to every email. Potential jobs and praise receive highest priority!
Original: June 9, 2010