Pages

Thursday, July 19, 2012

Spring 3 Internationalization and Localization - Not 'Hello World', But 'Practical'

I wanted to add internationalization and localization feature provided by spring 3 to one of my current project recently. I went through the spring documentation and then searched on internet to find some resources. 
But I could not find a resource which was able to satisfy my client requirement. Most of the tutorials are like hello world application which gives basic understanding. Even spring documentation does not give in detailed explanation on integrating this feature to our own project. Expert developers can pick the stuff from spring documentation. But for others, have to put extra effort to make things up and running. With this tutorial, I am going to explain very practical scenario that most of the clients are expecting.

The requirement

I am using spring security with my application. User should be able to select the language from the log-in page which was specified as 'login-page' of spring security XML file. I have provided links as "English","Chinese","German" and "Spanish" on top right corner of my log-in page to select the language. User can select the language and log in to the system by providing username and password. Then the whole application should be from the selected language. And also when selecting the language from the log-in page, the contents of the log-in page should also be changed.

Spring configurations

As the first step, I had to configure LocaleChangeInterceptor interceptor with in the dispatcher-servlet.xml file. This XML file name will change according to the name given to DispatcherServlet in web.xml file. I have given 'dispatcher' as the name for DispatcherServlet. So I should create 'dispatcher-servlet.xml' file under /WEB-INF folder. My application is running on Tomcat 7.

I could not make it working by following the way of declaring this interceptor as in the spring documentation. The request for changing the locale before log in(ie: from the login page) was not intercepted by the locale change interceptor. Therefore, I had to declare it as fallows.

<mvc:interceptors>
  <mvc:interceptor>
     <mvc:mapping path="/doChangeLocale*"/>
         <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" >
             <property name="paramName" value="locale" />
         </bean>
    </mvc:interceptor>
</mvc:interceptors>

The 'LocaleChangeInterceptor' will intercept the request asking for locale change and the corresponding locale code will be stored in the session with the help of 'SessionLocaleResolver'.

Next we will look at how to declare the 'SessionLocaleResolver' in the 'dispatcher-servlet.xml' file.

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
     <property name="defaultLocale" value="en" />
</bean>

The SessionLocaleResolver will store the locale in the current session and resolve it for every subsequent user requests for the current session.

Next, we have to declare the message resource bean.

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="useCodeAsDefaultMessage" value="true" />
    <property name="basenames">
         <list>
            <value>classpath:messages</value>
         </list>
    </property>
    <property name="cacheSeconds" value="0" />
    <property name="defaultEncoding" value="UTF-8"></property>
</bean>

My application should support for 4 languages. So I added 4 property files into the 'resources' folder (ultimately all those property files should be in 'classes' folder) as follows.

messages_de.properties - German
messages_en.properties - English
messages_zh.properties - Chinese
messages_es.properties - Spanish

Note that, all the file names should start with the text which you specified as 'basenames' property of message resource bean.

The spring 3 security configurations were very important in this implementation. Keep in mind that, when you click any locale change link from the log-in page, you are not authenticated yet. But still that request should be intercepted by 'LocaleChangeInterceptor'. Otherwise, the language will not be changed as expected. There fore, any anonymous user should be allowed to make locale change request and that request should go through the 'LocaleChangeInterceptor'. 

Carefully look into my spring security configuration.
<http auto-config="false">
    <form-login login-page="/login.jsp"  authentication-failure-url="/login.jsp?login_error=true" default-target-url="/mainMenu.htm"/>
    <logout logout-success-url="/login.jsp"/>
    <intercept-url pattern="/doChangeLocale**" access="ROLE_ANONYMOUS,ROLE_ADMIN,ROLE_USER"/>
    <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER"  />
</http>

The login.jsp file is where user can log into the system by providing username and password and also that page has the corresponding links to change the locale. When user makes any request to a protected resource without authenticating, the user will be redirected to the login.jsp page. The above configuration says all the requests that are coming to the application should be from a authenticated user and also the user should be authorized except for the '/doChangeLocale**' request.

The intercept URL '/doChangeLocale**' is very important. Without that, the requests for changing locales are not intercepted by the locale change interceptor and finally locale will not change.

The followings are the locale change links that are placed in the login.jsp file.

<a href="<%=request.getContextPath()%>/doChangeLocale?locale=en">English</a>
<a href="<%=request.getContextPath()%>/doChangeLocale?locale=de">German</a>
<a href="<%=request.getContextPath()%>/doChangeLocale?locale=es">Spanish</a>
<a href="<%=request.getContextPath()%>/doChangeLocale?locale=zh">Chinese</a>


Hope this will be helpful for you.
You may also like:
Share

Widgets