ZetCode

Spring MessageSource

last modified October 18, 2023

Spring MessageSource tutorial shows how to translate messages using MessageSource in a Spring application.

Spring is a popular Java application framework for creating enterprise applications.

Spring MessageSource

MessageSource is used for resolving messages, with support for the parameterization and internationalization of the messages. Spring contains two built-in MessageSource implementations: ResourceBundleMessageSource and ReloadableResourceBundleMessageSource. The latter is able to reload message definitions without restarting the Virtual Machine.

Spring MessageSource example

The following application contains messages in English and German language. It uses the built-in ResourceBundleMessageSource.

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           │   Application.java
│   │           └───config
│   │                   AppConfig.java
│   └───resources
│       │   logback.xml
│       └───messages
│               label.properties
│               label_de.properties
└───test
    └───java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.zetcode</groupId>
    <artifactId>messagesource</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-version>5.3.23</spring-version>

    </properties>

    <dependencies>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <mainClass>com.zetcode.Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

In the pom.xml file, we have basic Spring dependencies spring-core, spring-context, and logging logback-classic dependency.

The exec-maven-plugin is used for executing Spring application from the Maven on the command line.

resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <logger name="org.springframework" level="ERROR"/>
    <logger name="com.zetcode" level="INFO"/>

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
            </Pattern>
        </encoder>
    </appender>

    <root>
        <level value="INFO" />
        <appender-ref ref="consoleAppender" />
    </root>
</configuration>

The logback.xml is a configuration file for the Logback logging library.

resources/messages/labels.properties
l1=Earth
l2=Hello {0}, how are you?

These are English messages. The second property receives a parameter.

resources/messages/labels_de.properties
l1=Erde
l2=Hallo {0}, wie geht's?

These are German messages.

com/zetcode/config/AppConfig.java
package com.zetcode.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
public class AppConfig {

    @Bean
    public ResourceBundleMessageSource messageSource() {

        var source = new ResourceBundleMessageSource();
        source.setBasenames("messages/label");
        source.setUseCodeAsDefaultMessage(true);

        return source;
    }
}

The AppConfig configures the ResourceBundleMessageSource. The setBasenames tells where to look for message definitions.

com/zetcode/Application.java
package com.zetcode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.Locale;

@ComponentScan(basePackages = "com.zetcode")
public class Application {

    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    @Autowired
    private MessageSource messageSource;

    public static void main(String[] args) {

        var ctx = new AnnotationConfigApplicationContext(Application.class);

        var app = ctx.getBean(Application.class);
        app.run();

        ctx.close();
    }

    public void run() {

        logger.info("Translated messages:");
        logger.info("{}", messageSource.getMessage("l1",
                null, Locale.GERMAN));
        logger.info("{}", messageSource.getMessage("l1",
                null, Locale.ENGLISH));

        logger.info("Translated parameterized messages:");
        logger.info("{}", messageSource.getMessage("l2",
                new Object[] {"Paul Smith"}, Locale.GERMAN));
        logger.info("{}", messageSource.getMessage("l2",
                new Object[] {"Paul Smith"}, Locale.ENGLISH));
    }
}

The application prints plain messages and parameterized messages to the console.

@Autowired
private MessageSource messageSource;

We inject the MessageSource, which was generated in AppConfig.

logger.info("{}", messageSource.getMessage("l1",
    null, Locale.GERMAN));

The getMessage takes the property name as the first parameter. The second parameter is null, because the messsage takes no parameters. The third parameter is the locale.

logger.info("{}", messageSource.getMessage("l2",
    new Object[] {"Paul Smith"}, Locale.GERMAN));

Here we also provide a parameter to the message.

$ mvn -q exec:java
22:08:27.984 INFO  com.zetcode.Application - Translated messages:
22:08:27.984 INFO  com.zetcode.Application - Erde
22:08:27.984 INFO  com.zetcode.Application - Earth
22:08:27.984 INFO  com.zetcode.Application - Translated parameterized messages:
22:08:27.984 INFO  com.zetcode.Application - Hallo Paul Smith, wie gehts?
22:08:27.984 INFO  com.zetcode.Application - Hello Paul Smith, how are you?

We run the application.

In this article we have shown how to use ResourceBundleMessageSource in a Spring application.

Author

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Spring tutorials.