Java – Spring: How to get the “ACTUAL” / “CURRENT” locale like it works for messages

gettextjavalocalespringspring-mvc

I am a bit puzzled, as I have a working system but I cannot get the actual/current locale.

The working system is about this:

For example from: http://www.mkyong.com/spring-mvc/spring-mvc-internationalization-example/

Some messages.properties file,

A servlet-context.xml file with:

  <!-- Additional i18n -->
  <bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    <property name="defaultLocale" value="en" />
  </bean>

  <bean id="translationService" class="inbiz.webapp.service.TranslationService">
  </bean>
  <alias name="translationService" alias="t" />

  <mvc:interceptors>
    <bean id="localeChangeInterceptor" 
      class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
      <property name="paramName" value="lang" />
    </bean>
  </mvc:interceptors>
  <!-- END: Additional i18n -->

For the TranslationService (even if not directly related to the question check also: java spring mvc @service method: nullpointerexception | newbie and translation)

This apparently makes already everything working within the like of the first link. So I can do:

<a href="" th:text="#{help}">Help</a>

This is thymeleaf (http://www.thymeleaf.org/) but basically the same as JSP or JSF .. The messages get loaded with the correct locale.

But for my TranslationService I need to get the locale just like the messages bundle does.

Following: https://templth.wordpress.com/2010/07/21/configuring-locale-switching-with-spring-mvc-3/, I set up this filter:

package inbiz.webapp.filters;

import java.io.IOException;

import java.util.Map;
import java.util.Locale;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.LocaleResolver;

import org.springframework.context.i18n.LocaleContextHolder;

import org.springframework.web.servlet.support.RequestContextUtils;

import org.springframework.web.filter.OncePerRequestFilter;

public class LocaleConfigurerFilter extends OncePerRequestFilter {

    private LocaleResolver localeResolver;


    protected void initFilterBean() throws ServletException {

    Locale locale;

        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
        Map resolvers = wac.getBeansOfType(LocaleResolver.class);
        if (resolvers.size()==1) {
            localeResolver = (LocaleResolver) resolvers.values().iterator().next();
        }

    locale = LocaleContextHolder.getLocale();
    System.out.println("DEBUG FILTER LOCALE LCH - INIT: "+locale);

    }


    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
    throws IOException, ServletException {

    Locale locale;

    WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());

        Map resolvers = wac.getBeansOfType(LocaleResolver.class);
        if (resolvers.size()==1) {
            localeResolver = (LocaleResolver) resolvers.values().iterator().next();
        }
        if (localeResolver!=null) {
            locale = localeResolver.resolveLocale(req);
        System.out.println("DEBUG FILTER LOCALE LRS: "+locale);
            LocaleContextHolder.setLocale(locale);
        }

    locale = LocaleContextHolder.getLocale();
    System.out.println("DEBUG FILTER LOCALE LCH: "+locale);
    locale = RequestContextUtils.getLocale((HttpServletRequest) req);
    System.out.println("DEBUG FILTER LOCALE RCU: "+locale);
    LocaleContextHolder.setLocale(locale);

    chain.doFilter(req, res);

    }

}

The filter gets called, but the output is just:

DEBUG FILTER LOCALE LCH - INIT: en_US
DEBUG FILTER LOCALE LCH: en_US
DEBUG FILTER LOCALE RCU: en_US
DEBUG FILTER LOCALE LCH: en_US
DEBUG FILTER LOCALE RCU: en_US
DEBUG FILTER LOCALE LCH: en_US
DEBUG FILTER LOCALE RCU: en_US

Even if any page is called with something like: ?lang=it_IT

(which indeed works for the messages.properties)

I am sorry it might be too many information… but as I say I am a bit lost in understanding who keeps the actual locale. Also as the next step will be to set the locale from the user profile, but I need a controlled default if the user is not logged in.

So the final question: How do I get the locale?

I think, I miss some fundamental points … and the solution is just one line. But at present I finished my "web" resources.. 😉 Maybe a wrong search..

On the other side I give a bit of information, so that it might help
other people trying to implement a "gnu gettext" version.

Best Solution

  1. First of all, let's consider how the LocaleResolver is registered in a Spring context (pay attentiona, that default locale is set):

    @Configuration
    @EnableWebMvc
    @ComponentScan(value = "com.locales.package")
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Bean(name = "localeResolver")
        public LocaleResolver getLocaleResolver(){
            CookieLocaleResolver localeResolver = new CookieLocaleResolver();
            localeResolver.setDefaultLocale(Locale.ENGLISH);
            return localeResolver;
        }
    
    ...
    // Other beans        
    ...
    
    }
    
  2. At last in our controller (or another place) we can get current locale:

    @Autowired
    private LocaleResolver localeResolver;
    
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView resolveLocale(ModelMap model, HttpServletRequest request) {
        Locale locale = localeResolver.resolveLocale(request);
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        modelAndView.addObject("currentLocale", locale.getDisplayLanguage());
    
        return modelAndView;
    }
    
  3. Then we can display the result at JSP (index.jsp):

    <h1>Current locale = ${currentLocale}</h1>