How to interpolate messages using the client Locale

    This is are the pieces needed to do message interpolation in a web application based on the client Locale. This is just a suggestion, there are other solutions.

     

    Housekeeping

     

    Before we get to the actual validation/interpolation part we need to know how to get to the client locale. If we want to use the Locale provided by the browser one way of going about it is to implement a ServletFilter. In the filter we extract the client Locale and store it in a ThreadLocal.

     

    The ThreadLocal:

    public class ClientLocaleThreadLocal {
    
      private static ThreadLocal<Locale> tLocal = new ThreadLocal<Locale>();
    
      public static void set(Locale locale) {
        tLocal.set(locale);
      }
    
      public static Locale get() {
        return tLocal.get();
      }
    
      public static void remove() {
        tLocal.remove();
      }
    }
    

     

    We set the ThreadLocal in a filter:

    public class TimerFilter implements Filter {
    
      public void destroy() {
      }
    
      public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
        try {      ClientLocaleThreadLocal.set(req.getLocale());       
          filterChain.doFilter(req, res);
        }
        finally {
          ClientLocaleThreadLocal.remove();
        }
      }
    
    
     public void init(FilterConfig arg0) throws ServletException {
    }
    }
    






    Custom message interpolator

     

    Next we need a custom interpolator which will use the client Locale stored in the ThreadLocal. We can use delegation for this task:

    public class ClientLocaleMessageInterpolator implements MessageInterpolator {
      private final MessageInterpolator delegate;
    
      public ResourceBundleMessageInterpolator2(MessageInterpolator delegate) {
        this.delegate = delegate;
      }
    
      @Override
      public String interpolate(String message, Context context) {
        return this.interpolate(message, context, ClientLocaleThreadLocal.get());
      }
    
      @Override
      public String interpolate(String message, Context context, Locale locale)
      {
        return delegate.interpolate(message, context, locale);
      }
    }
    

     

    Bootstrapping

     

    Last but not least, we have to get Hibernate Validator to use the custom message interpolator. There are multiple ways to do this and it depends on the environment (eg depdency injection framework, etc), but here is how it would be done in code:

    Configuration config = Validation.byDefaultProvider().configure();
    config = config.messageInterpolator( config.getDefaultMessageInterpolator() );
    Validator validator = config.buildValidatorFactory().getValidator();