Spring MVC – Resolving Locale and Externalizing Locale-Sensitive Text Messages

A sample Spring MVC application to show how to

  • Retrieve the current Locale Resolver
  • Retrieve the current Locale
  • Set a new Locale
  • Display different version of the same message for different locales




I. Spring MVC Setup

Setting up a Spring MVC application is pretty straight forward, here are the web.xml file and application context xml file.

web.xml file

<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> </param-value> </context-param> <servlet> <servlet-name>springLocale</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet>         <servlet-mapping> <servlet-name>springLocale</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>     <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>



Application Context XML file

Since the purpose of this application is only to show how to use locale resolver, therefore we use a SimpleUrlHandlerMapping bean to map all requests to our custom controller.

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">                     <bean id="homeController" class="com.springLocale.controller.HomeController" /> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages" /> </bean>     <!--    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" --> <!--        />--> <!--    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" --> <!--        />     --> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> <property name="cookieName" value="locale" /> <property name="cookieMaxAge" value="30" /> <property name="defaultLocale" value="en" /> </bean>                        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/*">homeController</prop> </props> </property> <property name="order" value="0" /> </bean>           <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> <property name="order" value="0" /> </bean> </beans>



II. Custom Controller

This is our custom controller class. It simply extends from AbstractController class and overrides handleRequestInternal method.

Things we would like to do inside this controller are

  • Retrieve the current Locale Resolver
  • Retrieve the current Locale
  • Retrieve the new locale name and set the new Locale



There are several implementation of LocaleResolver interface such as AcceptHeaderLocaleResolver, SessionLocaleResolver, CookieLocaleResolver, etc. Among them, although we can use AcceptHeaderLocaleResolver to retrieve the current locale, we can not use it to set the new locale
as this operation is not allowed.

The complete controller code is shown below with comments explaining how to accomplish each task.

package com.springLocale.controller; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.propertyeditors.LocaleEditor; import org.springframework.web.bind.ServletRequestUtils; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import org.springframework.web.servlet.support.RequestContextUtils; public class HomeController extends AbstractController { protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { // used to hold attributes for ModelAndView Map map = new HashMap(); // get the locale resolver LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);                 if (localeResolver != null) { // get current locale Locale locale = localeResolver.resolveLocale(request); if (locale != null) { // if current locale is available // set the old locale name map.put("oldLocaleName", locale.toString()); } // get the locale resolver class name and set it in the model String localeResolverClassName = localeResolver.getClass().getName(); map.put("localeResolverClassName", localeResolverClassName); // get the new locale name from the request param, if possible String newLocaleName = ServletRequestUtils.getStringParameter(request, "locale"); if (newLocaleName != null) { LocaleEditor localeEditor = new LocaleEditor(); localeEditor.setAsText(newLocaleName); // set the new locale localeResolver.setLocale(request, response, (Locale) localeEditor.getValue()); } } // add a date attribute of type java.util.Date Date date = new Date(); map.put("date", date); // create ModelAndView object with view name "welcome" ModelAndView mav = new ModelAndView("welcome", map);                return mav; } }



III. Locale-Sensitive Text Messages

To display message for different locales, we have configured a ResourceBundleMessageSource bean with base name set to messages. The next thing to do is to create these message files for each locale we would like to support.

A simple message file would look like this

locale: en_US
(filename: messages.properties)
welcome.title=Welcome
welcome.message=Welcome to our system

locale: de
(filename: messages_de.properties)
welcome.title=Willkommen
welcome.message=Willkommen in unserem System




Later, we will show these messages on our JSP page.




IV. JSP View

We have configured a InternalResourceViewResolver to resolve view name to JSP page. In this sample
welcome.jsp page, we show the following information:

  • Messages for different locales
  • Current system time
  • Previous set locale name
  • Current locale name
  • Locale Resolver classname
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <html> <head> <title>Welcome</title> </head> <body> <h1><spring:message code="welcome.title" text="Welcome" /></h1> <strong><spring:message code="welcome.message" text="welcome jsp page" /></strong> <br /> <br /> Current time: ${date} <br /> <br /> Old Locale : ${oldLocaleName } <br /> <br /> Locale : ${pageContext.response.locale} <br /> <br /> Locale Resolver classname : ${localeResolverClassName } <br /> <br /> </body> </html>



Screen Shots

welcome page
Request url: http://127.0.0.1:8080/SpringLocale/home.do?locale=de



spring-locale-screenshot




Cookies
A cookie named “locale” has been set before with the value of “en_US” and after we sent a new request with param “locale=de”, you can see the locale cookie sent back from the server is set to “de”.



spring-locale-cookie




V. Download

The Eclipse project file for this application can be downloaded from here.




Advertisements
Spring MVC – Resolving Locale and Externalizing Locale-Sensitive Text Messages

6 thoughts on “Spring MVC – Resolving Locale and Externalizing Locale-Sensitive Text Messages

  1. irnbru says:

    Very useful! I would like more explanation about how you found about:

    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
    Locale locale = localeResolver.resolveLocale(request);

    what about ${pageContext.response.locale}
    I thought we were talking about the request to know about the locale and not the response?

    Thanks
    IRNBRU

    is it the only way?

  2. Love VN says:

    Hi,

    Very useful entry. I have similar though as @irnbru.
    Could you give show me how to force Spring take the locale from Response, (which is set by Struts2) and display message as using that locale.

  3. cchweblog says:

    @Love VN & @irnbru
    I am not sure I know the answer to your question, but will come back if I figure it out.

  4. The code is working. But I don’t want to have the code in every controller. I movde the code into a filter. But in the Filter the localeResolver is always null. The filter is managed by spring.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s