I hava i18n, but experience problems with russian letters. I have question marks ????? instead of text. Configuration:
#Bean
public LocaleResolver localeResolver(){
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setDefaultLocale(new Locale("ru"));
resolver.setCookieName("locale");
resolver.setCookieMaxAge(60 * 60 * 24 * 365 * 10);
return resolver;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor changeInterceptor = new LocaleChangeInterceptor();
changeInterceptor.setParamName("lang");
return changeInterceptor;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:/i18n/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
Also I am using Thymeleaf.
<h1 th:text="#{message}"></h1>
Just a guess: in "addInterceptor" you are constructing the LocaleChangeInterceptor manually yourself. If this class depends on other spring beans (like MessageSource) then these are not injected. Find a way to let spring instantiate the LocaleChangeInterceptor (e.g. by using one of the various getBean() of the application context).
Your files encoding is wrong. You should set it to UTF-8. If you use Intellij IDEA you can find it in the right bottom corner. If this option is disabled go to Settings -> Editor -> File Encodings and change the Default encoding for properties files parameter
Related
I followed some tutorials for internationalization in Spring Boot.
(https://www.youtube.com/watch?v=Y7pHhui0cD4 and https://www.baeldung.com/spring-boot-internationalization)
I came so far to configure it like this:
#Configuration
public class InternationalizationConfiguration {
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.GERMAN);
return sessionLocaleResolver;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
}
and to use it in the RestConroller like this:
#RestController
public class ExperimentalControllerImpl implements ExperimentalController{
#Autowired
ResourceBundleMessageSource messageSource;
#Override
public String testI18n(#RequestHeader("Accept-Language") String locale) {
StringBuilder builder = new StringBuilder();
builder.append(messageSource.getMessage(Messages.HELLO, null, new Locale(locale)));
builder.append("\n");
builder.append(messageSource.getMessage(Messages.HOW_ARE_YOU, null, new Locale(locale)));
return builder.toString();
}
}
It works fine.....
But how do I get the locale information from the request header to my service layer or my repository layers?
Is there a best practise to store the information which locale is sent by the request, so that I can access it in my services and repositories? I think the value must be request/thread specific. Giving it as a method parameter down to the other layer seems pretty ugly.
Thank you
Regards form Germany
I followed some tutorials for internationalization in Spring Boot.
(https://www.youtube.com/watch?v=Y7pHhui0cD4 and https://www.baeldung.com/spring-boot-internationalization)
I came so far to configure it like this:
#Configuration
public class InternationalizationConfiguration {
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.GERMAN);
return sessionLocaleResolver;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
}
and to use it in the RestConroller like this:
#RestController
public class ExperimentalControllerImpl implements ExperimentalController{
#Autowired
ResourceBundleMessageSource messageSource;
#Override
public String testI18n(#RequestHeader("Accept-Language") String locale) {
StringBuilder builder = new StringBuilder();
builder.append(messageSource.getMessage(Messages.HELLO, null, new Locale(locale)));
builder.append("\n");
builder.append(messageSource.getMessage(Messages.HOW_ARE_YOU, null, new Locale(locale)));
return builder.toString();
}
}
It works fine.....
But how do I get the locale information from the request header to my service layer or my repository layers?
Is there a best practise to store the information which locale is sent by the request, so that I can access it in my services and repositories? I think the value must be request/thread specific. Giving it as a method parameter down to the other layer seems pretty ugly.
Thank you
Regards form Germany
I am migrating my project from Thymeleaf 2 to 3 and I'm having an issue with the email template resolver interfering with my web template resolver.
When we first implemented Thymeleaf we followed this document to allow for email templates and web templates and had no issues (section 4.2):
http://www.thymeleaf.org/doc/articles/springmail.html
During conversion to Thymeleaf 3, I worked with ONLY the one template resolver for HTML templates (using the SpringResourceTemplateResolver) and the conversion was fine. I was able to run my application without any problems and the view templates all rendered without problems.
However, when including the email template resolver (using the ClassLoaderTemplateResolver), the following error occurs when going to any controller endpoint that returns a view:
java.io.FileNotFoundException: ClassLoader resource "thymeleaf/thymeleaf/login.html" does not exist
Which indicates it is trying to load the template from the ClassLoaderTemplateResolver and not the SpringResourceTemplateResolver. In Thymeleaf 2 setting the Order attribute solved this problem but this doesn't appear to work in Thymeleaf 3.
I couldn't find any help in the Thymeleaf 3 documentation for having 2 Template resolvers like there was in Thymeleaf 2 docs.
Any suggestions on how to get this working or documentation that I may have overlooked?
I have this same setup (a ClassLoaderTemplateResolver for emails and a SpringResourceTemplateResolver for html page templates). I think you need to set this property:
resolver.setCheckExistence(true);
On whichever of your template resolvers happens first, otherwise spring will assume it exists and you will see the error your seeing.
You can use the following setup..
AppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan("myapp")
public class AppConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(webTemplateEngine());
resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return resolver;
}
#Bean
public TemplateEngine webTemplateEngine() {
//this method must be defined as a bean otherwise i18n messages are not found
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.addTemplateResolver(webTemplateResolver());
return engine;
}
private ITemplateResolver webTemplateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/thymeleaf/");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setSuffix(".html");
resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return resolver;
}
#Bean
public TemplateEngine emailTemplateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(emailTemplateResolver());
return templateEngine;
}
private ITemplateResolver emailTemplateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/thymeleaf/email/");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setSuffix(".html");
resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return resolver;
}
}
And then where you need to use the email template engine, just autowire the emailTemplateEngine and use it
#Autowired
private TemplateEngine emailTemplateEngine;
I integrated i18n to my application using the following config:
#Configuration
public class LocaleConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:/i18n/application");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
I set up properties for "en" and "de" and everything is working fine so far.
If I enter the page from spain for example I only see the placeholder from my html file. But instead of this I want to achieve that the standard language is english ("en") for languages/countries with no existing property config. So I tried this:
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US);
return sessionLocaleResolver;
}
It sets the default to english as I want but now every page (also with existing property for the special language) is displayed in english.
Yo have to delete this
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US);
return sessionLocaleResolver;
}
And add in src\main\resources\i18n the default application.properties in English
That should fix your problem
Using new spring version, with thymeleaf, is not my specialty, with gradle,
I try a lot ways change position files and configurations of basename and still receiving ??welcome.message_**?? on template result.
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class Application {
[...]
#Bean
public ReloadableResourceBundleMessageSource resourceBundleMessageSource(){
ReloadableResourceBundleMessageSource messageSource=new ReloadableResourceBundleMessageSource();
String[] resources= {"/WEB-INF/locale/messages", "WEB-INF/locale/messages", "locale/messages", "i18n", "locale"};
messageSource.setBasenames(resources);
messageSource.setFallbackToSystemLocale(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
LocaleChangeInterceptor localeChangeInterceptor=new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
#Bean
public SessionLocaleResolver sessionLocaleResolver(){
SessionLocaleResolver localeResolver=new SessionLocaleResolver();
localeResolver.setDefaultLocale(new Locale("pt","BR"));
return localeResolver;
}
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
Template:
<h1 th:text="#{welcome.message}">Welcome!</h1>
have 2 properties on src/java/webapp/WEB-INF/local/messages.properties and src/java/webapp/WEB-INF/local/messages_pt_BR.properties
github project: https://github.com/brunoguerra/springtutorial/tree/master/web-scure-jpa
Thanks for any ideia
After walk around I found samples from spring-projects on github. The solution is very simple, just define public MessageSource messageSource() on your MVC configurer instead public ReloadableResourceBundleMessageSource resourceBundleMessageSource() on application configurer.
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
[...]
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
The bean name should be messageSource
We can do it either
#Bean(name ="messageSource")
public MessageSource anyName() {}
Or
public MessageSource messageSource() {}