Spring does a great job with internationalization. Simple, straightforward, great! However I need to easily access the messages from a rich Angular.JS based front end. For that matter it would be ideal to expose the messages in a JSON format that is loaded at the beginning of the app in the browser right? Then it makes sense to have a simple directive to load them all from JSP/JSTL, like:
<script>
var messages = ${ju:getMessages(locale)};
</script>
By default you easily find methods to get key by key but when you need all the messages you will need to create your own MessageSource. So we declare it:
<bean id="messageSource"
class="com.sample.web.CustomReloadableResourceBundleMessageSource">
<qualifier value="messageSource"/>
<!-- <property name="basename" value="classpath:messages" /> -->
<property name="basenames">
<value>/WEB-INF/i18n/messages</value>
</property>
<property name="cacheSeconds">
<value>60</value>
</property>
<property name="fallbackToSystemLocale" value="false" />
</bean>
The java code for the custom Message Source:
package com.sample.web;
import java.util.Locale;
import java.util.Properties;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
public class CustomReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
public Properties getAllProperties(Locale locale) {
clearCacheIncludingAncestors();
PropertiesHolder propertiesHolder = getMergedProperties(locale);
Properties properties = propertiesHolder.getProperties();
return properties;
}
}
A new method for our taglib named getMessages() (If you missed the tutorial for creating the first just search in this blog for it:
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemalocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>2.1</tlib-version>
<uri>JsonUtils</uri>
<function>
<name>toJson</name>
<function-class>com.sample.utils.JsonUtils</function-class>
<function-signature>
String toJson(java.lang.Object)
</function-signature>
</function>
<function>
<name>getMessages</name>
<function-class>com.sample.utils.JsonUtils</function-class>
<function-signature>
String getMessages(java.util.Locale)
</function-signature>
</function>
</taglib>
The new utility method for the taglib:
package com.sample.utils;
import java.io.IOException;
import java.util.Locale;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import com.sample.serialization.JacksonObjectMapper;
import com.sample.utils.web.ApplicationServletContextListener;
import com.sample.web.CustomReloadableResourceBundleMessageSource;
public final class JsonUtils {
private JsonUtils() {
}
public static String toJson(Object value) throws JsonGenerationException, JsonMappingException, IOException {
JacksonObjectMapper mapper = new JacksonObjectMapper();
return mapper.writeValueAsString(value);
}
public static String getMessages(Locale locale) throws JsonGenerationException, JsonMappingException, IOException {
CustomReloadableResourceBundleMessageSource messageSource = (CustomReloadableResourceBundleMessageSource) ApplicationServletContextListener
.getBean("messageSource");
JacksonObjectMapper mapper = new JacksonObjectMapper();
return mapper.writeValueAsString(messageSource.getAllProperties(locale));
}
}
Finally don't forget to inject the locale in your View from Controller. I prefer a single "locale" variable so the front end engineer just have to use the simple statement that started this post.
No comments:
Post a Comment