JavaBlog.fr / Java.lu DEVELOPMENT,Java,Spring Spring: Internationalization with message source

Spring: Internationalization with message source

In this mini-post, I would share you a solution to “internationalize” your application due to Spring message source. This component allow the additional capabilities to the ApplicationContext interface which extends an interface called MessageSource, and therefore provides internationalization (i18n) functionalities.

Spring currently provides two MessageSource implementations: ResourceBundleMessageSource and StaticMessageSource, however, this latter implementation StaticMessageSource is rarely used but provides programmatic ways to add messages to the source. So, we will use the ReloadableResourceBundleMessageSource implementation.

In this post, I will expose only the configuration needed to implement message Resource. Then, I try to explain the use cases of MessageSource in Java class, JSP, Spring MVC validator or viewer. My examples are recovered from a project base on Spring MVC.

How to implement message Resource, follow the steps below:

  • Step 1. Add the Message Source bean definition to the Spring Context Xml file
    <!-- ################### SPRING APPLICATION MESSAGES PROPERTIES ################### -->
    <!-- Files concerned: -->
    <!-- /WEB-INF/ApplicationMessageSource_en_US.properties -->
    <!-- /WEB-INF/ApplicationMessageSource_fr_FR.properties -->
    <!-- /WEB-INF/ApplicationMessageSource_zh_CN.properties -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    	<property name="defaultEncoding" value="UTF-8"/>
    	<property name="basenames">
    		<list>
    			<value>/WEB-INF/ApplicationMessageSource</value>
    		</list>
    	</property>
    </bean>
    
  • Step 2. Add the beans definitions concerning the SPRING Support Internationalization.
    To make Spring MVC application supports the internationalization, we need register 2beans :
    SessionLocaleResolver
    Register a “SessionLocaleResolver” bean, named it exactly the same characters “localeResolver“.
    It resolves the locales by getting the predefined attribute from user’s session.
    Note: If you do not register any “localeResolver”, the default AcceptHeaderLocaleResolver will be used,
    which resolves the locale by checking the accept-language header in the HTTP request.

    <!-- ################### SPRING Support Internationalization ################### -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    	<property name="defaultLocale" value="en_US" />
    </bean>
    	
    <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    	<property name="paramName" value="language" />
    </bean>
    

    LocaleChangeInterceptor
    Register a “LocaleChangeInterceptor” interceptor and reference it to any handler mapping that need
    to supports the multiple languages. The “paramName” is the parameter value that’s used to set the locale.

    In this case,
    1.welcome.htm?language=en – Get the message from English properties file.
    2.welcome.htm?language=zh_CN – Get the message from Chinese properties file.

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
    	<property name="interceptors">
    	   <list>
    		<ref bean="localeChangeInterceptor" />
    	   </list>
    	</property>
    </bean>
    
  • Step 3. Create 3 properties files to store English, French and Chinese messages:
    ApplicationMessageSource_en_US.properties

    user.list.form.title=Users' List
    book.list.form.title=Books' List of User
    user.add.form.title=Add a new user
    book.add.form.title=Add a new book
    field.required={0} is required!
    field.username=User Name
    

    ApplicationMessageSource_fr_FR.properties

    user.list.form.title=Liste des utilisateurs
    book.list.form.title=Liste des livres de l'utilisateur
    user.add.form.title=Ajouter un nouveau utilisateur
    book.add.form.title=Ajouter un nouveau livre
    field.required={0} est obligatoire!
    field.username=Nom Utilisateur
    

    ApplicationMessageSource_zh_CN.properties

    user.list.form.title=Users' List \u5feb\u4e50\u5b66\u4e60
    book.list.form.title=Books' List of User \u5feb\u4e50\u5b66\u4e60
    user.add.form.title=Add a new user \u5feb\u4e50\u5b66\u4e60
    book.add.form.title=Add a new book \u5feb\u4e50\u5b66\u4e60
    field.required={0} is required \u5feb\u4e50\u5b66\u4e60!
    field.username=User Name \u5feb\u4e50\u5b66\u4e60
    

