Can I tell spring-boot
to automatically resolve the requested locale
by a queryparameter, eg &lang=en
?
I would like to give the query param precedence over Accept-Language
parameter.
I found the following two properties, but nothing about a query param.
spring.mvc.locale= # Locale to use. By default, this locale is overridden by the "Accept-Language" header.
spring.mvc.locale-resolver=accept-header # Define how the locale should be resolved.
I tried as follows, which gives an exception:
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
Results in:
java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
The solution is probably as follows. Still I find the setup very counterintuitive. Especially I would have expected that:
LocaleChangeInterceptor
registers itself, but does not and have to call addInterceptors()
explicitspring.mvc.locale
parameter is still set into the custom LocaleResolver, but does not and have to override manually from WebMvcProperties
If all of this is desired, the docs might probably need more explanation on this.
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
@Bean
public AcceptHeaderLocaleResolver localeResolver(WebMvcProperties mvcProperties) {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver() {
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
LocaleContextHolder.setLocale(locale);
}
};
localeResolver.setDefaultLocale(mvcProperties.getLocale());
return localeResolver;
}
}
Update improved version after discussion:
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Bean
public AcceptHeaderLocaleResolver localeResolver(WebMvcProperties mvcProperties) {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver() {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String locale = request.getParameter("lang");
return locale != null
? org.springframework.util.StringUtils.parseLocaleString(locale)
: super.resolveLocale(request);
}
};
localeResolver.setDefaultLocale(mvcProperties.getLocale());
return localeResolver;
}
}
First, let's see what happen:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
...
Caused by: java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
at org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver.setLocale(AcceptHeaderLocaleResolver.java:142) ~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.i18n.LocaleChangeInterceptor.preHandle(LocaleChangeInterceptor.java:154) ~[spring-webmvc-5.3.2.jar:5.3.2]
...
After debug, you will know:
accept-header
not support preHandle
, you cannot use LocaleChangeInterceptor
accept-header
have not any supported languages, you must add them manual. You can see this issue.accept-header
only work when you set supported languages and the language match Content-Language
from client browser.
So, you needn't use spring.mvc.locale-resolver
or spring.web.locale-resolver
. Nowspring 5.3.2, no properties you need.
The way for your example to solve this is appending another LocaleResolver
: spring.io
@Bean
public LocaleResolver localeResolver() {
return new SessionLocaleResolver();//new CookieLocaleResolver();
}
And set:
spring:
main:
allow-bean-definition-overriding: true # SpringBoot>=2.1.0
web:
locale: en # default
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With