The new Certification Class of Learn Spring Security is out:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we’re going to take a look at how we can add internationalization to a Spring Boot application.

2. Maven Dependencies

For development, we need the following dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>

The latest version of spring-boot-starter-thymeleaf can be downloaded from Maven Central.

3. LocaleResolver

In order for our application to be able to determine which locale is currently being used, we need to add a LocaleResolver bean:

@Bean
public LocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.US);
    return slr;
}

The LocaleResolver interface has implementations that determine the current locale based on the session, cookies, the Accept-Language header, or a fixed value.

In our example, we have used the session based resolver SessionLocaleResolver and set a default locale with value US.

4. LocaleChangeInterceptor

Next, we need to add an interceptor bean that will switch to a new locale based on the value of the lang parameter appended to a request:

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

In order to take effect, this bean needs to be added to the application’s interceptor registry.

To achieve this, our @Configuration class has to extend the WebMvcConfigurerAdapter class and override the addInterceptors() method:

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

5. Defining the Message Sources

By default, a Spring Boot application will look for message files containing internationalization keys and values in the src/main/resources folder.

The file for the default locale will have the name messages.properties, and files for each locale will be named messages_XX.properties, where XX is the locale code.

The keys for the values that will be localized have to be the same in every file, with values appropriate to the language they correspond to.

If a key does not exist in a certain requested locale, then the application will fall back to the default locale value.

Let’s define a default message file for the English language called messages.properties:

greeting=Hello! Welcome to our website!
lang.change=Change the language
lang.eng=English
lang.fr=French

Next, let’s create a file called messages_fr.properties for the French language with the same keys:

greeting=Bonjour! Bienvenue sur notre site!
lang.change=Changez la langue
lang.eng=Anglais
lang.fr=Francais

6. Controller and HTML Page

Let’s create a controller mapping that will return a simple HTML page called international.html that we want to see in two different languages:

@Controller
public class PageController {

    @GetMapping("/international")
    public String getInternationalPage() {
        return "international";
    }
}

Since we are using thymeleaf to display the HTML page, the locale-specific values will be accessed using the keys with the syntax #{key}:

<h1 th:text="#{greeting}"></h1>

If using JSP files, the syntax is:

<h1><spring:message code="greeting" text="default"/></h1>

If we want to access the page with the two different locales we have to add the parameter lang to the URL in the form: /international?lang=fr

If no lang parameter is present on the URL, the application will use the default locale, in our case US locale.

Let’s add a drop-down to our HTML page with the two locales whose names are also localized in our properties files:

<span th:text="#{lang.change}"></span>:
<select id="locales">
    <option value=""></option>
    <option value="en" th:text="#{lang.eng}"></option>
    <option value="fr" th:text="#{lang.fr}"></option>
</select>

Then we can add a jQuery script that will call the /international URL with the respective lang parameter depending on which drop-down option is selected:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script type="text/javascript">
$(document).ready(function() {
    $("#locales").change(function () {
        var selectedOption = $('#locales').val();
        if (selectedOption != ''){
            window.location.replace('international?lang=' + selectedOption);
        }
    });
});
</script>

7. Running the Application

In order to initialize our application, we have to add the main class annotated with @SpringBootApplication:

@SpringBootApplication
public class InternationalizationApp {
    
    public static void main(String[] args) {
        SpringApplication.run(InternationalizationApp.class, args);
    }
}

Depending on the selected locale, we will view the page in either English or French when running the application.

Let’s see the English version:

screen shot in English
And now let’s see the French version:
screen shot in French

8. Conclusion

In this tutorial, we have shown how we can use the support for internationalization in a Spring Boot application.

The full source code for the example can be found over on GitHub.

Go deeper into Spring Security with the course:

>> LEARN SPRING SECURITY

  • Slava Semushin

    > window.location.replace(‘international?lang=’ + selectedOption);

    Looks like this is too coupled with a page URL. How it’s supposed to work if I have 30+ pages?

    Also using jQuery for such a trivial things looks superfluous. Perhaps, something like this would work too.

    • Loredana Crusoveanu

      The focus here was on the Spring Boot portion, with the jQuery sample being used for exemplification. We’re, of course, not relegated to any specific client side technology or implementation. If we wanted the language to change for all pages of an application, we could have a global variable that retains the locale code and an interceptor to add the lang parameter to every request, but that depends on what front end framework we are using.

      If you don’t like the parameter approach, there is also the possibility of creating a custom LocaleChangeInterceptor in Spring that could determine the locale, for example, from the path and then instead of url?lang=en, we could have /en/url. Then, from the client side, make requests in this format.

  • Adheli Tavares

    I’m getting a ??home.welcome?? on my page. Do you know how to solve this?

    • Grzegorz Piwowarek

      Adheli, is this a problem with your project or with our codebase?