The onslaught has started! The title icon (favicon, website icon, URL icon) on Java API pages (now hosted on oracle.com, but of course! good-old java.sun.com is gone) is not cool at all. I am trying to be polite here but can't just help.. it is plain ugly! Or do I only need another hot java cup? Any idea if Oracle is thinking of doing away with this 'iconic' symbol? I wish all the best to glassfish, MySQL... and of course, Java.
Tech Niche
Friday, July 30, 2010
Friday, July 27, 2007
Internationalization: Spring upon it
Supporting different locales using Spring Framework
Internationalization (also known as i18n where 18 is the number of letters between 'i' and 'n') is increasingly becoming a requirement today rather than being just a nice-to-have feature couple of years ago. It requires decoupling of data (date format, text, images, etc.) from source code (logic) so as to enable support for localized preferences. Though Java supports i18n, Spring framework makes it even easier to work with through a host of utility classes.
Let us see what it takes to display "Hello World!" in different languages using the same code base with Spring framework. The language preference is to be supplied in the URL as a parameter. In this article, I'll focus only on the parts that are concerned with our internationalization requirement. I will leave the deployment and testing details for the reader to take care of as I expect her to have some prior experience on web applications.
Let us see what it takes to display "Hello World!" in different languages using the same code base with Spring framework. The language preference is to be supplied in the URL as a parameter. In this article, I'll focus only on the parts that are concerned with our internationalization requirement. I will leave the deployment and testing details for the reader to take care of as I expect her to have some prior experience on web applications.
- The first step is to take out all the localized resources (text, image source names, date formats, etc.) from the application code and put it in resource bundles. A ResourceBundle contains key/value pairs. Let us make a properties file and put it in the classpath of our application. Let us place it in WEB-INF/classes folder. I have named my file messages.properties which has one entry:
- We need to maintain messages in other languages as different files with same name, only suffixing the name with the appropriate ISO language code. So, for instance, we'll need a file messages_ja.properties to hold the Japanese entries where in the key will have to be same as in messages.properties but the value will be Unicode(UTF-8) representation of the message in Japanese or any other language for that matter.
- Next, we need a ResourceBundle bean to represent our message resources. For this example, we'll use ResourceBundleMessageSource. You can also consider using ReloadableResourceBundleMessageSource for an alternative that is capable of refreshing the underlying bundle files. Let us see the entry in configuration metadata. We are using XML-based metadata for our purpose:
- Now, we need a mechanism to resolve when to use which resource bundle (messages file). As mentioned earlier, this resolution uses a parameter in the request URL. For our purpose, lets say, the parameter name is "userLang". Fortunately, Spring framework provides LocaleChangeInterceptor thats reads a parameter in the request and change the locale. We will need a LocaleResolver to resolve the messages based on the Locale set in by the interceptor. Here is the configuration entry that provides the whole mechanism:
- The basic work is done. We have all the right pieces in place and we are ready to start reading the messages based on the value of 'userLang' parameter provided in URL. Spring framework provides a RequestContext that helps getting the messages.
- As we are reading from a property file for the values in different languages supporting non-latin Unicode characters, it can be a little tricky. Once I had run into trouble while supporting the Japanese language and I resolved it the following way:
- It is a good practice to wrap the logic of getting the messages from RequestContext in a helper class instead of using RequestContext directly in a JSP.
- Make sure the target JSP supports UTF-8 charset. Put the following directive in your JSP.
message.Hello=Hello World!
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
<!-- Declare the Interceptor -->
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="siteLanguage"/>
</bean>
<!-- Declare the Resolver -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
<!-- Add the Interceptor to handler mapping -->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor"/>
</list>
</property>
<property name="mappings">
<value>/**/*.view=myController</value>
</property>
</bean>
String msg = new RequestContext(request).getMessage(key, default);
This gives us the localized messages based on the Locale set in LocaleResolver.
String finalMsg = new String(msg.getBytes("ISO-8859-1"),"UTF-8");
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="iso-8859-1" %>
Subscribe to:
Posts (Atom)