Spring 3 – Internationalization (i18n) Support Example

Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes. The term is frequently abbreviated as i18n (where 18 stands for the number of letters between the first i and last n in internationalization). Above definition essentially means making changes in your application such that it should be usable in multiple locales (or languages in simple words).

If your application is developed using Spring 3, then in this post, you will learn about making your application i18n supported.

Please note that default locale of application is always based on locale set on server machine. So, if you have set Spanish locale on server machine, all your application users will get the Spanish locale specific look and feel.

Classes used for internationalization (i18n) support

Spring 3 provides following classes for i18n support. Lets see them first:

LocaleChangeInterceptor : This interceptor allows for changing the current locale on every request, via a configurable request parameter. Usually this parameter is lang. So, anytime a user send a request with request parameter “lang=en”, his locale automatically be set as English.

If no parameter has been defined then default parameter name is “locale”.

	<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
		<property name="paramName" value="lang" />
	</bean>

CookieLocaleResolver: It’s a LocaleResolver implementation that uses a cookie sent back to the user in case of a custom setting. Remember that sending locale or lang parameter in request is actually a custom setting. The cookie sent to user is used in further communication as user will not have to set the locale in every request. If this cookie has been generated, each request will have this overridden locale in request.

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

DefaultAnnotationHandlerMapping: Implementation of the HandlerMapping interface that maps handlers based on HTTP paths expressed through the RequestMapping annotation at the type or method level. As we are using @RequestMapping based request mapping, we have to use it. We are using it basically for adding the “localeChangeInterceptor” in interceptors list. So each time, a http request come in application, our LocaleChangeInterceptor will be invoked and check for any locale change request as well.

	<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
		<property name="interceptors">
			<ref bean="localeChangeInterceptor" />
		</property>
	</bean>

Update messages in properties file

Another important thing is to make locale specific files to contain label and messages different for each locale e.g. messages_en.properties (english) and messages_es.properties (spanish).

I have used some english to spanish converter for message conversion. So if its spanish equivalent is incorrect, then please bear with me and concentrate on actual concept.

messages_en.properties

message.unauth=Unauthorized Access !!
message.fakeLogin=Your fake login attempt was busted, dare again !!
message.goback=Go back to login page
message.accessdenied=Access denied!!
message.demo=Spring 3 method security Demo
message.username=Username:
message.password=Password:

messages_es.properties

message.unauth=Unauthorized Access !!
message.fakeLogin=Your fake login attempt was busted, dare again !!
message.goback=Go back to login page
message.accessdenied=Access denied!!
message.demo=Spring 3 method security Demo
message.username=Username:
message.password=Password:

Update the spring servlet file

Now make sure to have all these for bean definitions in your spring servlet file. I am making changes in employee-servlet.xml file in this demo:

<bean id="messageSource"
	class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
	<property name="basename" value="classpath:messages" />
	<property name="defaultEncoding" value="UTF-8" />
</bean>

<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
	<property name="paramName" value="lang" />
</bean>
 
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
	<property name="defaultLocale" value="en"/>
</bean>

<bean id="handlerMapping"
	class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
	<property name="interceptors">
		<ref bean="localeChangeInterceptor" />
	</property>
</bean>

Test the application for i18n support

We are done with necessary changes. Let’s move on to testing it.

1) Login screen with en locale

login_screen_locale_en
Login screen “en” locale

2) Access denied screen with en locale

access_denied_screen_locale_en
Access denied screen “en” locale

3) Login screen with es locale

login_screen_locale_es
Login screen “es” locale

4) Access denied screen with es locale

access_denied_screen_locale_es
Access denied screen “es” locale

To download sourcecode of above tutorial

Sourcecode Download

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

4 thoughts on “Spring 3 – Internationalization (i18n) Support Example”

  1. Can we use internationalization only for a part of the project? like, I’m using HTML and Jsps both. But I want to use i18n for HTML but for Jsps, it should be English only. How can I achieve this?

    Reply
  2. Hi Lokesh,

    Using your Spring3 Internationalization example, I tried to connect two databases based on locations lang =en or es using AbstractRoutingDataSource.

    I’m getting following exception while bringing up the server , Could you please help in resolving this and why I am getting this error…
    Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outsi
    de of an actual web request, or processing a request outside of the originally receiving thread? If you are actually ope
    rating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/D
    ispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.ja
    va:123)
    at com.howtodoinjava.dao.MyRoutingDataSource.determineCurrentLookupKey(MyRoutingDataSource.java:14)

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.