Core JSTL Mastering the JSPT Standard Tag Library [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Core JSTL Mastering the JSPT Standard Tag Library [Electronic resources] - نسخه متنی

David M. Geary

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید











7.5 Use of <fmt:message>


The JSTL I18N actions all work together for one purpose:

to retrieve Request Encoding" on page 287


<fmt:message" on page 502 for a complete description of <fmt:message> syntax.



<fmt:message key [bundle] [var] [scope]/>


The key attribute, which is mandatory in the preceding syntax, specifies a key in a resource bundle. Usually, <fmt:message> actions search for a localization context (that contains a resource bundle) themselves, but you can also specify a localization context with the optional bundle attribute.

<fmt:message> actions send their localized message to the current JspWriter or, if you specify the var and scope attributes, to a scoped variable. Here are three examples of how you can use <fmt:message> with the preceding syntax:


<fmt:message key='greeting'/>
<fmt:message key='greeting' var ='msg' scope='request'/>
<fmt:message key='greeting' bundle='${aLocalizationContext}'/>

The first line of the preceding code fragment shows the simplest use of Localization Contexts" on page 263is a simple bean that contains a resource bundle and a locale; if you specify a localization context with the bundle attribute, the corresponding <fmt:message> action will use that localization context's resource bundle to retrieve a localized message. This use of <fmt:message> is not very popular, because it's cumbersome to specify a localization context every time you use <fmt:message>.

[9] The word bundle is a misnomer. The <fmt:message> bundle attribute used to refer to a resource bundle, but now it refers to a localization context.


You can also localize compound messages with <fmt:message>, with this syntax:


<fmt:message key [bundle] [var] [scope]>

<fmt:param> actions

</fmt:message>


A compound message contains parameters; for example, at the bottom of your website you might show the current date with a compound message that looks like this: Today is: {0}, where {0} is a parameter that specifies the current date. You could do that like this:


<jsp:useBean id='now' class='java.util.Date'/>
<fmt:message key='footer.messages.todaysDate'>
<fmt:param value='${now}'/>
</fmt:message>

The preceding code fragment uses <jsp:useBean> to create a Java beanan instance of java.util.Date. A <fmt:param> action specifies that bean as a parameter for its enclosing <fmt:message> action. That <fmt:message> action substitutes the bean's value for {0} in the compound message. In a resource bundle, you would specify that compound message like this:


footer.messages.todaysDate=Today is: {0}

See "Compound Messages and <fmt:param>" on page 283 for more information about compound messages and message parameters. Also, see Listing 7.16 on page 285 for an alternative to <jsp:useBean> in the preceding code fragment by using the fmt_rt tag library.

The <fmt:message> action also lets you specify the message key in the body of the action, with this syntax:


<fmt:message [var] [scope] [bundle]>

key

optional <fmt:param> actions

</fmt:message>


Long message keys and message keys produced by custom actions are two reasons for the preceding syntax; for example, you might store categories for user preferences as message keys, and you might access those categories with custom actions, so you could do this:


<fmt:message>
<acme:preference category='SESSION_TIMEOUT'/>
</fmt:message>

In the preceding code fragment, the <acme:preference> custom action returns the message key associated with a user's session timeout; e.g., preferences.session.timeout. That key is used by <fmt:message> to display a localized message; for example, User Session Timeout, for an English locale. That technique essentially lets you create constant values for message keys, so that you can change the keys without changing your JSP pages.

If you specify a null value or an empty string for the <fmt:message> key attribute, that <fmt:message> action will produce this message: ??????. If a <fmt:message> action cannot locate a localization context or if the specified key is not defined in the resource bundle stored in the localization context, <fmt:message> will produce output that looks like this: ???<key>???, where <key> represents the value that you specified for the action's key attribute.

Localization Context Lookup


As we saw in "Use of <fmt:message>" on page 265, <fmt:message> actions use a resource bundle stored in a localization context to turn message keys into localized messages. To locate a localization context, all <fmt:message> actions perform a

localization context lookup; once they find a localization context, they use its resource bundle to localize their messages. That lookup works like this:


  1. If the <fmt:message>

    bundle

    attribute is specified, use it.


  2. If the <fmt:message> action is

    nested in a <fmt:bundle> action, use the enclosing <fmt:bundle> action's localization context.


  3. Use the FMT_LOCALIZATION_CONTEXT

    configuration setting.




Core Approach






It's easy to remember how <fmt:message> actions search for a localization context if you realize that <fmt:message> searches

from within itself (the bundle attribute)

outward to its enclosing <fmt:bundle> action, if any, and then to the FMT_LOCALIZATION_CONTEXT configuration setting, which applies to a specific scope.

Let's discuss each of the steps listed above.

1 If the <fmt:message>

bundle attribute is specified, use it.


First, <fmt:message> checks to see if you specified its bundle attribute, for example:


<fmt:message key='footer.messages.title' bundle='${messages}'/>

If you specify the bundle attribute, <fmt:message> assumes that the bundle attribute's value (${messages} in the preceding code fragment) is a localization context, and it uses that localization context's resource bundle to localize its message. That localization context is most often created by business components, but you can easily create one in a scriptlet, like this:[10]

[10] The scriptlet approach is not recommended; it's shown here for illustration only.



<%@ page import='javax.servlet.jsp.jstl.fmt.LocalizationContext'%>
<%@ page import='java.util.*'%>
<% ResourceBundle rb =
ResourceBundle.getBundle("messages", Locale.FRENCH);
LocalizationContext lc = new LocalizationContext(rb);
pageContext.setAttribute("messages", lc);
%>
<fmt:message key='company.slogan' bundle='${messages}'/>

The preceding code fragment retrieves a French resource bundle, which is used to create a localization context. The scriptlet stores the localization context in page scope by using PageContext.setAttribute. Subsequently, a <fmt:message> action accesses that localization context by specifying it with the action's bundle attribute.

Specifying a localization context with the <fmt:message> bundle attribute is cumbersome because you have to specify that localization context for every <fmt:message> action. It would be better if you could group <fmt:message> actions that use the same localization context; in fact, you can do just that with the <fmt:bundle> action, which is discussed next.

2 If the <fmt:message> action is

nested in a <fmt:bundle> , use the enclosing <fmt:bundle> action's localization context.


If you don't specify the bundle attributeas is usually the case<fmt:message> actions check to see if they are nested in a <fmt:bundle>" on page 500 for a complete description of <fmt:bundle> syntax, including the prefix attribute.



<fmt:bundle basename [prefix]>

body content, presumably with I18N or formatting actions, or both

</fmt:bundle>


All <fmt:message> actions in the body of a <fmt:bundle> action implicitly access the localization context of their enclosing <fmt:bundle> action; for example, in the following code fragment, the first two <fmt:message> actions use the localization context established by their enclosing <fmt:bundle> action.


<fmt:bundle

basename='messages' >
<%-- The two <fmt:message> actions that follow use the resource
bundle associated with the bundle base name "messages" --%>
<fmt:message key='login.title'/>
<fmt:message key='login.welcome'/>
<%-- This <fmt:message> action uses a different
localization context --%>
<fmt:message key='login.footer'

bundle='${footers}' />
</fmt:bundle>


The third <fmt:message> action in the preceding code fragment uses a localization context that contains a resource bundle whose base name is footers. Because <fmt:message> actions check their bundle attribute first, that attribute overrides the localization context established by an enclosing <fmt:bundle>; so, in the preceding code fragment, the footers localization context overrides the messages localization context for the third <fmt:message> action.

The <fmt:bundle> action has a mandatory basename attribute that specifies a resource bundle base name. That attribute is a string that <fmt:bundle> actions use to search for a resource bundle, which is subsequently stored in the <fmt:bundle> action's localization context. See "The Resource Bundle Lookup Algorithm" on page 276 for more information about that resource bundle search.

The <fmt:bundle> action is great for grouping <fmt:message> actions that use the same localization context, so you don't have to specify a localization context for every <fmt:message> action. But <fmt:bundle> cannot span JSP pages; it would be nice if you could specify a localization context for all <fmt:message> actions in a particular scope, say, request or session. You can do that with the <fmt:setBundle> action, which is discussed below.

3 Use the FMT_LOCALIZATION_CONTEXT configuration setting.

If a <fmt:message> action is free-standing (meaning it's not enclosed in a <fmt:bundle> action) and its bundle attribute is not specified, then the <fmt:message> action looks for a localization context in the FMT_LOCALIZATION_CONTEXT configuration setting; for example:

<%-- The following <fmt:message> action is not nested in
<fmt:bundle> and does not specify the bundle attribute, so it uses the
FMT_LOCALIZATION_CONTEXT configuration setting --%>
<fmt:message key='footer.messages.title'/>


The FMT_LOCALIZATION_CONTEXT configuration setting is listed in Table 7.7.


























Table 7.7. FMT_LOCALIZATION_CONTEXT Configuration Setting

Config Constant


FMT_LOCALIZATION_CONTEXT


Name


javax.servlet.jsp.jstl.fmt.localizationContext


Type


java.lang.String or javax.servlet.jsp.jstl.fmt.LocalizationContext


Set by


<fmt:setBundle>, Deployment Descriptor, Config class


Used by


<fmt:message>, <fmt:formatNumber>, <fmt:parseNumber>, <fmt:formatDate>, <fmt:parseDate>

In a nutshell, a JSTL configuration setting is a combination of a context initialization parameter and a scoped variable, where the latter can override the former. Configuration settings are searched for in this order: page scope, request scope, session scope, application scope, context initialization parameter.Configuration Settings" on page 230 for more information about configuration settings.


Because you can specify a configuration setting as a string, you can specify the FMT_LOCALIZATION_CONTEXT configuration setting as a context initialization parameter in a deployment descriptor, like this:


<web-app>
...
<context-param>
<param-name>

javax.servlet.jsp.jstl.fmt.localizationContext
</param-name>
<param-value>

messages
</param-value>
</context-param>
...
</web-app>


The preceding fragment of a deployment descriptor (WEB-INF/web.xml) declares a context initialization parameter named javax.servlet.jsp.jstl.localizationContext, which is the name of the FMT_LOCALIZATION_CONTEXT configuration setting (see <fmt:setBundle>" on page 498 for a complete description of <fmt:setBundle> syntax.



<fmt:setBundle basename [var] [scope]/>


Like <fmt:bundle>, <fmt:setBundle> has a mandatory basename attribute that specifies a resource bundle basename; for example:


<fmt:setBundle basename='messages' scope='request'/>

The <fmt:setBundle> action in the preceding line of code locates a resource bundle based on the action's mandatory basename attribute (messages), and stores that resource bundle in the localization context stored in the FMT_LOCALIZATION_CONTEXT configuration setting. Instead of storing the localization context in that configuration setting, <fmt:setBundle> will store it in a scoped variable if you specify the var, and optionally the scope, attribute.

Whether you specify the Resource Bundles" on page 259 for more information about resource bundles and resource bundle base names.


You can also specify the FMT_LOCALIZATION_CONTEXT configuration setting in a business component, such as a servlet like the one listed below:The Config Class" on page 239 for more information about the Config class.



...
import javax.servlet.jsp.jstl.core.Config;
public class InitializationServlet extends HttpServlet {
public void init() throws ServletException {
// Create a localization context and store it in
// the FMT_LOCALIZATION_CONTEXT configuration setting

Config.set (getServletContext(),
Config.FMT_LOCALIZATION_CONTEXT,

"messages"); // resource bundle base name
}
}


When the servlet in the preceding code fragment starts, it sets the FMT_LOCALIZATION_CONTEXT configuration setting with the string messages, which represents a resource bundle base name. The preceding servlet uses the Config class from the javax.servlet.jsp.jstl.core package to set the FMT_LOCALIZATION_CONTEXT configuration setting. See "The Config Class" on page 239 for more information about how you use the Config class.

You can also specify the FMT_LOCALIZATION_CONTEXT configuration setting with an instance of javax.servlet.jsp.jstl.LocalizationContext; for example, the preceding servlet could be modified as follows:


...
import java.util.Locale;
import java.util.ResourceBundle;
import javax.servlet.jsp.jstl.core.Config;
import javax.servlet.jsp.jstl.fmt.LocalizationContext;
public class InitializationServlet extends HttpServlet {
public void init() throws ServletException {
...
Locale l = Locale.US;
ResourceBundle rb = ResourceBundle.getBundle("basename", l);

Config.set (getServletContext(),
Config.FMT_LOCALIZATION_CONTEXT,

new LocalizationContext(rb, l) );
...
}
}


This section discussed the localization context lookup. The next section discusses how a localization context's resource bundle, if not explicitly specified, is determined.

Resource Bundle Lookup


We've covered some ground since we started discussing <fmt:message> at "Use of <fmt:message>" on page 265; here are the highlights:


  • <fmt:message> retrieves localized messages from resource bundles stored in localization contexts.


  • <fmt:message> performs a localization context lookup by searching in the following locations:


    1. The <fmt:message> bundle attribute


    2. An enclosing <fmt:bundle> action


    3. The FMT_LOCALIZATION_CONTEXT configuration setting



  • <fmt:bundle> lets you specify a single localization context for a group of <fmt:message> actions nested in the <fmt:bundle> action.


  • <fmt:setBundle> lets you specify a localization context for a given scope. That localization context is shared by <fmt:message> actions in that scope.



<fmt:message> actions perform a

localization context lookup to find a localization context they can use to localize messages. Those localization contexts are, for the most part, created by <fmt:bundle> or <fmt:setBundle>, both of which perform a

resource bundle lookup, given a resource bundle base name. If you specify a string for the FMT_LOCALIZATION_CONTEXT configuration setting, <fmt:message> actions will also perform a resource bundle lookup, using that string as a resource bundle base name. We've already discussed localization context lookups in "Localization Context Lookup" on page 268, so this section focuses on the resource bundle lookup performed by <fmt:bundle>, <fmt:setBundle>, and <fmt:message>.

The resource bundle lookup performed by <fmt:bundle>, <fmt:setBundle>, and <fmt:message> requires two pieces of information: a resource bundle base name and one or more locales. You specify a resource bundle base name with the <fmt:bundle> and <fmt:setBundle> mandatory bundle attributes. The next section shows you how to specify the locale.

Locales

You can specify the locale(s) that the <fmt:bundle>, <fmt:setBundle>, and <fmt:message> actions use to find a resource bundle in one of two ways:


  • The set of preferred locales that you specify in your browser


  • The FMT_LOCALE configuration setting



By default, the resource bundle lookup uses your browser's preferred locales, but you can override that default with the Configuration Settings" on page 230 shows you how to do all those things. The FMT_LOCALE configuration setting is listed in Table 7.8.


























Table 7.8. The FMT_LOCALE Configuration Setting

Config Constant


FMT_LOCALE


Name


javax.servlet.jsp.jstl.fmt.locale


Type


java.lang.String or java.util.Locale


Set by


<fmt:setLocale>, Deployment Descriptor, Config class


Used by


<fmt:bundle>, <fmt:setBundle>, <fmt:message>, <fmt:formatNumber>, <fmt:parseNumber>, <fmt:formatDate>, <fmt:parseDate>

You can also set the <fmt:setLocale>" on page 496 for a more complete description of <fmt:setLocale> syntax.



<fmt:setLocale value [variant] [scope]/>


The <fmt:setLocale> value attribute specifies a locale as either a language or a language-country combination, such as fr or fr-CA. The variant attribute specifies a browser- or vendor-specific value, such as WIN for Windows or MAC for Macintosh. See "Locales" on page 258 for more information about locales and variants. In practice, variants are seldom used.

The scope attribute, which can be page, request, session, or application, specifies the scope to which the locale applies. For example, if you specify application scope, the locale specified with the value attribute will apply to all JSP pages in your application. The default scope is page.

The Resource Bundle Lookup Algorithm

The resource bundle lookup algorithm performed by <fmt:message>, <fmt:bundle>, and <fmt:setBundle> starts with a resource bundle base name and a list of preferred locales. If you've set the FMT_LOCALE configuration setting, then your list of preferred locales consists of the single locale. If you haven't set the FMT_LOCALE configuration setting, then your browser's list of preferred locales will be used.

For each preferred locale in order of preference, JSTL searches for resource bundles in WEB-INF/classesor a subdirectory of WEB-INF/classeswith the following names:


basename + "_" +

language + "_" +

country + "_" +

variant + "." + class

basename + "_" + language + "_" + country + "_" + variant + "." + properties

basename + "_" + language + "_" + country + "." + class

basename + "_" + language + "_" + country + "." + properties

basename + "_" + language + "." + class

basename + "_" + language + "." + properties


For the preceding names,

basename represents a bundle base name, and

language, country, and

variant are specified by a locale. As soon as a match is found, the algorithm selects that resource bundle and stops.

If the set of available resource bundles changes during the execution of a page, the resulting behavior is undefined; leaving that behavior undefined allows implementations to cache resource bundles to improve performance.

If no resource bundle is found for any of the preferred locales, the resource bundle lookup is applied to the

fallback locale, which you can set with the FMT_FALLBACK_LOCALE configuration variable.[17]

[17] None of the JSTL actions set the FMT_FALLBACK_LOCALE configuration setting, so it's most often set in the deployment descriptor with a context initialization parameter.


If <fmt:bundle>, <fmt:setBundle>, or <fmt:message> cannot find a resource bundle with the preferred locales or the fallback locale, they try to find a resource bundle with only the base name.

To help clarify the resource bundle search algorithm, here are some examples that illustrate how the algorithm works:

Example 1:


  • Bundle base name :
    Resources


  • Preferred locales :
    en_GB, fr_CA


  • Fallback locale:
    fr_CA


  • Application resource bundles:


    /WEB-INF/classes/Resources_en.class,
    /WEB-INF/classes/Resources_fr_CA.properties


The algorithm matches the en_GB locale with this Java class: /WEB-INF/classes/Resources_en.class.

Example 2:


  • Bundle base name :
    Resources


  • Preferred locales :
    de, fr


  • Fallback locale:
    en


  • Application resource bundles:


    /WEB-INF/classes/Resources_en.properties


The algorithm does not find a match for the de or fr locales, but it does find a match for the fallback locale; therefore, the selected resource bundle is specified with this properties file: /WEB-INF/classes/Resources_en.properties.

Example 3:


  • Bundle base name :
    Resources


  • Preferred locales :
    fr, sv, en


  • Fallback locale:
    de


  • Application resource bundles:


    /WEB-INF/classes/Resources_fr_CA.properties,
    /WEB-INF/classes/Resources_sv.properties,
    /WEB-INF/classes/Resources_en.properties,
    /WEB-INF/classes/Resources_de.class


The algorithm does not find a match for the fr locale, because that locale specifies French, not

Canadian French. The algorithm does find a match for the sv locale (Swedish), and therefore selects the resource bundle specified with the properties file /WEB-INF/classes/Resources_sv.properties.

In this case, even though the user prefers French over Swedish and has a French resource bundle, that resource bundle will not be selected, because it is Canadian French. This example illustrates that resource bundles for a specific language and country should be backed up with a resource bundle covering just the language. If the country-specific differences for a language are too significant for a language-only bundle, users should specify two locales with both language and country in their list of preferred locales.

An Example of Dynamically Switching Locales


This section discusses a Web application, shown in Figure 7-4, that lets users change their locale by clicking on an image of a flag. Changing the locale initiates the resource bundle search algorithm discussed in "The Resource Bundle Lookup Algorithm" on page 276, which changes the current resource bundle. The Login button does not initiate a login; for the sake of illustration, it simply reloads the login page.

Figure 7-4. Using <fmt:setLocale>Clicking on a Flag Switches Locales


The application shown in Unicode and Charsets" on page 260 for more information about charsets and UTF-8. The preceding JSP page uses <fmt:setBundle> to specify a bundle base name for the JSP page. The application's properties files are listed below.

The Chinese properties fileapp_zh.propertiesspecifies messages with Unicode escape sequences; see "Unicode and Charsets" on page 260 for more information about Unicode.

The JSP page listed in Listing 7.9 also imports flags.jsp and set_locale.jsp. The former displays the flags, and the latter sets the locale, depending on which flag was last selected.

When the application is started, no flags have been selected, so the locale is determined from the javax.servlet.jsp.jstl.fmt.locale context initialization parameter, which is specified in WEB-INF/web.xml. Listing 7.13 lists an excerpt from that deployment descriptor.

In the preceding listing, the FMT_LOCALE configuration variable (whose value is javax.servlet.jsp.jstl.fmt.locale) is set to de, so the application shown in Figure 7-4 is initially displayed in German.

flags.jsp is listed in Listing 7.14.

The preceding JSP page displays the flags shown in Figure 7-4 on page 278. When you click on one of those flags, the current page in which flags.jsp resides is reloaded with the corresponding locale request parameter.

Note that the preceding JSP page uses the rather unusual HTML construct <a href=''>. That construct causes the current HTML (or JSP) page to be reloaded with XXX appended to the page's URL as a request parameter. That construct comes in handy for developing reusable HTML or JSP components, such as the JSP page listed in Listing 7.14. You can read about that construct in section 4.0 (Resolving Relative URLs) of RFC 1808; that RFC is available online at this URL: http://www.ietf.org/rfc/rfc1808.txt.

The JSP page set_locale.jsp, which sets the locale according to the last flag selected, is listed in Listing 7.15.

The preceding JSP page sets the locale for the user's session with <fmt:setLocale>, depending on the value of the locale request parameter. If that request parameter has not been set, the preceding JSP page does nothing.

Listing 7.9 index.jsp


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<%-- Set the charset to UTF-8 for multiple language
support --%>
<%@ page contentType='text/html; charset=UTF-8' %>
<%@ taglib uri='http://java.sun.com/jstl/fmt' prefix='fmt'%>
<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c'%>
<%-- set_locale.jsp sets the locale according to the locale
request parameter that is set by flags.jsp, which is
imported below. set_locale.jsp uses <fmt:setLocale>--%>

<c:import url='set_locale.jsp'/>
<%-- Establish a localization context (based on the locale
set by set_locale.jsp and the bundle base name specified
for <fmt:setBundle>) used by subsequent <fmt:message>
actions. Because the locale set by set_locale.jsp is
used to establish that localization context,
set_locale.jsp must be imported before
<fmt:setBundle> is used. --%>

<fmt:setBundle basename='app'/>
<%-- Use <fmt:message> to show the page title --%>
<title><fmt:message key='login.page.title'/></title>
</head>
<body>
<%-- flags.jsp shows the flags --%>

<c:import url='flags.jsp'/> <br>
<%-- All of the <fmt:message> actions that follow will
use the resource bundle determined by the 'app'
bundle base name and the locale that was last selected
by a user clicking on a flag. Initially, that locale is
set by the javax.servlet.jsp.jstl.fmt.locale
context init param in WEB-INF/web.xml. --%>
<fmt:message key='login.form.title'/><hr/>
<form method='post'>
<table>
<tr><td><fmt:message key='login.textfield.name'/></td>
<td><input type='text' name='userName'/></td>
</tr>
<tr>
<td><fmt:message key='login.textfield.pwd'/></td>
<td><input type='password' name='password'/></td>
</tr>
</table><br>
<input type='submit'
value='<fmt:message key="login.button.submit"/>'/>
</form>
</body>
</html>


Listing 7.10 WEB-INF/classes/app_en.properties


login.page.title=Switching Locales
login.form.title=Please Log In
login.textfield.name=Name
login.textfield.pwd=Password
login.button.submit=Login

Listing 7.11 WEB-INF/classes/app_de.properties


login.page.title=Schaltend Locales
login.form.title=Bitte Ausstellung(Einrichtung) der Verbindung
login.textfield.name=Name:
login.textfield.pwd=Password:
login.button.submit=Ausstellung(Einrichtung) der Verbindung

Listing 7.12 WEB-INF/classes/app_zh.properties


login.page.title=\u8bf7\u767b\u5f55
login.form.title=\u8bf7\u767b\u5f55
login.textfield.name=\u7528\u6237\u540d
login.textfield.pwd=\u5bc6\u7801
login.button.submit=\u767b\u5f55

Listing 7.13 WEB-INF/web.xml (Excerpt)


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.3.dtd">
<web-app>
...
<context-param>
<param-name>

javax.servlet.jsp.jstl.fmt.locale
</param-name>
<param-value>

de
</param-value>
</context-param>
...
</web-app>


Listing 7.14 flags.jsp


<table>
<tr><td>
<a href=''>
<img src='/image/library/english/10238_britain_flag.gif'/></a>
<a href=''>
<img src='/image/library/english/10238_german_flag.gif'/></a>
<a href=''>
<img src='/image/library/english/10238_chinese_flag.gif'/></a>
</td></tr>
</table>

The <fmt:setLocale> action calls ServletResponse.setLocale(), which is required by the servlet specification, to set the response charset to match the specified locale. Because of that requirement, index.jsp, listed in Listing 7.9 on page 280, should not have to specify the UTF-8 charset; however, some servlet containers do not properly implement that requirement, so the contentType page directive in Listing 7.9 on page 280 is necessary to ensure that the example works with all servlet containers.

Listing 7.15 set_locale.jsp


<%@ taglib uri='http://java.sun.com/jstl/fmt' prefix='fmt'%>
<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c'%>
<c:choose>
<c:when test='${param.locale == "de"}'>
<fmt:setLocale value='de' scope='session'/>
</c:when>
<c:when test='${param.locale == "zh"}'>
<fmt:setLocale value='zh' scope='session'/>
</c:when>
<c:when test='${param.locale == "en"}'>
<fmt:setLocale value='en' scope='session'/>
</c:when>
</c:choose>

Also, notice that flags.jsp and set_locale.jsp can be used in any JSP page to switch locales. In fact, those JSP pages, modified to display different flags, are used in the Web applications discussed below and in "Validation with JSP Pages" on page 296.

Compound Messages and <fmt:param>


When you go to the store, you might say, "I'm going to {0}," where {0} represents the name of the store; after all, there are only so many ways to say that you're going to the store. Sometimes you might say, "I'm going to {0} to get {1}."

This phenomenon, known as parameterized text, is commonplace; in fact, you can find many occurrences of "The JSP page shown in {0} is listed in {1}" scattered throughout this book.

You can parameterize text by specifying <fmt:param>" on page 504 for a more complete description of <fmt:param> syntax.



<fmt:param value/>


You can also specify a parameter within the body of a <fmt:param> action, with this syntax:


<fmt:param>

value

</fmt:param>


Figure 7-5 shows a Web application that uses both <fmt:param> syntaxes.

Figure 7-5. Localizing Compound Messages with <fmt:param> Actions


The Web application shown in Figure 7-5 provides parameters for a disk number and date. The top picture in Figure 7-5 shows the English version of the message, and the bottom picture shows the French version.

The JSP page shown in Figure 7-5 is listed in Listing 7.16.

Like the JSP page shown in Figure 7-4 on page 278, the preceding JSP page imports set_locale.jsp and flags.jsp so the user can switch locales and sets the bundle base name to app for page scope.

The preceding JSP page uses both syntaxes of <fmt:param> to specify parameters for a message specified with the message.diskFull key. The <fmt:param> action specifies its value in its body, whereas the <fmt_rt:param> action specifies its value with the value attribute. Notice that the second param tag uses the runtime expression library version of the param action (<fmt_rt:param>) because it creates a Java object for its value, which is something you cannot do with the expression language equivalent action (<fmt:param>).[19]

[19] But you can use <fmt:param> in combination with <jsp:useBean>; see "Use of <fmt:message>" on page 265.


Listing 7.16 index.jsp


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %>
<%@ taglib uri='http://java.sun.com/jstl/fmt' prefix='fmt'%>
<%@ taglib uri='http://java.sun.com/jstl/fmt_rt'
prefix='fmt_rt' %>
<%-- set_locale.jsp sets the locale according to the locale
request parameter that is set by flags.jsp, which is
imported below. set_locale.jsp uses <fmt:setLocale> --%>
<c:import url='set_locale.jsp'/>
<%-- Establish a localization context (based on the locale
set by set_locale.jsp and the bundle base name specified
for <fmt:setBundle>) used by subsequent <fmt:message>
actions. Because the locale set by set_locale.jsp is
used to establish that localization context,
set_locale.jsp must be imported before
<fmt:setBundle> is used. --%>
<fmt:setBundle basename='app'/>
<title><fmt:message key='page.title'/></title>
</head>
<body>
<c:import url='flags.jsp'/><br/>
<%-- All of the <fmt:message> actions that follow will
use the resource bundle determined by the 'app'
bundle base name and the locale that was last selected
by the user clicking on a flag. --%>
<fmt:message key='message.diskFull'>
<%-- Specify the parameter for the disk number
in the body of the <fmt:param> action --%>

<fmt:param>

5

</fmt:param>
<%-- Specify the parameter for the date
with the <fmt_rt:param> action's value
attribute --%>

<fmt_rt:param value='<%= new java.util.Date() %>'/>
</fmt:message>
</body>
</html>


The English and French properties files used by the application shown in Figure 7-5 are listed below.

Listing 7.17 WEB-INF/classes/app_en.properties


# application properties -- English Version
page.title=Using Compound Messages
message.diskFull=Disk number <b>{0}</b> filled up at <b>{1, time}</b> on <b>{1, date, full}</b>.

Listing 7.18 WEB-INF/classes/app_fr.properties


# application properties -- French Version
page.title=Utiliser les Messages Compose
message.diskFull=Le disque nombre <b>{0}</b> est rempli sur <b>{1, time}</b> <b>{1, date, full}</b>

The messages in the preceding properties files identify parameters with {0} and {1}. Those parameters are supplied by the <fmt:param> and <fmt_rt:param> actions, respectively.

The preceding properties files also specify

styles to format the date supplied by <fmt:param>; for example, {1,

time } specifies the time portion of the date, and {1,

date, full } specifies the full date without the time. You can use other styles, such as {n, percent}, to specify a number as a percent. See the Java documentation for the java.text.MessageFormat class for more information about those styles.

The flags.jsp and set_locale.jsp JSP pages imported by the preceding JSP page are nearly identical to the JSP pages of the same name discussed in "An Example of Dynamically Switching Locales" on page 278, except for the flags and locales they support. Those files are listed in Listing 7.19 and Listing 7.20 for completeness.

Listing 7.19 flags.jsp


<table>
<tr><td>
<a href='-GB'>
<img src='/image/library/english/10238_united-kingdom-flag.gif'/></a>
<a href=''>
<img src='/image/library/english/10238_french-flag.gif'/></a>
</td></tr>
</table>

Listing 7.20 set_locale.jsp


<%@ taglib uri='http://java.sun.com/jstl/core'prefix='c' %>
<%@ taglib uri='http://java.sun.com/jstl/fmt' prefix='fmt'%>
<c:choose>
<c:when test='${param.locale == "fr-FR"}'>
<fmt:setLocale value='fr-FR' scope='request'/>
</c:when>
<c:when test='${param.locale == "en-GB"}'>
<fmt:setLocale value='en-GB' scope='request'/>
</c:when>
</c:choose>



    / 124