13.4. Accessing Resources

The GlobalizedMessage class is specifically designed to facilitate management and access to localized resources. This class represents a single globalized resource. It contains the base name of the ResourceBundle, which contains the resource and the key to use to lookup the resource, and an optional array of arguments to interpolate into the localized resource using Java's MessageFormat [1] class. It also contains a localize(java.util.Locale) method, which is used to localize the resource to a particular Locale.

You should use this class to represent all localizable data for your application. In Section 13.5 Globalization and Bebop, you will learn how to pass GlobalizedMessages to Bebop components so that they will perform the lookup when it is time to display the localized resource to the user.

The following example demonstrates how to access the hello_world resource defined in PropertyResourceBundle. Assuming that those files are in the com.arsdigita.helloworld package, you would create a GlobalizedMessage to represent that resource and localize it as follows:

GlobalizedMessage message = new GlobalizedMessage(
    "hello_world",
    "com.arsdigita.helloworld.HelloWorldResources"
);

// print in English:
System.out.println((String) message.localize(new Locale("en", "", "")));

// print in Spanish:
System.out.println((String) message.localize(new Locale("es", "", "")));

// print in French:
System.out.println((String) message.localize(new Locale("fr", "", "")));

The output will appear as:

Hello world!
Hola todo el mundo!
Salut tout le monde!

You can also make a parameter out of resources that will be interpolated using the MessageFormat class. The next example will use the following PropertyResourceBundles:

WineResources_en.properties
this_wine_is=This is a {0} wine.
wine_color=red
WineResources_es.properties
this_wine_is=Este es un vino {0}.
wine_color=rojo
WineResources_fr.properties
this_wine_is=C'est un vin {0}.
wine_color=rouge

It is possible to create a GlobalizedMessage to perform the proper interpolation of the resource. For example, this works if the wine_color resource is retrieved from a MessageCatalog and is not stored statically in the PropertyResourceBundle.

GlobalizedMessage message = new GlobalizedMessage(
    "this_wine_is",
    "com.arsdigita.wine.WineResources",
    {"wine_color"}

);

// print in English:
System.out.println((String) message.localize(new Locale("en", "", "")));

// print in Spanish:
System.out.println((String) message.localize(new Locale("es", "", "")));

// print in French:
System.out.println((String) message.localize(new Locale("fr", "", "")));

The output will appear as follows:

This is a red wine.
Este es un vino rojo.
C'est un vin rouge.

NoteNote
 

When a key is not found in a ResourceBundle, or when the ResourceBundle is not found at all, the localize(java.util.Locale) method returns the key. This is done for two reasons: first, it is more user-friendly to display the key than it is to display an exception or error message. Second, this method makes it easier for a translator to see all the resources that need to be translated on a particular page.

CautionCaution
 

There are GlobalizedMessage constructors that do not have the base name of the ResourceBundle as a parameter. When these constructors are used, the base name of the ResourceBundle for the current application is used. This information is retrieved from the current ApplicationContext.

Using these constructors is discouraged because the method is non-deterministic with regard to changes in the application stack. For example, if an application written by one developer — e.g. notes — runs on top of a portal application written by another developer, and it is using these certain GlobalizedMessage constructors, an error can occur.

The first application is no longer the current running application, and therefore the base name of the ResourceBundle for the GlobalizedMessages will be set incorrectly. It will be set to the base name of the ResourceBundle for the Portal application.

Only use these constructors if you are sure that your application will always be at the top of the application stack.

Notes

[1]

http://java.sun.com/j2se/1.3/docs/api/java/text/MessageFormat.html