Rest API localization using spring-boot

Photo by Porapak Apichodilok from Pexels
Photo by Porapak Apichodilok from Pexels

This is a quick blog post on how to add locale support for your REST API's using spring-boot. In this example you will learn to send localized content based on the Accept-Language header. 

Accept-Language: Language Tag 

eg:

* Send an API request with Accept-Language: en ,  you will get English language content.

* end an API request with Accept-Language: zh ,  you will get Chinese language (mandarin) content.

You can check the supported language tags from here.  

https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html

Assume that your back-end needs to send localized contents based on the language choose from the front end application. 

The easiest way is to keep this localized messages in a Resource bundle for each language. You can do this by using the ResourceBundleMessageSource.

Create a new resource bundle in src/main/resources directory. This directory holds the property files for each language. I have created a resource bundle named as menu and it contains 2 property files for both English and Chines (Mandarin) languages. A property file contain a key and value pairs. Key will be the message code and value is the actual message. You can add any no of language files as per your requirement. Let's take a look at the property files. 

menu.properties
s1=Hot Pot
s2=Sichuan Pork
s3=Braised Pork Balls in Gravy
s4=Shrimp vermicelli
view raw menu.properties hosted with ❤ by GitHub
menu_zh.properties
s1=火锅
s2=四川猪肉
s3=肉汁炖猪肉丸
s4=虾粉条

Now we need to create a bean class to set these files to a ResourceBundleMessageSource.

package com.rkdevblog.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
@Configuration
public class ResourceBundleMessageSourceBean {
/**
* Set the list of resource files here
*
* @return resourceBundleMessageSource
*/
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource rs = new ResourceBundleMessageSource();
rs.setBasenames("menu");
rs.setDefaultEncoding("UTF-8");
rs.setUseCodeAsDefaultMessage(true);
return rs;
}
}
We are all set, now we just need a Translator class to translate the message to specific language when the message code is given. We can write a simple class as below. 

package com.rkdevblog.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.stereotype.Component;
import java.util.Locale;
@Component
public class Translator {
private final ResourceBundleMessageSource messageSource;
@Autowired
Translator(ResourceBundleMessageSource messageSource) {
this.messageSource = messageSource;
}
public String toLocale(String msgCode) {
Locale locale = LocaleContextHolder.getLocale();
return messageSource.getMessage(msgCode, null, locale);
}
}
Now we can use traslator.toLocale("messageCode") in any place that we need language translation.
In the code sample I have written a simple API to test this, let's see this in action.  

1) I'am invoking a request without any Accept-Language Header, see the results, I'am getting English content meaning that default accept-language will be English.


2) Now I'm sending a request with Accept-Language header as zh.  We should get mandarin language menu.


Yes, as expected we got the mandarin content. So as I mentioned earlier this is a quick getting started guide to support localization from your backend, hope this example helped you to write or design your own localization support. As usual you can find the source code below.

References & Useful Readings.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/support/ResourceBundleMessageSource.html
https://blog.usejournal.com/spring-boot-rest-internationalization-9ab3fce2489


Comments