Get all message properties key value pairs as JSON for selected locale in Spring boot
--
Problem Statement
For internationalization we store all key value pairs as message properties in spring boot project such that our web component doesn’t have to store all the key value pairs for all the locales which we are supporting now or we will support in future. And based on which locale user selects we have to only send the map of key value pairs as a JSON for that particular locale to our web component.
Solution
Let’s say we support three language en, cn and jp language as of now. So we will have three files message_cn.properties
message_jp.properties
, message.properties
in our resources folder. And we all know that we can access the message properties directly in thymeleaf templates as #{key_name}
, but in our case we want all the key value pairs as a map at once. So let’s dive deep into how we solved it step by step.
Step 1
First, we will create a method to get all the message properties by accessing getMergedProperties
method of ReloadableResourceBundleMessageSource
class.
import java.util.Locale;import java.util.Properties;import org.springframework.context.support.ReloadableResourceBundleMessageSource;public class ExposedResourceMessageBundleSource extends ReloadableResourceBundleMessageSource {
public Properties getMessages(Locale locale) {
return getMergedProperties(locale).getProperties();
}
}
Step 2
Now, we can create a utility service which will send us the HashMap of key value pairs given the locale.
// Import ExposedResourceMessageBundleSourceimport org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;import org.springframework.context.MessageSource;import org.springframework.context.NoSuchMessageException;import org.springframework.stereotype.Service;@Service
public class MessageResolverService extends MessageSourceAware { @Autowired
private MessageSource messageSource; @Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
} public Map<String, String> getMessages(Locale locale) {
Properties properties =((AnnotationConfigServletWebServerApplicationContext) messageSource)
.getBean("messageSource", ExposedResourceMessageBundleSource.class).getMessages(locale);
Map<String, String> messagesMap = new HashMap<>();
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
messagesMap.put(entry.getKey().toString(), entry.getValue().toString());
}
return messagesMap;
}
}
Step 3 (Final)
Now we can inject MessageResolverService
in our controller and convert it to JSON with the help of ObjectMapper. So we can create a utility method getLanguageMapJson
which will call the getMessages
method and write it as JSON using ObjectMapper and return the JSON string given the locale.
// Autowire MessageResolveService - import com.ti.dc.avl.service.MessageResolveService;// Autowire ObjectMapper - import com.fasterxml.jackson.databind.ObjectMapper;public String getLanguageMapJson(Locale locale) {
String languageJson = null;
try {
languageJson = objectMapper.
writeValueAsString(messageResolveService.
getMessages(locale));
} catch (Exception e) {
log.error("Something went wrong while converting HashMap to json" + e);
}
return languageJson;
}
If you want to read more about it, go through this doc.