Categories
Java

MessageSource in Spring 3

The MessageSource interface supports the parameterization and internationalization of messages and provides 2 implementations:

  1. ResourceBundleMessageSource, built on top of the standard ResourceBundle
  2. ReloadableResourceBundleMessageSource, being able to reload message definitions without restarting the VM

The following is an example of ResourceBundleMessageSource to get messages in the specified language in Spring 3.

  1. create a java project in your preferred IDE (eclipse, netbeans, etc.)
  2. configure the project with Maven with file pom.xml
    <project
    	xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>Autowired</groupId>
    	<artifactId>Autowired</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<build>
    		<sourceDirectory>src</sourceDirectory>
    		<plugins>
    			<plugin>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>2.3.2</version>
    				<configuration>
    					<source />
    					<target />
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context</artifactId>
    			<version>3.1.2.RELEASE</version>
    		</dependency>
    
    		<!-- log4j -->
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.17</version>
    		</dependency>
    	</dependencies>
    
    </project>
    

    otherwise you can use the following library:

    • spring-context-3.1.2.RELEASE.jar
    • spring-aop-3.1.2.RELEASE.jar
    • aopalliance-1.0.jar
    • spring-beans-3.1.2.RELEASE.jar
    • spring-core-3.1.2.RELEASE.jar
    • commons-logging-1.1.1.jar
    • spring-expression-3.1.2.RELEASE.jar
    • spring-asm-3.1.2.RELEASE.jar
    • log4j-1.2.17.jar
  3. create a folder “resources” and add to the classpath
  4. create the file resources/app-context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans
    	xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"
    	default-lazy-init="true">
    
    	<context:component-scan base-package="eu.lucazanini" />
    
    	<bean
    		id="messageSource"
    		class="org.springframework.context.support.ResourceBundleMessageSource">
    		<property name="basenames">
    			<list>
    				<value>messages</value>
    			</list>
    		</property>
    	</bean>
    
    </beans>
    

    as explained below, the string “messages” is equal to the first part of the name of the files .properties, and you can specify a path from the classpath such as “locale/messages” for example

  5. create the file resources/log4j.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd">
    
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> 
        <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" />
    <!--
    ConversionPattern format specification
    %d      inserts the date; you can specify the format (%d{yyyy-MM-dd HH:mm:ss,SSS})
    %-5p    inserts the priority log level, 5 characters, left justified
    %c{1}   inserts the name of the class
    %L      inserts the line number
    %m      inserts the user message
    %n      inserts the separator (for example, a new line)
    -->
            </layout>
        </appender>
    
        <appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">
            <param name="append" value="false" />
            <param name="Threshold" value="DEBUG" />
            <param name="File" value="logs/app.log"/>
            <param name="MaxFileSize" value="512KB" />
            <param name="MaxBackupIndex" value="10" />
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" />
            </layout>
        </appender>
    
    <!--sets the priority log level for org.springframework-->
        <logger name="org.springframework">
            <level value="info"/>
        </logger>
    
    <!--sets the priority log level for eu.lucazanini-->
        <logger name= "eu.lucazanini">
            <level value="debug"/>
        </logger>
    
    <!--sets the default priority log level-->
        <root>
            <priority value="debug"></priority>
            <appender-ref ref="stdout"/>
            <appender-ref ref="fileAppender"/>
        </root>
    </log4j:configuration>
    
  6. create the 3 file .properties to manage the content of messages in english language (Great Britain), english language (United States) and italian language
    • resources/messages_en_GB.properties
      msg1=in british english
      msg2=My name is {0} {1}
      
    • resources/messages_en_US.properties
      msg1=in american english
      msg2=My name is {0} {1}
      
    • resources/messages_it.properties
      msg1=in italiano
      msg2=Il mio nome è {0} {1}
      

      the names of the files .properties are important and must comply with one of the following syntaxes:

      • [base name]_[language]
      • [base name]_[language]_[country]
      • [base name]_[language]_[country]_[variant]

      where

      • [base name] is that specified in resources/app-context.xml (“messages” in this example)
      • [language] is the language code (“en”, “it”, etc.)
      • [country] is the country code (“GB”,”US”, “IT”, the same language changes depending on the country, the english spoken in the United States is different from that spoken in England)
      • [variant] is a code for the variant of the language (not used in this example)
  7. create the eu/lucazanini/messagesource/Main.java
    package eu.lucazanini.messagesource;
    
    import java.util.Locale;
    import org.apache.log4j.Logger;
    import org.springframework.context.support.GenericXmlApplicationContext;
    
    public class Main {
        private static Logger log = Logger.getLogger(Main.class);
    
        public static void main(String[] args) {
    
    	GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
    	ctx.load("classpath:app-context.xml");
    	ctx.refresh();
    
    	Locale britishEnglish = new Locale("en", "GB");
    	System.out.println(ctx.getMessage("msg1", null, britishEnglish));
    	System.out.println(ctx.getMessage("msg2", new Object[] { "Luca",
    		"Zanini" }, britishEnglish));
    
    	System.out.println("\n");
    
    	Locale americanEnglish = new Locale("en", "US");
    	System.out.println(ctx.getMessage("msg1", null, americanEnglish));
    	System.out.println(ctx.getMessage("msg2", new Object[] { "Luca",
    		"Zanini" }, americanEnglish));
    
    	System.out.println("\n");
    
    	Locale italian = new Locale("it");
    	System.out.println(ctx.getMessage("msg1", null, italian));
    	System.out.println(ctx.getMessage("msg2", new Object[] { "Luca",
    		"Zanini" }, italian));
    
        }
    }
    

    I use the method String getMessage(String code, Object[] args, Locale locale) where

    • code to look up in the files .properties
    • args is an object array to pass as arguments and they replace {0} {1} {2} … in the files .properties, use “null” if you don’t have arguments
    • Locale is an object of Locale class and has 3 constructors:
      • Locale(String language)
      • Locale(String language, String country)
      • Locale(String language, String country, String variant)

    you can also use the method String getMessage(String code, Object[] args, String defaultMessage, Locale locale) where you can specify a default value for the message

  8. launch the application
    in british english
    My name is Luca Zanini
    
    
    in american english
    My name is Luca Zanini
    
    
    in italiano
    Il mio nome è Luca Zanini
    

References:
MessageSource
Locale

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.