Spring MVC: Fallback for unknown language code in uri parameter value Spring MVC: Fallback for unknown language code in uri parameter value spring spring

Spring MVC: Fallback for unknown language code in uri parameter value


My suggestion would be to subclass the SessionLocaleResolver and override the getLocale method:

@SpringBootApplicationpublic class DemoApplication {    public static void main(String[] args) {        SpringApplication.run(DemoApplication.class, args);    }    private static Set<Locale> allowedLocales;    static {        HashSet<Locale> allowed = new HashSet<>();        allowed.add(Locale.GERMAN);        allowed.add(Locale.CANADA);        allowedLocales = Collections.unmodifiableSet(allowed);    }    @Bean    LocaleResolver localeResolver() {        return new LimitedSessionLocaleResolver();    }    class LimitedSessionLocaleResolver extends SessionLocaleResolver {        @Override        public Locale resolveLocale(HttpServletRequest request) {            Locale locale = super.resolveLocale(request);            if (!allowedLocales.contains(locale)) {                return determineDefaultLocale(request);            }            return locale;        }    }}

This does not modify the Spring classes in any major way and is probably going to work without issues for the foreseeable future.


Probably far from being perfect but this is what i built...

I also need to say that i changed the default language select mechanism a bit because of SEO needs and i decided to change the language not by using a get parameter but using instead the first part of my uri path for the selected language.For example:http://myurl.com/en/test.html instead of http://myurl.com/test.html?lang=de

In my annotation based configuration:

@Beanpublic LocaleResolver localeResolver() {    UriLocaleResolver uriLocaleResolver = new UriLocaleResolver();    return uriLocaleResolver;}

The locale resolver

public class UriLocaleResolver implements LocaleResolver {    private final Logger logger = LoggerFactory.getLogger(getClass());    private Locale locale = null;    @Autowired    private LocalizationService localizationService;    @Override    public Locale resolveLocale(final HttpServletRequest servletRequest) {        if (locale != null) {            return locale;        }        String languageIsoCode = null;        try {            languageIsoCode = ((String)servletRequest.getAttribute(RequestKey.LANGUAGE_ISO_CODE)).toLowerCase();        }        catch (Exception e) { }        if (StringUtils.isBlank(languageIsoCode) || !localizationService.getSupportedLocaleLanguageIsoCodes().contains(languageIsoCode)) {            logger.trace("Couldn't find valid language iso code. Using default locale '{}'", GlobalConstant.DEFAULT_LOCALE);            return GlobalConstant.DEFAULT_LOCALE;        }        logger.trace("Found language iso code '{}'", languageIsoCode);        return new Locale(languageIsoCode);    }    @Override    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale)     {    this.locale = locale;    }}

The filter which checks for a valid language code in the uri...

@Componentpublic class UriLocalizationFilter extends OncePerRequestFilter {    private final Logger logger = LoggerFactory.getLogger(getClass());    @Autowired    private LocalizationService localizationService;    @Override    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {        String uri = request.getRequestURI().substring(request.getContextPath().length());        String[] pathParts = uri.split("/");        if (!uri.startsWith(GlobalConstant.FRONTEND_RESOURCE_PATH_PREFIX) && pathParts.length >= 1 && pathParts[1].length() == 2) {             String originalLanguageIsoCode = pathParts[1];             String lowerCaseLanguageIsoCode = originalLanguageIsoCode.toLowerCase();            if (localizationService.getSupportedLocaleLanguageIsoCodes().contains(lowerCaseLanguageIsoCode)) {                logger.debug("Found valid language iso code {}", lowerCaseLanguageIsoCode);            }            else {                 logger.debug("Found invalid language iso code {}. Using default language iso code {}.", lowerCaseLanguageIsoCode, GlobalConstant.DEFAULT_LOCALE.getLanguage());                 lowerCaseLanguageIsoCode = GlobalConstant.DEFAULT_LOCALE.getLanguage();            }            String newUrl = StringUtils.removeStart(uri, '/' + originalLanguageIsoCode);            request.setAttribute(RequestKey.LANGUAGE_ISO_CODE, lowerCaseLanguageIsoCode);            logger.debug("Dispatching to new url '{}'", newUrl);            request.getRequestDispatcher(newUrl).forward(request, response);        }        else {            filterChain.doFilter(request, response);        }    }    public void setLocalizationService(LocalizationService localizationService) {        this.localizationService = localizationService;    }}

}

Frontend path is "resources" in my case where all static files like js, css, fonts etc are laying.localizationService.getSupportedLocaleLanguageIsoCodes() is a Set containing currently three language codes (en, ru, de).So in case of a wrong language code like abc im doing a forward with my default language "de". For me it was/is acceptable solution cause having a wrong language code in the uri means that the uri was manipulated by the user...

Like i said its maybe not "the" solution; for example im not sure how and if it works with cookies and/or "remember me" authentications (using spring security)...just had no time to test it yet...


A very late answer, but I thought the easiest way to set a default locale in spring mvc is simply set a i18n file properties with your default language.

For example if you have two languages available in your application (suppose english and deutsch), you've this files:

messages_de.propertiesmessages_en.properties

Then you can simply copy the messages_de.properties to messages.properties, then you've:

messages_de.propertiesmessages_en.propertiesmessages.properties

Spring mvc will fallback automatically to messages.properties file, when the lang parameter does not match with any of the i18n files availables in your application.