Recipe 12.4. Changing Locale on the Fly
Problem
You want to allow a user to choose the language and country to be used by the web application for his session.
Solution
Use my ChangeLocaleAction, based on the Struts built-in
LocaleAction, as shown in Example 12-5.
Example 12-5. Struts action for changing the current locale
package com.oreilly.strutsckbk.ch12;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.jsp.jstl.core.Config;
import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping;
/** * Implementation of <strong>Action</strong> that changes the user's * @link(java.util.Locale and forwards to a page, based on request level * parameters that are set (language, country, variant, & page). * Also changes the JSTL locale. */ public final class ChangeLocaleAction extends Action {
private static final String SUCCESS = "success"; /** * Commons Logging instance. */ private Log log = LogFactory.getFactory( ).getInstance(this.getClass( ). getName( ));
/** * <p> * Change the user's @link(java.util.Locale) based on @link(ActionForm) * properties. * </p> * <p> * This <code>Action</code> looks for <code>language</code> and * <code>country</code> and <code>variant</code> properties on the given * form, constructs an appropriate Locale object, and sets it as the Struts * Locale for this user's session as well as the JSTL locale. * Any <code>ActionForm, including a @link(DynaActionForm), may be used. * </p> * <p> * If a <code>page</code> property is also provided, then after * setting the Locale, control is forwarded to that URI path. * Otherwise, control is forwarded to "success". * </p> * * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request (if any) * @param request The HTTP request we are processing * @param response The HTTP response we are creating * * @return Action to forward to * @exception java.lang.Exception if an input/output error or servlet * exception occurs */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Extract attributes we will need HttpSession session = request.getSession( ); Locale locale = getLocale(request); String language = null; String country = null; String variant = null; String page = null; try { language = (String) PropertyUtils.getSimpleProperty(form, "language"); country = (String) PropertyUtils.getSimpleProperty(form, "country"); variant = (String) PropertyUtils.getSimpleProperty(form, "variant"); page = (String) PropertyUtils.getSimpleProperty(form, "page"); } catch (Exception e) { log.error(e.getMessage( ), e); }
boolean isLanguage = language != null && language.length( ) > 0; boolean isCountry = country != null && country.length( ) > 0; boolean isVariant = variant != null && variant.length( ) > 0; if ( isLanguage && isCountry && isVariant ) { locale = new java.util.Locale(language, country, variant); } else if ( isLanguage && isCountry ) { locale = new java.util.Locale(language, country); } else if ( isLanguage ) { locale = new java.util.Locale(language, ""); } // reset the Struts locale session.setAttribute(Globals.LOCALE_KEY, locale); // reset the JSTL locale Config.set(session, Config.FMT_LOCALE, locale); if (null==page || "".equals(page)) return mapping.findForward(SUCCESS); else return new ActionForward(page); } }
Discussion
The ChangeLocaleAction is based on the Struts 1.2 LocaleAction. This action provides the same capabilities at the Struts LocaleAction, and it supports a locale variant. Variants aren't defined by an ISO standard like language and country codes but are supported by Java and can give you additional means of organizing your localized messages. Even more importantly, the ChangeLocaleAction updates the Locale used by JSTL as well as the Struts Locale:
// reset the Struts locale session.setAttribute(Globals.LOCALE_KEY, locale); // reset the JSTL locale Config.set(session, Config.FMT_LOCALE, locale);
The Struts LocaleAction doesn't do this because it would be dependent on the JSTL APIs. But if you're using Struts and JSTL's internationalization capabilities, you will want to update the Locale for both.
Similar to the LocaleAction, the ChangeLocaleAction reads the language, country, and variant codes from properties on an ActionForm. It creates a Locale using these values and stores this Locale in the session. The action returns an ActionForward using the path specified by the page property or found under the name "success."
To use the ChangeLocaleAction, you'll need to create an ActionForm containing the required properties. You can extend ActionForm, or you can use a DynaActionForm specified in your struts-config.xml file:
<form-bean name="LocaleForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="language" type="java.lang.String"/> <form-property name="country" type="java.lang.String"/> <form-property name="variant" type="java.lang.String"/> <form-property name="page" type="java.lang.String"/> </form-bean>
Then declare an action in the struts-config.xml file that uses this ActionForm and the ChangeLocaleAction:
<action path="/ChangeLocale" name="LocaleForm" scope="request" type="com.oreilly.strutsckbk.ch12.ChangeLocaleAction"/>
Here's a set of links using this action that allow the user to change languages between English, Russian, and U.S. English (Southeastern variant):
<html:link action="/ChangeLocale?language=en"> English </html:link><br /> <html:link action="/ChangeLocale?language=ru"> Russian </html:link><br /> <html:link action="/ChangeLocale? language=en&country=US&variant=SE"> Southeastern U.S. English </html:link><br />
Here's an
HTML form that allows a user to change the current language. Once changed the request will be forwarded to the /Welcome.do page.
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<html:html lang="true"> <head> <title>Change language</title> </head> <body> <html:form action="/ChangeLocale"> <html:select property="language"> <html:option value="en">English</html:option> <html:option value="fr">French</html:option> <html:option value="ru">Russian</html:option> </html:select> <html:hidden property="page" value="/Welcome.do"/> <html:submit/> </html:form> </body> </html:html>
If you're using Struts 1.2 and you're not using JSTL or locale variants, then it doesn't matter if you use the Struts LocaleAction or my ChangeLocaleAction. However, if you aren't using Struts 1.2 or you're using JSTL, then my ChangeLocaleAction will work best.
See Also
The API for the LocaleAction can be found at http://struts.apache.org/api/org/apache/struts/actions/LocaleAction.html.
If you're using Struts and JSTL together, you can share the resource bundles using the Solution in Recipe 12.2.
|
No comments:
Post a Comment