From e150b2ff54c67faa719ce889782351b3ad91e3b1 Mon Sep 17 00:00:00 2001 From: maibin Date: Thu, 19 Jan 2017 11:37:38 +0100 Subject: [PATCH] i18n fixes Thymeleaf (#1015) * How to work with dates in Thymeleaf * Fixes in PR for Thymeleaf * Changes to i18n --- spring-thymeleaf/pom.xml | 514 +++++++++--------- .../thymeleaf/config/WebMVCConfig.java | 147 ++--- .../thymeleaf/controller/DatesController.java | 16 +- .../thymeleaf/controller/HomeController.java | 1 - ...n_US.properties => messages_en.properties} | 0 .../src/main/webapp/WEB-INF/views/home.html | 4 +- ...ilityObjectsControllerIntegrationTest.java | 29 +- 7 files changed, 362 insertions(+), 349 deletions(-) rename spring-thymeleaf/src/main/resources/{messages_en_US.properties => messages_en.properties} (100%) diff --git a/spring-thymeleaf/pom.xml b/spring-thymeleaf/pom.xml index 457ac6dd56..f5dfc9931e 100644 --- a/spring-thymeleaf/pom.xml +++ b/spring-thymeleaf/pom.xml @@ -1,272 +1,262 @@ - 4.0.0 - com.baeldung - spring-thymeleaf - 0.1-SNAPSHOT - war + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + spring-thymeleaf + 0.1-SNAPSHOT + war + + 1.8 + + 4.3.4.RELEASE + 4.2.0.RELEASE + 3.1.0 + + 1.7.21 + 1.1.7 + + 3.0.3.RELEASE + 3.0.0.RELEASE + 2.1.2 + + 1.1.0.Final + 5.3.3.Final + 5.2.5.Final - - - - org.springframework - spring-context - ${org.springframework-version} - - - - commons-logging - commons-logging - - - - - org.springframework - spring-webmvc - ${org.springframework-version} - + 4.12 + + 3.6.0 + 2.6 + 2.19.1 + 1.6.1 + 2.2 + - - - org.springframework.security - spring-security-web - ${springframework-security.version} - - - org.springframework.security - spring-security-config - ${springframework-security.version} - + + + + org.springframework + spring-context + ${org.springframework-version} + + + + commons-logging + commons-logging + + + + + org.springframework + spring-webmvc + ${org.springframework-version} + + + + org.springframework.security + spring-security-web + ${springframework-security.version} + + + org.springframework.security + spring-security-config + ${springframework-security.version} + + + + org.thymeleaf + thymeleaf + ${org.thymeleaf-version} + + + org.thymeleaf + thymeleaf-spring4 + ${org.thymeleaf-version} + + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + ${thymeleaf-layout-dialect.version} + + + org.thymeleaf.extras + thymeleaf-extras-java8time + ${org.thymeleaf.extras-version} + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-version} + provided + + + + javax.validation + validation-api + ${javax.validation-version} + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + - - - org.thymeleaf - thymeleaf - ${org.thymeleaf-version} - - - org.thymeleaf - thymeleaf-spring4 - ${org.thymeleaf-version} - + + org.springframework + spring-test + ${org.springframework-version} + test + - - nz.net.ultraq.thymeleaf - thymeleaf-layout-dialect - ${thymeleaf-layout-dialect.version} - - - org.thymeleaf.extras - thymeleaf-extras-java8time - ${org.thymeleaf.extras-version} - + + + org.springframework.security + spring-security-test + ${springframework-security.version} + test + - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - + + + junit + junit + ${junit.version} + test + - - - javax.servlet - javax.servlet-api - ${javax.servlet-version} - provided - + - - - javax.validation - validation-api - ${javax.validation-version} - - - org.hibernate - hibernate-validator - ${hibernate-validator.version} - + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java-version} + ${java-version} + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LiveTest.java + + + - - - org.springframework - spring-test - ${org.springframework-version} - test - + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty8x + embedded + + + + + + 8082 + + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + ${tomcat7-maven-plugin.version} + + + tomcat-run + + exec-war-only + + package + + / + false + webapp.jar + utf-8 + + + + + + - - org.springframework.security - spring-security-test - ${springframework-security.version} - test - - - - junit - junit - ${junit.version} - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java-version} - ${java-version} - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - false - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - **/*IntegrationTest.java - **/*LiveTest.java - - - - - - org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} - - true - - jetty8x - embedded - - - - - - 8082 - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - ${tomcat7-maven-plugin.version} - - - tomcat-run - - exec-war-only - - package - - / - false - webapp.jar - utf-8 - - - - - - - - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - - - **/*IntegrationTest.java - - - - - - - json - - - - - - - - - - 1.8 - - 4.3.5.RELEASE - 4.2.1.RELEASE - 3.1.0 - - - 1.7.21 - 1.1.7 - - - 3.0.3.RELEASE - 3.0.0.RELEASE - 2.1.2 - - - 1.1.0.Final - 5.3.3.Final - 5.2.5.Final - - 4.12 - - - 3.6.0 - 2.6 - 2.19.1 - 1.6.1 - 2.2 - - - - + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + \ No newline at end of file diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java index 10b9f0b7a0..e4335cbcf3 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java @@ -1,5 +1,7 @@ package com.baeldung.thymeleaf.config; +import java.util.Locale; + import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; @@ -8,10 +10,14 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Description; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.thymeleaf.TemplateEngine; import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect; import org.thymeleaf.spring4.SpringTemplateEngine; @@ -41,70 +47,70 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application this.applicationContext = applicationContext; } - @Bean - public ViewResolver htmlViewResolver() { - ThymeleafViewResolver resolver = new ThymeleafViewResolver(); - resolver.setTemplateEngine(templateEngine(htmlTemplateResolver())); - resolver.setContentType("text/html"); - resolver.setCharacterEncoding("UTF-8"); - resolver.setViewNames(ArrayUtil.array("*.html")); - return resolver; - } + @Bean + public ViewResolver htmlViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(htmlTemplateResolver())); + resolver.setContentType("text/html"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.html")); + return resolver; + } - @Bean - public ViewResolver javascriptViewResolver() { - ThymeleafViewResolver resolver = new ThymeleafViewResolver(); - resolver.setTemplateEngine(templateEngine(javascriptTemplateResolver())); - resolver.setContentType("application/javascript"); - resolver.setCharacterEncoding("UTF-8"); - resolver.setViewNames(ArrayUtil.array("*.js")); - return resolver; - } + @Bean + public ViewResolver javascriptViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(javascriptTemplateResolver())); + resolver.setContentType("application/javascript"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.js")); + return resolver; + } - @Bean - public ViewResolver plainViewResolver() { - ThymeleafViewResolver resolver = new ThymeleafViewResolver(); - resolver.setTemplateEngine(templateEngine(plainTemplateResolver())); - resolver.setContentType("text/plain"); - resolver.setCharacterEncoding("UTF-8"); - resolver.setViewNames(ArrayUtil.array("*.txt")); - return resolver; - } + @Bean + public ViewResolver plainViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(plainTemplateResolver())); + resolver.setContentType("text/plain"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.txt")); + return resolver; + } - private TemplateEngine templateEngine(ITemplateResolver templateResolver) { - SpringTemplateEngine engine = new SpringTemplateEngine(); - engine.addDialect(new LayoutDialect(new GroupingStrategy())); - engine.addDialect(new Java8TimeDialect()); - engine.setTemplateResolver(templateResolver); - return engine; - } + private TemplateEngine templateEngine(ITemplateResolver templateResolver) { + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.addDialect(new LayoutDialect(new GroupingStrategy())); + engine.addDialect(new Java8TimeDialect()); + engine.setTemplateResolver(templateResolver); + return engine; + } - private ITemplateResolver htmlTemplateResolver() { - SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); - resolver.setApplicationContext(applicationContext); - resolver.setPrefix("/WEB-INF/views/"); - resolver.setCacheable(false); - resolver.setTemplateMode(TemplateMode.HTML); - return resolver; - } + private ITemplateResolver htmlTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/views/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.HTML); + return resolver; + } - private ITemplateResolver javascriptTemplateResolver() { - SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); - resolver.setApplicationContext(applicationContext); - resolver.setPrefix("/WEB-INF/js/"); - resolver.setCacheable(false); - resolver.setTemplateMode(TemplateMode.JAVASCRIPT); - return resolver; - } + private ITemplateResolver javascriptTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/js/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.JAVASCRIPT); + return resolver; + } - private ITemplateResolver plainTemplateResolver() { - SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); - resolver.setApplicationContext(applicationContext); - resolver.setPrefix("/WEB-INF/txt/"); - resolver.setCacheable(false); - resolver.setTemplateMode(TemplateMode.TEXT); - return resolver; - } + private ITemplateResolver plainTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/txt/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.TEXT); + return resolver; + } @Bean @Description("Spring Message Resolver") @@ -114,12 +120,31 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application return messageSource; } - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/"); + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver localeResolver = new SessionLocaleResolver(); + localeResolver.setDefaultLocale(new Locale("en")); + return localeResolver; + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("lang"); + return localeChangeInterceptor; } @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/"); + } + + @Override @Description("Custom Conversion Service") public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new NameFormatter()); diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java index 20f5d02fed..74e2356076 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java @@ -13,13 +13,13 @@ import org.springframework.web.bind.annotation.RequestMethod; @Controller public class DatesController { - @RequestMapping(value = "/dates", method = RequestMethod.GET) - public String getInfo(Model model) { - model.addAttribute("standardDate", new Date()); - model.addAttribute("localDateTime", LocalDateTime.now()); - model.addAttribute("localDate", LocalDate.now()); - model.addAttribute("timestamp", Instant.now()); - return "dates.html"; - } + @RequestMapping(value = "/dates", method = RequestMethod.GET) + public String getInfo(Model model) { + model.addAttribute("standardDate", new Date()); + model.addAttribute("localDateTime", LocalDateTime.now()); + model.addAttribute("localDate", LocalDate.now()); + model.addAttribute("timestamp", Instant.now()); + return "dates.html"; + } } diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java index f1a394cac4..21f230c84c 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java @@ -18,7 +18,6 @@ public class HomeController { @RequestMapping(value = "/", method = RequestMethod.GET) public String getHome(Model model) { - DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.getDefault()); model.addAttribute("serverTime", dateFormat.format(new Date())); return "home.html"; diff --git a/spring-thymeleaf/src/main/resources/messages_en_US.properties b/spring-thymeleaf/src/main/resources/messages_en.properties similarity index 100% rename from spring-thymeleaf/src/main/resources/messages_en_US.properties rename to spring-thymeleaf/src/main/resources/messages_en.properties diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html b/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html index 8adecc49f1..aa4047641c 100644 --- a/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html @@ -1,6 +1,6 @@ - + Home diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java b/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java index 5211136c35..597583eee0 100644 --- a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java +++ b/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java @@ -31,25 +31,24 @@ import com.baeldung.thymeleaf.config.WebMVCSecurity; @ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) public class ExpressionUtilityObjectsControllerIntegrationTest { - @Autowired - WebApplicationContext wac; - - @Autowired - MockHttpSession session; + @Autowired + WebApplicationContext wac; + @Autowired + MockHttpSession session; - private MockMvc mockMvc; + private MockMvc mockMvc; - @Autowired - private Filter springSecurityFilterChain; + @Autowired + private Filter springSecurityFilterChain; - protected RequestPostProcessor testUser() { - return user("user1").password("user1Pass").roles("USER"); - } + protected RequestPostProcessor testUser() { + return user("user1").password("user1Pass").roles("USER"); + } - @Before - public void setup() { - mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); - } + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); + } @Test public void testGetObjects() throws Exception {