How to use this message Resource in Java class, JSP, Spring MVC validator or viewer:

  • In a simple java class, the messages are dipslayed from properties file:
    public class MyExample {
    	private MessageSource messages;
    	public void setMessages(MessageSource messages) {
    		this.messages = messages;
    	}
    
    	public void execute() {
    		String message = this.messages.getMessage("field.required", new Object [] {"UserName"}, "Required", null);
    		System.out.println(message);
    	}
    }
    
  • In a Web based application, we need a JSP page containing three hyperlinks which allow the change of the locale manually:
    Language : <a href="?language=en_US">English</a>&nbsp;|&nbsp;<a href="?language=fr_FR">Français</a>&nbsp;|&nbsp;<a href="?language=zh_CN">快乐学习</a>
    

    … the ${pageContext.response.locale} can be used to display the current user’s locale like:

    Current user’s locale: ${pageContext.response.locale}<br/>
    

    to display the message from the corresponds properties file by checking the current user’s locale.

    And the messages are displayed from the corresponds properties file by checking the current user’s locale and using automatically the spring:message tag:

    <u><spring:message code="user.list.form.title"/></u><br/>
    <a href="../user/create.htm"><img src="../img/adduser.png" border="0"/> <spring:message code="user.add.form.title"/></a>
    <a href="../user/pdflist.htm"><img src="../img/pdf.gif" border="0"/> <spring:message code="label.get.pdf.users.list"/></a>
    
  • The use of MessageSource in the Spring MVC validator or viewer is similar to the simple Java class:
    Validator
    It’s an example of a validator that validates the data received from cliebt. Its declaration in configuration file could be like:

    <!-- SPRING MVC Data Validation -->
    <bean id="bookValidator" class="com.ho.persistence.hibernate.spring.ex1.web.validator.BookValidator">
    	<property name="messageSource" ref="messageSource" /><!-- Injection of MessageSource -->
    </bean>
    

    …its use in Java code:

    /**
     * Class for validation of input validation for the new user form. 
     * @author huseyin
     *
     */
    public class BookValidator implements Validator {
    
    	// Spring Message Source
    	private MessageSource messageSource;
    
    	public void setMessageSource(MessageSource messageSource) {
    		this.messageSource = messageSource;
    	}
    
    
    	public void validate(Object obj, Errors errors) {
    		Book book = (Book) obj;
     
    		/**
    		 * To add an error these parameters are needed:
    		 * - the concerned field name
    		 * - error message key 
    		 * - default message if no message is not found for the key
    		 */
    		String nameField = this.messageSource.getMessage("field.name", new Object [] {}, null);
    		String aboutbookField = this.messageSource.getMessage("field.about.book", new Object [] {}, null);
    		
    		// Validateur permet de sp�cifier des erreurs sur chaque propri�t� du formulaire
    		if ( ! errors.hasFieldErrors("name")) {
    			ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "field.required", new Object [] {nameField}, "Required field");
    
    		// validateur permet de sp�cifier des erreurs � un niveau global
    		if( errors.hasErrors() ) {
    			errors.reject("register.error");
    		}
    	}
    ...
    }
    

    Viewer
    It’s an example of a viewer that generates a PDF. Its declaration in configuration file could be like:

    <!-- Book List View PDF -->	
    <bean id="bookListPDFView" class="com.ho.persistence.hibernate.spring.ex1.web.view.BookListPdfReportView">
    	<property name="messageSource" ref="messageSource"/>  <!-- Injection of MessageSource -->
    </bean>
    

    …its use in Java code:

    public class BookListPdfReportView extends AbstractPdfView {
    
    	// Spring Message Source
    	private MessageSource messageSource;
    
    	public void setMessageSource(MessageSource messageSource) {
    		this.messageSource = messageSource;
    	}
    
    
    @Override
    	protected void buildPdfDocument(Map model, Document document,
    			PdfWriter writer, HttpServletRequest request,
    			HttpServletResponse response) throws Exception {
    
    		List<Book> bookList = (List<Book>) model.get("bookList");
    		
    		// G�n�ration du PDF
    		Table table = new Table(2);
    		// Noms des colonnes renseign�s dans "ApplicationResources.properties"
    		table.addCell(this.messageSource.getMessage("column.header.name", null, null));
    		table.addCell(this.messageSource.getMessage("column.header.about.book", null, null));
    	...
    	}
    }
    
  • Warning: The Spring MVC controller which “extends MultiActionController” doesn’t work with “ControllerClassNameHandlerMapping”.

To conclude, this post, I would add comments about the the UTF-8 encoding:

  • First, remember put the “<%@ page contentType=”text/html;charset=UTF-8″ %>” on top of the page, else the page may not able to display the UTF-8 (Chinese) characters properly.
  • Use the SPRING UTF-8 servlet filter CharacterEncodingFilter defined in the le web.xml in order to force the encoding.Be careful to position the filter in the first position in the list of different filters!
    <filter>
    	<filter-name>encodingFilter</filter-name>
    	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    	<init-param>
    		<param-name>encoding</param-name>
    		<param-value>UTF-8</param-value>
    	</init-param>
    	<init-param>
    		<param-name>forceEncoding</param-name>
    		<param-value>true</param-value>
    	</init-param>
    </filter>
    
  • Convert your *.properties file with ‘non-Latin 1′ or ‘non-Unicode’ characters to ‘Unicode-encoded’ characters via “native2ascii” utility supported by the JDK. It is usable in command line like:
    – “C:\Program Files (x86)\Java\jdk1.6.0_26\bin\native2ascii.exe” -encoding utf8 C:\MyFiles\Development\Java\dev\SpringHibernateIntegration1\WebContent\WEB-INF\ApplicationMessageSource_fr_FR.properties_no_unicode C:\MyFiles\Development\Java\dev\SpringHibernateIntegration1\WebContent\WEB-INF\ApplicationMessageSource_fr_FR.properties

    – “C:\Program Files (x86)\Java\jdk1.6.0_26\bin\native2ascii.exe” -encoding utf8 C:\MyFiles\Development\Java\dev\SpringHibernateIntegration1\WebContent\WEB-INF\ApplicationMessageSource_zh_CN.properties_no_unicode C:\MyFiles\Development\Java\dev\SpringHibernateIntegration1\WebContent\WEB-INF\ApplicationMessageSource_zh_CN.properties

    – For example:

Best regards,

7 thoughts on “Spring: Internationalization with message source”

  1. With Spring3 you can just implement the MessageSourceAware interface, and skip the injection of messagesource in the context

  2. Thanks for the article. I had trouble making chinese localization work.

    One piece of advice: You don’t have to convert your property files.
    Property files come in two flavors: .properties and as xml file. Xml files have an encoding, so you can just use plain UTF-8. This is an example:

    查看消息

    1. Hi, I don’t know this ‘famous person’, it’s simply a copy/paste action from internet (chinese text) 🙂

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post