Performing Localization
As mentioned in Using Localized Data (page 343), data and messages in the Duke's Bookstore application have been localized for French, German, Spanish, and American English.
This section explains how to produce the localized error messages as well as how to localize dynamic data and messages.
Using Localized Data (page 343) describes how page authors access localized data from the page.
If you are not familiar with the basics of localizing web applications, see Chapter 14.
Creating a Resource Bundle
A
ResourceBundlecontains a set of localized messages. To learn how to create aResourceBundle, seeAfter you create the
ResourceBundle, put it in the same directory as your classes. Much of the data for the Duke's Bookstore application is stored in aResourceBundlecalledBookstoreMessages,located in<INSTALL>/javaeetutorial5/examples/web/bookstore/src/java/com/sun/bookstore/messages/.Localizing Dynamic Data
The Duke's Bookstore application has some data that is set dynamically in backing beans. Because of this, the beans must load the localized data themselves; the data can't be loaded from the page.
The
messagemethod inAbstractBeanis a general-purpose method that looks up localized data used in the backing beans:protected void message(String clientId, String key) { // Look up the requested message text String text = null; try { ResourceBundle bundle = ResourceBundle.getBundle("messages.BookstoreMessages", context().getViewRoot().getLocale()); text = bundle.getString(key); } catch (Exception e) { text = "???" + key + "???"; } // Construct and add a FacesMessage containing it context().addMessage(clientId, new FacesMessage(text)); }This method gets the current locale from the
UIViewRootinstance of the current request and loads the localized data for the messages using thegetBundlemethod, passing in the path to theResourceBundleand the current locale.The other backing beans call this method by using the key to the message that they are trying to retrieve from the resource bundle. Here is a call to the
messagemethod fromShowCartBean:Localizing Messages
The JavaServer Faces API provides two ways to create messages from a resource bundle:
- You can register the
ResourceBundleinstance with the application configuration resource file and use a message factory pattern to examine theResouceBundleand to generate localizedFacesMessageinstances, which represent single localized messages. The message factory pattern is required to access messages that are registered with theApplicationinstance. Instead of writing your own message factory pattern, you can use the one included with the Duke's Bookstore application. It is calledMessageFactoryand is located in<INSTALL>/javaeetutorial5/examples/web/bookstore6/src/java/com/sun/bookstore6/util/.- You can use the
FacesMessageclass to get the localized string directly from theResourceBundleinstance.Registering Custom Error Messages (page 459) includes an example of registering a
ResourceBundlein the application configuration resource file.Creating a Message with a Message Factory
To use a message factory to create a message, follow these steps:
- Register the
ResourceBundleinstance with the application. This is explained in Registering Custom Error Messages (page 459).- Create a message factory implementation. You can simply copy the
MessageFactoryclass included with the Duke's Bookstore application to your application.- Access a message from your application by calling the
getMessage(FacesContext, String, Object)method of theMessageFactoryclass. TheMessageFactoryclass uses theFacesContextto access theApplicationinstance on which the messages are registered. TheStringargument is the key that corresponds to the message in theResourceBundle. TheObjectinstance typically contains the substitution parameters that are embedded in the message. For example, the custom validator described in Implementing the Validator Interface will substitute the format pattern for the{0}in this error message:
Input must match one of the following patterns {0}Implementing the Validator Interface gives an example of accessing messages.
Using FacesMessage to Create a Message
Instead of registering messages in the application configuration resource file, you can access the
ResourceBundledirectly from the code. ThevalidateEmailmethod from the Coffee Break example does this:... String message = ""; ... message = CoffeeBreakBean.loadErrorMessage(context, CoffeeBreakBean.CB_RESOURCE_BUNDLE_NAME, "EMailError"); context.addMessage(toValidate.getClientId(context), new FacesMessage(message)); ...These lines also call the
loadErrorMessageto get the message from theResourceBundle. Here is theloadErrorMessagemethod fromCoffeeBreakBean: