A Sample Application

Message Bundles

When you implement a web application, it is a good idea to collect all message strings in a central location. This process makes it easier to keep messages consistent and, crucially, makes it easier to localize your application for other locales. In this section, we show you how JSF makes it simple to organize messages. In the section "A Sample Application" on page 46, we put managed beans and message bundles to work.

You collect your message strings in a file in the time-honored properties format:

  guessNext=Guess the next number in the sequence!   answer=Your answer:

Note

Look into the API documentation of the load method of the java.util.Properties class for a precise description of the file format.


Save the file together with your classes for example, insrc/java/com/corejsf/messages.properties. You can choose any directory path and file name, but you must use the extension .properties.

You can declare the message bundle in two ways. The simplest way is to include the following elements in your faces-config.xml file:

  <application>      <resource-bundle>         <base-name>com.corejsf.messages</base-name>         <var>msgs</var>      </resource-bundle>   </application>

Alternatively, you can add the f:loadBundle element to each JSF page that needs access to the bundle, like this:

  <f:loadBundle basename="com.corejsf.messages" var="msgs"/>

In either case, the messages in the bundle are accessible through a map variable with the name msgs. (The base name com.corejsf.messages looks like a class name, and indeed the properties file is loaded by the class loader.)

You can now use value expressions to access the message strings:

  <h:outputText value="#{msgs.guessNext}"/>

That is all there is to it! When you are ready to localize your application for another locale, you simply supply localized bundle files.

Note

The resource-bundle element is more efficient than the f:loadBundle action since the bundle can be created once for the entire application. However, it is a JSF 1.2 feature. If you want your application to be compatible with JSF 1.1, you must use f:loadBundle.


When you localize a bundle file, you need to add a locale suffix to the file name: an underscore followed by the lower case, two-letter ISO-639 language code. For example, German strings would be in com/corejsf/messages_de.properties.

Note

You can find a listing of all two- and three-letter ISO-639 language codes at http://www.loc.gov/standards/iso639-2/.


As part of the internationalization support in Java, the bundle that matches the current locale is automatically loaded. The default bundle without a locale prefix is used as a fallback when the appropriate localized bundle is not available. See Horstmann and Cornell, 2004, 2005. Core Java 2, vol. 2, chap. 10, for a detailed description of Java internationalization.

Note

When you prepare translations, keep one oddity in mind: Message bundle files are not encoded in UTF-8. Instead, Unicode characters beyond 127 are encoded as \uxxxx escape sequences. The Java SDK utility native2ascii can create these files.


You can have multiple bundles for a particular locale. For example, you may want to have separate bundles for commonly used error messages.

Messages with Variable Parts

Often, messages have variable parts that need to be filled. For example, suppose we want to display the sentence "You have n points.", where n is a value that is retrieved from a bean. Make a resource string with a placeholder:

  currentScore=Your current score is {0}.

Placeholders are numbered {0}, {1}, {2}, and so on. In your JSF page, use the h:outputFormat tag and supply the values for the placeholders as f:param child elements, like this:

  <h:outputFormat value="#{msgs.currentScore}">      <f:param value="#{quiz.score}"/>   </h:outputFormat>

The h:outputFormat tag uses the MessageFormat class from the standard library to format the message string. That class has several features for locale-aware formatting.

You can format numbers as currency amounts by adding a suffix number,currency to the placeholder, like this:

  currentTotal=Your current total is {0,number,currency}.

In the United States, a value of 1023.95 would be formatted as $1,023.95. The same value would be displayed as 1.023,95 in Germany, using the local currency symbol and decimal separator convention.

The choice format lets you format a number in different ways, such as "zero points", "one point", "2 points", "3 points", and so on. Here is the format string that achieves this effect:

  currentScore=Your current score is {0,choice,0#zero points|1#one point|2#{0} points}.     

There are three cases: 0, 1, and greater-than or equal to 2. Each case defines a separate message string.

Note that the 0 placeholder appears twice, once to select a choice, and again in the third choice, to produce a result such as "3 points".

Listings 2-5 and 2-6 on page 53 illustrate the choice format in our sample application. The English locale does not require a choice for the message, "Your score is ...". However, in German, this is expressed as "Sie haben ... punkte" (You have ... points). Now the choice format is required to deal with the singular form "einen punkt" (one point).

For more information on the MessageFormat class, see the API documentation or Horstmann and Cornell, 2004, 2005. Core Java 2, vol. 2, chap. 10.

Setting the Application Locale

Once you have prepared your message bundles, you need to decide how to set the locale of your application. You have three choices:

1.

You can let the browser choose the locale. Set the default and supported locales in WEB-INF/faces-config.xml (or another application configuration resource):

<faces-config>    <application>       <locale-config>          <default-locale>en</default-locale>          <supported-locale>de</supported-locale>       </locale-config>   </application> </faces-config>

When a browser connects to your application, it usually includes an Accept-Language value in the HTTP header (see http://www.w3.org/International/questions/qa-accept-lang-locales.html). The JSF implementation reads the header and finds the best match among the supported locales. You can test this feature by setting the preferred language in your browser (see Figure 2-2).

Figure 2-2. Selecting the preferred language


2.

You can add a locale attribute to the f:view element for example,

<f:view locale="de">

The locale can be dynamically set:

<f:view locale="#{user.locale}"/>>

Now the locale is set to the string that the getLocale method returns. This is useful in applications that let the user pick a preferred locale.

3.

You can set the locale programatically. Call the setLocale method of the UIViewRoot object:

UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot(); viewRoot.setLocale(new Locale("de"));

See "Using Command Links" on page 125 of Chapter 4 for an example.


Core JavaServerT Faces
Core JavaServer(TM) Faces (2nd Edition)
ISBN: 0131738860
EAN: 2147483647
Year: 2004
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net