Shailendra Singh
Shail's Blog

Shail's Blog

Internationalization in Spring Boot

Internationalization in Spring Boot

Shailendra Singh
·Apr 10, 2022·

4 min read

Listen to this article

Table of contents

What is Internationalization & Why do we need it?

The method of adapting your application to multiple languages, regional quirks, and technological needs of a targeted locality is known as internationalization and localization, or i18n and L10n, respectively.

Because we are living in an era of globalization and we want to make our application accessible to as many users as possible and having your application available in multiple languages helps to do that.

Internationalization in Spring Boot 101

MessageSource

The message source interface was developed by Spring developers to help with internationalization in Spring Boot applications. Here we (or more precisely Spring Boot auto-configuration) will be using its ResourceBundleMessageSource 1    implementation for our language resource resolving purpose. Under the hood, the class uses JDK's ResourceBundle 2   implementataion. By default, Spring Boot looks for the presence of a messages resource bundle (i.e, messages.properties)at the root of the classpath. If we want to define a custom resource bundle for our messages we can do it by using the property spring.messages.basename in application.properties

Rules to follow for resource file

  • All resource file should be kept in same package.
  • All resource file must share a common basename.
  • The default resource file should simply have the basename like basename.properties.
  • Additional properties files must be named in the following pattern:
    • Resource file for a specific language should have the name as basename_languageCode.properties
    • If we want to restrict the target location down to a particular country, it should be named as basename_languageCode_countryCode.properties

LocaleResolver 3

The interface is used for web-based locale resolution strategies that allow for both request and response-based locale resolution and change. There are a few LocaleResolver implementations in Spring that are utilised in various scenarios. In our example, we will be using CookieLocaleResolver implementation, that uses a cookie sent back to the user in case of a custom setting, with a fallback to the specified default locale or the request's accept-header locale.

LocaleChangeInterceptor 4

LocaleChangeInterceptor will intercept each request that the application receives and eagerly inspect the HTTP request for the argument set in the LocaleChangeInterceptor bean definition.

In our example, we will be using "lang" as a parameter. To utilise the interceptor we should add it to the Spring InterceptorRegistry and to do that we will use WebMvcConfigurer and override the method addInterceptors.

Implementation

Let's create a basic Spring Boot web application using Spring Initializer and add Spring Web and Thymeleaf dependency.

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

Let's create a simple controller with a method annotated with @GetMapping to the root url.

HomeController.java

@Controller
public class HomeController {

    @GetMapping(value = "/")
    public String home() {
        return "home";
    }

}

Let's write the configuration to resolve the locale.

MvcConfigurer.java

@Configuration
public class MvcConfigurer implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver () {
        CookieLocaleResolver localeResolver = new CookieLocaleResolver();
        return localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

Let's create our message resource.

messages.properties

title=Internationalization Demo
message=The website ApneKaamSeKaamRakho or AKSKR as we call it, is currently in the works, and two great minds are working to create a fun website where you can connect and be entertained by playing entertaining games and trivia quizzes, among other things.
The website will be up and running soon, so keep an eye out for it.
lang-en=English
lang-es=Spanish

messages_es.properties

title=Demostración de internacionalización
message=El sitio web ApneKaamSeKaamRakho o AKSKR, como lo llamamos, está actualmente en proceso, y dos grandes mentes están trabajando para crear un sitio web divertido donde pueda conectarse y entretenerse jugando juegos divertidos y cuestionarios de trivia, entre otras cosas.
lang-en=Inglés
lang-es=Español

Let's create a simple Thymeleaf template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title th:text="#{title}">Internationalization Demo</title>

</head>
<body>
<div class="one">
    <a class="one" href="https://www.akskr.com" target="_blank">
        <div>A<span>PNE</span></div>
        <div>K<span>AAM</span></div>
        <div>S<span>E</span></div>
        <div>K<span>AAM</span></div>
        <div>R<span>AKHO</span></div>
    </a>
</div>
<br>
<br>
<div th:text="#{message}" class="para"></div>

<br>
<br>
<br>
<button type="button" th:text="#{lang-en}" onclick="window.location.href='http://localhost:8080/?lang=en'"
        class="btn"></button>
<button type="button" th:text="#{lang-es}" onclick="window.location.href='http://localhost:8080/?lang=es'"
        class="btn"></button>
</body>
</html>

On clicking the button, the page is reloaded with and additional parameter lang=en or lang=es for English or Spanish respectively.

Testing

To test our implementation let's run our application and go to http://localhost:8080/. We will see that our application is loaded in English.

image.png

Let's try switching the language through buttons. We will see that our website is switched to Spanish language.

image.png

Now, let's change the default language of our browser to Spanish and move it to top in the list.

image.png

Now, navigate to http://localhost:8080/ and the website would load in Spanish by default.

image.png

Now, you can try switching your language to English and reload the page and see it will load in English.

Summary

In this article, we learnt how we can localize our application and integrate internationalization in Spring Boot. We learned how to use MessageSource implementations to perform simple translations, how to resolve languages using the details of incoming HTTP requests using LocaleResolver and LocaleChangeInterceptor classes, and how to switch to a different language with a single click in our internationalized Spring Boot web application.

As always you can find the source code for the example @ Github

 
Share this