How to use Spring with I18n?

473
February 20, 2017, at 6:23 PM

I've my project on github : https://github.com/QuentinVaut/JavaquariumEE

I've follow many tutorial who say different things and I tried to implement the solutions found in tutorials but nothing wrong, I understand why.

Can you tell me what is wrong with my project and explain me ?

One of many tutorials and Github sample :

http://memorynotfound.com/spring-mvc-internationalization-i18n-example/

Answer 1

I had a cursory look over that tutorial. Here is how I would do it:

First Configure it:

Create a Bean in the configuration class that returns the MessageSource implementation.

@Bean
public MessageSource messageSource() //The bean must be named messageSource.
{
ReloadableResourceBundleMessageSource messageSource =
new ReloadableResourceBundleMessageSource();
messageSource.setCacheSeconds(-1); //cache time in seconds was set to -1. This disables reloading and makes the message source cache messages forever (until the JVM restarts).
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
messageSource.setBasenames(
"/WEB-INF/i18n/messages", "/WEB-INF/i18n/errors"); //the message source is configured with the basenames /WEB-INF/i18n/messages and /WEB-INF/i18n/errors. This means that the message source will look for filenames like /WEB-INF/i18n/messages_en_US.properties, /WEB-INF/i18n/errors_fr_FR.properties
return messageSource;
}

Now create a bean that returns LocaleResolver:

@Bean
public LocaleResolver localeResolver() //The bean must be named localeResolver.
{
return new SessionLocaleResolver();
}

This makes the LocaleResolver available to any code executed by the DispatcherServlet. That means other non-view JSPs do not have access to the LocaleResolver. To take care of this problem, you can create a Filter and set it up like this:

private ServletContext servletContext;
private LocaleResolver = new SessionLocaleResolver();    
@Inject MessageSource messageSource;
...
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
request.setAttribute(
DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver
);
JstlUtils.exposeLocalizationContext(
(HttpServletRequest)request, this.messageSource
); 

Now you need to configure Handler Interceptors:

You override the addInterceptors method of WebMvcConfigurerAdapter in your configuration class to set up LocaleChangeInterceptor (or any other interceptor for that matter.):

@Override
public void addInterceptors(InterceptorRegistry registry)
{
super.addInterceptors(registry);
registry.addInterceptor(new LocaleChangeInterceptor());
}

Now you can simply use an @Injected LocaleResolver on your controller. You simply call setLocale on the resolver to update the current locale.

Edit: More Specific Example:

Say you have a simple controller that has this:

@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Map<String, Object> model)
{
model.put("date", new Date());
model.put("alerts", 12);
model.put("numCritical", 0);
model.put("numImportant", 11);
model.put("numTrivial", 1);
return "home/index";
}

Then say you have messages_en_US.properties file under /WEB-INF/i18n/. This properties file contains messages localized for US English.

title.alerts=Server Alerts Page

alerts.current.date=Current Date and Time:

number.alerts=There {0,choice,0#are no alerts|1#is one alert|1

alert.details={0,choice,0#No alerts are|1#One alert is|1<{0,number,integer} > \ alerts are} critical. {1,choice,0#No alerts are|1#One alert is|1<{1,number,\ integer} alerts are} important. {2,choice,0#No alerts are|1#One alert \ is|1<{2,number,integer} alerts are} trivial.

Then, say that you have messages_es_MX.properties file under /WEB-INF/i18n/ and this file contains messages localized for Mexican Spanish.

title.alerts=Server Alertas Página

alerts.current.date=Fecha y hora actual: number.alerts={0,choice,0#No hay alertas|1#Hay una alerta|1

alert.details={0,choice,0#No hay alertas son críticos|1#Una alerta es \ crítica|1<{0,number,integer} alertas son críticos}. \ {1,choice,0#No hay alertas son importantes|1#Una alerta es importante\ |1<{1,number,integer} alertas son importantes}. \ {2,choice,0#No hay alertas son triviales|1#Una alerta es trivial\ |1<{2,number,integer} alertas son triviales}.

Now, you need to use <spring:message> tag in your JSP to translate between English and Spanish. This is how your jsp page will look like:

<spring:htmlEscape defaultHtmlEscape="true" /> 
<%--@elvariable id="date" type="java.util.Date"--%> 
<%--@elvariable id="alerts" type="int"--%> 
<%--@elvariable id="numCritical" type="int"--%> 
<%--@elvariable id="numImportant" type="int"--%> 
<%--@elvariable id="numTrivial" type="int"--%> 
 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 
 
<!DOCTYPE html> 
<html> 
<head> 
<title><spring:message code="title.alerts" /></title> 
</head> 
<body> 
<h2><spring:message code="title.alerts" /></h2> 
<i><fmt:message key="alerts.current.date"> 
<fmt:param value="${date}" /> 
</fmt:message></i><br /><br /> 
<fmt:message key="number.alerts"> 
<fmt:param value="${alerts}" /> 
</fmt:message><c:if test="${alerts > 0}"> 
&nbsp;<spring:message code="alert.details"> 
<spring:argument value="${numCritical}" /> 
<spring:argument value="${numImportant}" /> 
<spring:argument value="${numTrivial}" /> 
</spring:message> 
</c:if> 
</body> 
</html>

Answer 2

In my application.properties, I added this line :

spring.messages.basename=i18n/messages
spring.messages.cache-seconds=-1
spring.messages.encoding=UTF-8

You can remove the MessageSource bean with this.

Before I use

 <spring:message code="javaquarium.welcome" text="default text" />

But I've thymleaf need this line :

<h1 th:text="#{javaquarium.welcome}"></h1>

Now message from messages.properties show correctly.

READ ALSO
Json Formatting issue in PHP calling from Java

Json Formatting issue in PHP calling from Java

I am calling mysql data in Java as Follows:

355
Stanford NLP POS Tagger(MaxentTagger)

Stanford NLP POS Tagger(MaxentTagger)

I am trying to get the Parts of Speech of few sentences, for this I am using stanford NLP POS tagger english-left3words-distsimtagger

328
Printing Sinhala Unicode letters to Epson xp 310

Printing Sinhala Unicode letters to Epson xp 310

we are trying to print sinhala unicode from Epson xp 310 using java, but when we try to print sinhala unicode from printer, it print as a question mark "?"

335