How to set a standard i18n locale using spring-boot and thymeleaf? - java

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

Related

Spring Boot: How to access locale in Services or Repositories

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

Spring Boot: How to access set Locale in Service or Repository layer

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

Spring boot Internationalization ?lang=en has no effect

I'm currently working on a Web-App using Spring boot (including spring security) and thymeleaf. At the moment i'm trying to integrate internationalization support for the languages english and german as a start.
For the basics I've followed this Tutorial and tried to get their example to work.
Now if I go to Localhost:8443/international and choose one of the languages the URL gets built correctly to .../international?lang=en. Thymeleaf even reads the fields in the .propperties file marked as default. But I can't get it to actually switch the language no matter what I do.
Code:
#Configuration
#EnableWebMvc
#EnableAutoConfiguration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**");
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
}
Like this I assume it's taking the default messages.propperties. However if I put the LocaleResolver Bean into my
public class Application extends SpringBootServletInitializer
class where the main method is, it takes whatever language is set as default Locale there.
From where I am at right now I conclude that my .propperties files are fine and can be read but something with the LocaleChangeInterceptor does not work propperly. I went into debug mode but any breakpoints in the WebConfig class did not trigger at all.
One assumption of mine would be Spring security messing something up, such that the ?lang request can't be resolved. (Tried both logged-in and logged-out).
Would be really glad if anyone has some idea on how to resolve the issue, thanks for every reply in advance!
My Application class:
#SpringBootApplication
#EnableMongoRepositories(basePackageClasses = UserRepository.class)
#ComponentScan(basePackages = { "my.company.controller", "my.company.Services", "java.lang.String","my.company.Services.Security" })
#EnableConfigurationProperties(my.company.Services.Storage.StorageProperties.class)
public class Application extends SpringBootServletInitializer {
#Autowired
private UserRepository repository;
#Autowired
private SecUserDetailsService userDetailService;
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
#Bean
CommandLineRunner init(StorageService storageService) {
return (args) -> {
repository.deleteAll();
userDetailService.addUser("bob", "ross", "admin");
userDetailService.addUser("1", "1", "superuser");
userDetailService.addUser("2", "2", "admin");
System.out.println("All users currently in DB:");
System.out.println("-------------------------------");
for (User user1 : repository.findAll()) {
System.out.println(user1);
}
System.out.println();
// storageService.deleteAll();
try {
storageService.init();
} catch (StorageException e) {
System.out.println("Ordner schon vorhanden");
}
};
//If i add this here french gets picked as default language, changing does still not work
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.FRENCH);
return slr;
}
}
Try removing the #ComponentScan annotation. The #SpringBootApplication does the component scanning automatically. I guess your WebConfig class is not loaded.

Spring i18n question marks instead of text

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

Spring 4 Framework Internationalization not identify message from resource properties file with thymeleaf

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() {}

Categories