Spring MVC 5 - Internationalization example

Posted on February 18, 2018


Continuing with our previous post, this post shows you how to use the Spring’s internationalization (i18n) functionality in web application.

In Spring framework, MessageSource interface is used to resolve the messages with support of internationalization and localization. 

In Spring MVC, DispatcherServlet enables you to automatically resolve messages using the client’s locale. This is done with LocaleResolver objects.
 

Project structure

Final project structure of our application will look like as follows.

spring-mvc-locale-example.png

Note – No changes are needed in theme properties, CSS, MvcWebApplicationInitializer.java and MyController.java files. Please refer our previous post for these files.

Message properties files

Create resource bundle files under src\main\resources\locale folder as follows.

messages.properties

# messages.properties
app.title=BORAJI.COM
app.nav.home=Home

app.page.header=Spring MVC 5
app.page.body=This is an example of using theme resolver in Spring MVC.

app.theme.title=Change Theme
app.theme.cerulean=Cerulean
app.theme.pulse=Pulse

app.lang.title=Change Language
app.lang.english=English
app.lang.hindi=Hindi
app.lang.chinese=Chinese

messages_hi.properties

# messages_hi.properties
app.title=BORAJI.COM
app.nav.home=\u0939\u094B\u092E

app.page.header=\u0938\u094D\u092A\u094D\u0930\u093F\u0902\u0917 \u090F\u092E\u0935\u0940\u0938\u0940 5
app.page.body=\u092F\u0939 Spring MVC \u092E\u0947\u0902 \u0925\u0940\u092E \u0930\u093F\u091C\u093C\u0949\u0932\u094D\u0935\u0930 \u0915\u093E \u0909\u092A\u092F\u094B\u0917 \u0915\u0930\u0928\u0947 \u0915\u093E \u090F\u0915 \u0909\u0926\u093E\u0939\u0930\u0923 \u0939\u0948

app.theme.title=\u0925\u0940\u092E \u092C\u0926\u0932\u0947\u0902
app.theme.cerulean=\u0906\u0938\u092E\u093E\u0928\u0940
app.theme.pulse=\u092A\u0932\u094D\u0938

app.lang.title=\u092D\u093E\u0937\u093E \u092C\u0926\u0932\u094B
app.lang.english=\u0905\u0902\u0917\u094D\u0930\u0947\u091C\u093C\u0940
app.lang.hindi=\u0939\u093F\u0902\u0926\u0940
app.lang.chinese=\u091A\u0940\u0928\u0940

messages_cn.properties

# messages_cn.properties
app.title=BORAJI.COM
app.nav.home=\u5BB6

app.page.header=Spring MVC 5
app.page.body=\u8FD9\u662F\u5728Spring MVC\u4E2D\u4F7F\u7528\u4E3B\u9898\u89E3\u6790\u5668\u7684\u4E00\u4E2A\u4F8B\u5B50\u3002

app.theme.title=\u66F4\u6539\u4E3B\u9898
app.theme.cerulean=\u851A\u84DD\u7684
app.theme.pulse=\u8109\u51B2

app.lang.title=\u66F4\u6539\u8BED\u8A00
app.lang.english=\u82F1\u8BED
app.lang.hindi=\u5370\u5730\u6587
app.lang.chinese=\u4E2D\u56FD

 

Spring Web Configuration

To configure the internationalization (i18n) in  your web @Configuration class  -

  • First, register the MessageSource by declaring a @Bean method with messageSource name.
  • Next, register the LocaleResolver to resolve the client locale. 
  • Finally, register the LocaleChangeInterceptor in overridden method addInterceptors() of WebMvcConfigurer to set the request parameter for changing the current locale.

MvcWebConfig.java

package com.boraji.tutorial.spring.config;

import java.util.concurrent.TimeUnit;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.CacheControl;
import org.springframework.ui.context.ThemeSource;
import org.springframework.ui.context.support.ResourceBundleThemeSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.theme.CookieThemeResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;

@Configuration
@EnableWebMvc
@ComponentScan("com.boraji.tutorial.spring.controller")
public class MvcWebConfig implements WebMvcConfigurer {

   @Override
   public void configureViewResolvers(ViewResolverRegistry registry) {
      registry.jsp("/WEB-INF/views/", ".jsp");
   }


   @Bean("messageSource")
   public MessageSource messageSource() {
      ReloadableResourceBundleMessageSource messageSource=new ReloadableResourceBundleMessageSource();
      messageSource.setBasename("classpath:locale/messages");
      messageSource.setDefaultEncoding("UTF-8");
      messageSource.setUseCodeAsDefaultMessage(true);
      return messageSource;
   }

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

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      ThemeChangeInterceptor themeChangeInterceptor = new ThemeChangeInterceptor();
      themeChangeInterceptor.setParamName("theme");
      registry.addInterceptor(themeChangeInterceptor);

      LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
      localeChangeInterceptor.setParamName("lang");
      registry.addInterceptor(localeChangeInterceptor);
   }

}

JSP views

Edit your index.jsp file and add one more Bootstrap's dropdown component for changing the language as follows.

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<spring:message code=""/>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><spring:message code="app.title"/> </title>

<spring:theme code="stylesheet" var="themeName" />
<link href='<spring:url value="/resources/css/${themeName}"/>' rel="stylesheet" />

</head>
<body>
   <nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
      <a class="navbar-brand" href="#"><spring:message code="app.title"/></a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse"
         aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
         <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarCollapse">
         <ul class="navbar-nav mr-auto">
            <li class="nav-item active"><a class="nav-link" href="#"><spring:message code="app.nav.home"/> <span class="sr-only"></span></a></li>
         </ul>
      </div>
   </nav>

   <div role="main" class="container">
      <div class="jumbotron">
         <h1><spring:message code="app.page.header"/></h1>
         <p class="lead"><spring:message code="app.page.body"/></p>


         <div class="dropdown">
            <button class="btn btn-danger dropdown-toggle" type="button" id="dropdownMenuButton"
               data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><spring:message code="app.theme.title"/></button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
               <a class="dropdown-item" href="?theme=pulse"><spring:message code="app.theme.pulse"/></a>
               <a class="dropdown-item" href="?theme=cerulean"><spring:message code="app.theme.cerulean"/></a> 
            </div>
         </div>
         <hr/>
         <!-- Dropdown for selecting language -->
         <div class="dropdown">
            <button class="btn btn-danger dropdown-toggle" type="button" id="dropdownMenuButton"
               data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><spring:message code="app.lang.title"/></button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
               <a class="dropdown-item" href="?lang=en"><spring:message code="app.lang.english"/></a> 
               <a class="dropdown-item" href="?lang=hi"><spring:message code="app.lang.hindi"/></a>
               <a class="dropdown-item" href="?lang=cn"><spring:message code="app.lang.chinese"/></a>
            </div>
         </div>

      </div>
   </div>
   <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
   <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

 

Run application

Use the following maven command to run your application.

mvn jetty:run (This command deploy the webapp from its sources, instead of build war).

Enter the http://localhost:8080 URL in browser's address bar to test the LocaleResolver configuration.

spring-mvc-locale-example01.png

Change the language of your application by selecting language from dropdown list.

spring-mvc-locale-example02.png

spring-mvc-locale-example03.png