Internationalization & Localization

Introduction

Internationalization (i18n) and localization (L10n) are means of supporting multi-languages for multiple countries or multiple regions within a country without changing code in the application.

The terms are frequently abbreviated to the numeronyms i18n (where 18 stands for the number of letters between the first i and last n in internationalization) and L10n respectively, due to the length of the words. The capital L in L10n helps to distinguish it from the lowercase i in i18n.

Create Message resource files

Create message resource files, one for each language in the root classpath. These files are suffixed by 2 character language code say "en" for English, "hi" for Hindi, and "sp" for Spanish.

1. messages_en.properties:

message.view=Message from View

message.ctl=Message from Controller

message.error=Error Message

2. messages_hi.properties:

message.view=Message from View \u0939\u093F\u0928\u094D\u0926\u0940

message.ctl=Message from Controller \u0939\u093F\u0928\u094D\u0926\u0940

message.error=Error Message \u0939\u093F\u0928\u094D\u0926\u0940

Code suffixed by \u (\u0939, \u093F, \u0928) are representing unicode values of Hindi fonts. "हिन्दी" string is converted into unicode values as "\u0939\u093F\u0928\u094D\u0926\u0940".

Configuration

We have created message resource properties for our application. We need to declare these files in the spring configuration file. We will use class org.springframework.context.support.ReloadableResourceBundleMessageSource to define the message resources.

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<property name="basename" value="classpath:messages" />

<property name="defaultEncoding" value="UTF-8" />

</bean>

Now we will provide a feature where the user will be able to select a language for the application. This is implemented using org.springframework.web.servlet.i18n.LocaleChangeInterceptor class. The LocaleChangeInterceptor class will intercept the request and make i18n, L10n changes.

<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">

<property name="paramName" value="lang" />

</bean>

User can pass request parameter ?lang=hi or ?lang=en to change the Locale and in turn his regional language.

The user's selected Locale is saved in cookies for future subsequent requests. Class org.springframework.web.servlet.i18n.CookieLocaleResolver is used to store the locale changes in cookies. Due to security reasons, in a few applications cookies are not supported in this case Locale is stored in the user's Session object using class org.springframework.web.servlet.i18n.SessionLocaleResolver.

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">

<property name="defaultLocale" value="en" />

</bean>

Make the following entries on *-servlet.xml.

<!-- Defines the message resources -->

<bean id="messageSource"

class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<property name="basename" value="classpath:messages" />

<property name="defaultEncoding" value="UTF-8" />

</bean>

<!-- Stores User locale in cookie for subsequent requests -->

<bean id="localeResolver"

class="org.springframework.web.servlet.i18n.CookieLocaleResolver">

<property name="defaultLocale" value="en"></property>

</bean>

<!--Intercepts request and make i18n, L10n changes. -->

<mvc:interceptors>

<bean id="localeChangeInterceptor"

class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">

<property name="paramName" value="lang" />

</bean>

</mvc:interceptors>

Change the View: The JSPs

Now as we have created two message resources files and configured it in Spring MVC, we will use these messages in the JSP files. Create a LocaleCtl.java that will forward to view LocaleView.jsp that will contain the following code:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>

<%@ page isELIgnored="false"%>

<HTML>

<BODY>

<a href="${pageContext.request.contextPath}"> Home </a>

<form>

Change Language:

<select name="lang">

<option value="en">English</option>

<option value="hi">Hindi</option>

</select> <input type="submit" value="Go">

</form>

<H1 style="color: green">${message }</H1>

<spring:message code="message.view" />

</BODY>

</HTML>

We have used <spring:message> tag to display the message from the resource bundle above JSP.

One thing that you must note here in LocaleView.jsp , we have defined <select name="lang"> list where you can select either Hindi or English language. The Form sets a request parameter ?lang=hi when user submits the Form. Note that spring identifies this request parameter by using LocaleChangeInterceptor interceptor and change the local accordingly. Also note that while configuring LocaleChangeInterceptor in a spring-servlet.xml file, we have specified property “paramName” with value “lang”.

<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">

<property name="paramName" value="lang" />

</bean>

Thus the Spring framework will look for a parameter called “lang” from request.

Get Locale Messages in the Controller

You may also need Locale messages in a Controller when you want to send some notification messages to View from Controller in case of Business Validation fail or Success operation.

You may do it by Auto wring MessageSource object and pass the Locale parameter in the controller method. Here is the example of LocaleCtl.java that gets a message for resource and set into the Model object.

@Autowired

private MessageSource messageSource;

@RequestMapping(method = RequestMethod.GET)

public String display(Model model, Locale locale) {

String msg = messageSource.getMessage("message.ctl", null, locale);

model.addAttribute("message", msg);

return "LocaleView";

}

Input validation error locale messages

There is a very simple way to get error messages of a validated form-bean in localized language. Here we will have an example form-bean LocaleForm that will apply input validations on an attribute and in case of validation fail error messages will be localized from resource bundle files.

Lets start applying localization on input validation error messages:

1. Validation Form

Here is an example of LocaleForm that is applying input validation @NotEmpty and @Size at "name" attribute.

public class LocaleForm {

@NotEmpty

@Size(min=5, max=20)

private String name =null;

2. Controller

The controller validate the form and stores form-bean in the Model by name "localeForm".

public class LocaleCtl{

@RequestMapping(method = RequestMethod.GET)

public String display(@ModelAttribute("localeForm") @Valid LocaleForm form,BindingResult bindingResult, Model model, Locale locale) {

..

3. Entry in Resource files

Now time to make entries for locale messages in resource files messages_en.properties and messages_hi.properties. Keys of validation error messages must follow a name pattern (Validation.formNameInModel.attributeName ) that consists of (1) Input Validation Type (2) Name of form-bean object in the Model (3) Attribute name on which validation is applied.

Here keys are formatted for @Size and @NonEmpty validation on "name" attribute.

NotEmpty.localeForm.name=Name is required.

Size.localeForm.name=Name must be between 5 to 20 characters.

4. View JSP

Here is JSP LocaleView.jsp that does not need any special entry for i18n / L10n messages.

Name : <form:input path="name" /><form:errors path="name" cssClass="error" />

That's it, Now go ahead and enjoy i18n/L10n messages in your application.

FAQ

Q: How do you configure i18n?

Q: What is the naming convention of messages.properties

A: Message file is suffixed by language code.

Q: What parameter will you pass in the request object to change the language?

A: lang parameter.

Q: How do configure 'lang' parameter?

Q: How many .properties files will you create?

A: It depends upon a number of language support. Each language .properties file is suffix by language 2 character code.

Q: What are the location of the .properties file?

Q: Root classpath

Q: How do you configure in locale messages Form bean?

A: Bypassing the message key to the validation annotation.

Q: How do you get language-specific messages in a method of Controller?

A: Using MessageResource object.

Q: What is MessageResource class?

Q: How do you get language-specific messages in a JSP?

A: Using <s:message> tag.