ReloadableResourceBundleMessageSource vs ResourceBundleMessageSource - boundle not found - spring

When I put WAR file with Spring application on Tomcat server, if I use ReloadableResourceBundleMessageSource everything works fine.
#Bean
AbstractMessageSource messageSource()
{
ReloadableResourceBundleMessageSource bundle
= new ReloadableResourceBundleMessageSource();
bundle.setBasename("/WEB-INF/classes/messages");
return bundle;
}
But if I change message source implementation to ResourceBundleMessageSource:
#Bean
AbstractMessageSource messageSource()
{
ResourceBundleMessageSource bundle
= new ResourceBundleMessageSource();
bundle.setBasename("/WEB-INF/classes/messages");
return bundle;
}
I got following error:
org.springframework.context.support.ResourceBundleMessageSource.getResourceBundle ResourceBundle [/WEB-INF/classes/messages] not found for MessageSource: Can't find bundle for base name /WEB-INF/classes/messages, locale pl_PL
What makes a difference?

Related

Internationalization in Spring

I have a springBoot 2.4.0 app, with this piece of code in the controller:
String defaultLocation =
messages.getMessage("home.default.location", null, LocaleContextHolder.getLocale());
In the application I see the messages from the properties loaded correctly with the messages, and no error, but in the log I see this error:
14:43:41.168 [http-nio-7080-exec-13] WARN o.s.c.s.ReloadableResourceBundleMessageSource.refreshProperties 445 - Could not parse properties file [messages_en.properties]
java.util.zip.ZipException: invalid code lengths set
at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:165)
at org.springframework.boot.loader.jar.ZipInflaterInputStream.read(ZipInflaterInputStream.java:52)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
at java.base/java.io.Reader.read(Reader.java:229)
at java.base/java.util.Properties$LineReader.readLine(Properties.java:500)
at java.base/java.util.Properties.load0(Properties.java:415)
at java.base/java.util.Properties.load(Properties.java:378)
at org.springframework.util.DefaultPropertiesPersister.load(DefaultPropertiesPersister.java:64)
at org.springframework.context.support.ReloadableResourceBundleMessageSource.loadProperties(ReloadableResourceBundleMessageSource.java:495)
at org.springframework.context.support.ReloadableResourceBundleMessageSource.refreshProperties(ReloadableResourceBundleMessageSource.java:440)
at org.springframework.context.support.ReloadableResourceBundleMessageSource.getProperties(ReloadableResourceBundleMessageSource.java:395)
at org.springframework.context.support.ReloadableResourceBundleMessageSource.resolveCodeWithoutArguments(ReloadableResourceBundleMessageSource.java:186)
at org.springframework.context.support.AbstractMessageSource.getMessageInternal(AbstractMessageSource.java:212)
at org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:153)
at com.bonanza.controller.HomeController.home(HomeController.java:46)
this is my config class:
#Configuration
public class I18NConfig {
private final Environment env;
public I18NConfig(Environment env) {
this.env = env;
}
#Bean
#Qualifier("messageSource")
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource resourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
resourceBundleMessageSource.setBasename("classpath:i18n/messages");
resourceBundleMessageSource.setDefaultEncoding("UTF-8"); // Set the UTF-8 encoding
resourceBundleMessageSource.setCacheSeconds(1);
return resourceBundleMessageSource;
}
}
Change in your bean definition like this ...remove cache seconds and use setUSeCodeAsDefaultMessage() and give it a try.Also recheck you properties file definitions and naming references.
#Bean
#Qualifier("messageSource")
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource resourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
resourceBundleMessageSource.setBasename("classpath:i18n/messages");
resourceBundleMessageSource.setDefaultEncoding("UTF-8");
resourceBundleMessageSource.setUseCodeAsDefaultMessage(true);
return resourceBundleMessageSource;
}
use
org.springframework.context.support.ReloadableResourceBundleMessageSource
instead of
org.springframework.context.support.ResourceBundleMessageSource
configuration like this:
<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>classpath*:i18n/messages</value>
</property>
</bean>
or this:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:i18n/messages");
messageSource.setCacheSeconds(10); //reload messages every 10 seconds
return messageSource;
}

How to get values from message bundle?

In my application configuration class, I have the following entry:
#Bean(name = "messageSource")
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/i18n/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver(){
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(new Locale("pt_BR"));
return resolver;
}
The message_pt_BR.properties is located according to the attached image.
I'm trying to access an entry on this with a <span th:text="#{app.name}"></span> file and all I get is:
??app.name_pt_br??
What am I missing here?
Your message bundle name should be
messages_pt_BR.properties
It's case sensitive.
It's OK without default message bundle(messages.properties). Mine works fine with only _en and _zh_TW.
And it should be ok that you put your resource bundle everywhere if you give the correct path to set basename.
You need to replace your messages bundle to /resources folder.
Also you need to add messages.properties bundle, it's required.

i18n works with Thymeleaf but not with MessageSource

I am working with Spring MVC+Thymeleaf and getting the following exception when I tried to get a message from de the MessageSource: NoSuchMessageException
My configuration:
#Bean(name="messageSource")
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
source.setBasename("classpath:i18n/messages");
source.setUseCodeAsDefaultMessage(true);
source.setDefaultEncoding( propWebEncoding );
source.setCacheSeconds(0); /* check the last-modified timestamp */
return source;
}
My files are under:
src/main/resources/i18n/messages_es.properties
src/main/resources/i18n/messages_en.properties
My locale is “en”
When I use the message “myproperty.example” in HTML (Thymeleaf) it works fine but not when I try to get the message in my #Controller or #Service with:
#Autowired MessageSource messageSource;
And
messageSource.getMessage(“myproperty.example”, null, Locale.EN);
It raises NoSuchMessageException exception impossible to find … for locale ‘en’
This is all configured with maven and my i18n files are in the target folder under:
WEB-INF/classes/i18n/ [files]
What I am doing wrong?
The problem: I was working in two different contexts. I was calling MessageSource in the #Service tier (getRootConfigClasses) and it was configured in the ServletConfigClasses.
Solution: Only work in the root context (getRootConfigClasses)

Spring-Boot Thymeleaf localization issue

My application works fine when I run it through Intellij (spring-boot jar). However, localized messages are not resolved when I manually deploy the war file to stand-alone tomcat. I get ??key??en_US
(key being the message key)
Any ideas on how to fix this?
I was able to resolve this issue by defining my own message source bundle.
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setAlwaysUseMessageFormat(true);
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setBasenames("classpath:messages");
return messageSource;
}

Why messages don't show up?

I have message property files in my Spring web application. The following is a related configuration:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(0);
return messageSource;
}
The message in the property doesn't show up but the key with a language suffix. For example, a key, nav.welcome, in the property file is shown on a web page as ??nav.welcome_en?? I use Gradlew to run my application. And I see the messages.properties file on the root of the class path.
C:\Users\vic\workspace-sts\myapp\build\tmp\tomcatRunWar\work\Tomcat\localhost\_\WEB-INF\classes>
After turning up org.springframework.web log level, I see the following related log messages:
DEBUG: AnnotationConfigWebApplicationContext:649 - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource#2a83e48a]
and
DEBUG: AnnotationConfigWebApplicationContext:639 - Using MessageSource [org.springframework.context.support.ResourceBundleMessageSource: basenames=[classpath:messages]]
What is missing here?

Resources