Boot

Internationalization in Spring Boot

Welcome, in this tutorial, we will see how to implement internationalization in a spring boot application where a single application can support multiple languages like English, French, German, etc.

1. Introduction

Before going further in this tutorial, we will look at the common terminology such as introduction to Spring Boot.

1.1 Spring Boot

  • Spring boot is a module that provides rapid application development feature to the spring framework including auto-configuration, standalone-code, and production-ready code
  • It creates applications that are packaged as jar and are directly started using embedded servlet container (such as Tomcat, Jetty or, Undertow). Thus, no need to deploy the war files
  • It simplifies the maven configuration by providing the starter template and helps to resolve the dependency conflicts. It automatically identifies the required dependencies and imports them into the application
  • It helps in removing the boilerplate code, extra annotations, and xml configurations
  • It provides powerful batch processing and manages the rest endpoints
  • It provides an efficient jpa-starter library to effectively connect the application with the relational databases
  • It offers a Microservice architecture and cloud configuration that manages all the application related configuration properties in a centralized manner

Let us go ahead with the tutorial implementation but before going any further I’m assuming that you’re aware of the Spring boot basics.

2. Internationalization in Spring Boot

2.1 Tools Used for Spring boot application and Project Structure

We are using Eclipse Kepler SR2, JDK 8, and Maven. In case you’re confused about where you should create the corresponding files or folder, let us review the project structure of the spring boot application.

spring boot internationalization - project structure
Fig. 1: Project structure

Let us start building the application!

3. Creating a Spring Boot application

3.1 Maven Dependency

Add the basic spring boot dependencies to the pom.xml. Maven will automatically resolve the other dependencies.
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot.internationalization</groupId>
    <artifactId>SpringbootInternationalization</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringbootInternationalization</name>
    <description>Springboot and internationalization tutorial</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.2 Application XML file

Create a new XML file at the location: SpringbootInternationalization/src/main/resources/ and add the following code to it. Here we will define the spring configuration and a placeholder key for the internationalization.

application.yml

placeholder:
  greetings: welcome.message
server:
  port: 9800
spring:
  application:
    name: springboot-and-internationalization

3.3 Language files

Create the language properties at the location: SpringbootInternationalization/src/main/resources/internationalization. We will create 3 different properties file where we will specify the welcome.message property in the native language. We will create the English translation file and similarly, you can create the properties file for the French and German language.

lang. properties

welcome.message=Greetings {0}

3.4 Java Classes

3.4.1 Implementation/Main class

Add the following code to the main class to bootstrap the application from the main method. Always remember, the entry point of the spring boot application is the class containing @SpringBootApplication annotation and the static main method.

SpringbootInternationalizationApplication.java

package com.springboot.internationalization;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//lombok annotation
@Slf4j
//spring annotation
@SpringBootApplication
public class SpringbootInternationalizationApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootInternationalizationApplication.class, args);
        log.info("Springboot internationalization application is started successfully");
    }
}

3.4.2 Locale configuration class

Add the following code to the configuration class where will define the locale configuration as in this tutorial we will use the AcceptHeaderLocaleResolver bean that helps to accept the Accept-Language header from the request.

LocaleConfig.java

package com.springboot.internationalization.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;

import java.util.Locale;

//spring annotation
@Configuration
public class LocaleConfig {

    //AcceptHeaderLocaleResolver helps to retrieve locale based on the Accept-Language
    // header in the request
    @Bean
    public AcceptHeaderLocaleResolver localeResolver() {
        final AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
        resolver.setDefaultLocale(Locale.US);
        return resolver;
    }

    //ResourceBundleMessageSource resolve text messages from properties file based on different locales
    @Bean
    public ResourceBundleMessageSource messageSource() {
        final ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("internationalization/lang");
        return source;
    }
}

3.4.3 Greetings controller class

Add the following code to the controller class to accept the incoming request and return a response to the user.

HelloController.java

package com.springboot.internationalization.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.bind.annotation.*;

import java.util.Locale;

//lombok annotation
@Slf4j
//spring annotations
@RestController
@RequestMapping("/api")
public class HelloController {

    @Autowired
    private ResourceBundleMessageSource source;
    @Value("${placeholder.greetings}")
    private String greetings;

    //URL - http://localhost:9800/api/get-message
    //or
    //URL - http://localhost:9800/api/get-message?username=Daniel
    //note - incoming request to contain the optional "Accept-Language" header
    @GetMapping("/get-message")
    public String getLocaleMessage(
            @RequestHeader(name = "Accept-Language", required = false) final Locale locale,
            @RequestParam(name = "username", defaultValue = "John Wick", required = false) final String username) {
        //if "Accept-Language" header is not present, "en" locale is treated as default
        //if no matching locale is found, "en" locale is treated as default
        log.info("Returning greetings for locale = {}", locale);
        return source.getMessage(greetings, new Object[]{username}, locale);
    }
}

4. Run the Application

To execute the application, right-click on the SpringbootInternationalizationApplication.java class, Run As -> Java Application.

spring boot internationalization - Run the Application
Fig. 2: Run the Application

5. Project Demo

When the application is started, open the Postman tool to hit the application endpoints to persist the data into the database or fetch from it. You are free to use any other tool of your choice to make the post and get requests to the endpoints. Remember that each incoming request contains the Accept-Language header, where we will specify the locale, and based on this locale the appropriate message, will be returned to the user.

Application endpoints

-- HTTP GET endpoint –
http://localhost:9800/api/get-message

-- HTTP GET end (with username specified) –
http://localhost:9800/api/get-message?username=Daniel

In the below image we have sent the Accept-Language header value as de and the message will be displayed in the german language. Similarly, change the header value to fr and the message will be displayed in the French language.

spring boot internationalization - postman request
Fig. 3: Postman request and response

That is all for this tutorial and I hope the article served you whatever you were looking for. Happy Learning and do not forget to share!

6. Summary

In this section, you learned,

  • Steps to implement internationalization in spring boot

You can download the sample application as an Eclipse project in the Downloads section.

7. Download the Project

This was an example of implementing internationalization in a spring boot application.

Download
You can download the full source code of this example here: Internationalization in Spring Boot

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

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

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button