diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java index 8039a13fb4..e0be67a3ca 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; @@ -49,10 +50,12 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.util.StringUtils; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -61,6 +64,7 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; +import org.springframework.web.servlet.i18n.FixedLocaleResolver; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.view.BeanNameViewResolver; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; @@ -139,6 +143,9 @@ public class WebMvcAutoConfiguration { @Value("${spring.resources.cachePeriod:}") private Integer cachePeriod; + + @Value("${spring.mvc.locale:}") + private String locale = ""; @Autowired private ListableBeanFactory beanFactory; @@ -190,6 +197,13 @@ public class WebMvcAutoConfiguration { return resolver; } + @Bean + @ConditionalOnMissingBean(LocaleResolver.class) + @ConditionalOnExpression("'${spring.mvc.locale:}' != ''") + public LocaleResolver localeResolver() { + return new FixedLocaleResolver(StringUtils.parseLocaleString(this.locale)); + } + @Override public void addFormatters(FormatterRegistry registry) { for (Converter converter : getBeansOfType(Converter.class)) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java index 98644cca2e..036f76248f 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java @@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web; import java.lang.reflect.Field; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -28,27 +29,34 @@ import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; +import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.View; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; +import org.springframework.web.servlet.i18n.FixedLocaleResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.view.AbstractView; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -141,6 +149,40 @@ public class WebMvcAutoConfigurationTests { equalTo((Resource) new ClassPathResource("/foo/"))); } + @Test(expected = NoSuchBeanDefinitionException.class) + public void noLocaleResolver() throws Exception { + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + this.context.register(AllResources.class, Config.class, + WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + this.context.getBean(LocaleResolver.class); + } + + @Test + public void overrideLocale() throws Exception { + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + // set fixed locale + EnvironmentTestUtils.addEnvironment(this.context, + "spring.mvc.locale:en_UK"); + this.context.register(AllResources.class, Config.class, + WebMvcAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + // mock request and set user preferred locale + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addPreferredLocale(StringUtils.parseLocaleString("nl_NL")); + LocaleResolver localeResolver = this.context.getBean(LocaleResolver.class); + Locale locale = localeResolver.resolveLocale(request); + assertThat(localeResolver, + instanceOf(FixedLocaleResolver.class)); + // test locale resolver uses fixed locale and not user preferred locale + assertThat(locale.toString(), + equalTo("en_UK")); + } + @SuppressWarnings("unchecked") protected Map> getMappingLocations() throws IllegalAccessException { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index f9afc30df9..23fde8aab6 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -67,6 +67,7 @@ content into your application; rather pick only the properties that you need. # SPRING MVC ({sc-spring-boot-autoconfigure}/web/HttpMapperProperties.{sc-ext}[HttpMapperProperties]) http.mappers.json-pretty-print=false # pretty print JSON http.mappers.json-sort-keys=false # sort keys + spring.mvc.locale= # set fixed locale, e.g. en_UK spring.view.prefix= # MVC view prefix spring.view.suffix= # ... and suffix spring.resources.cache-period= # cache timeouts in headers sent to browser