Unexpected behavior of default message in org.springframework.context.MessageSource.getMessage ()

What I wanted to do

I encountered unintended behavior when supporting multilingualization with spring-boot, so I will describe it here (probably the same for spring). What I wanted to do was to get the language information from the outside and display the message of that language, but if it is an unsupported language, display some default message. However, this default message may not appear as expected.

Example

Suppose you have English and Japanese language property files, as shown below.

messages_en.properties


key1=hoge
key2=fuga

messages_ja.properties


key1=Hoge
key2=Fuga

At this time, what happens if you try to get the message by specifying Chinese with the following display () method?

    @Autowired
    private MessageSource messageSource;

    public void display() {
        System.out.println(getMessage1(Locale.CHINESE));
        System.out.println(getMessage2(Locale.CHINESE));
    }

    /**
     *Get multilingualized messages.
     * @param locale locale
     * @return Multilingual message
     */
    private String getMessage1(Locale locale) {
        return messageSource.getMessage("key1", null, locale);
    }

    /**
     *Get multilingualized messages.
     * @param locale locale
     * @return Multilingual message
     */
    private String getMessage1(Locale locale) {
        return messageSource.getMessage("key1", null, "Default message", locale);
    }

As far as you can see this Javadoc, getMessage1 throws NoSuchMessageException and getMessage2 It seems like "default message" is displayed, but it didn't happen in my environment. Both come out as "hoge".

What went wrong

The above code is not bad. The cause was a property of MessageSource. In spring-boot, common application properties are defined as shown in here. However, there is a property called ** spring.messages.fallback-to-system-locale ** in it. In that comment

Whether to fall back to the system Locale if no files for a specific Locale have been found.

There is. The translation is

Whether to fall back to the system locale if the file for the specified locale is not found.

is. This is ** true ** by default (in short, if undefined). That is, as long as this property is true, getMessage1 will not throw a NoSuchMessageException and getMessage2 will not return a default message. Since the language of the environment in which the application is deployed is displayed, in the case of my environment this time, a Japanese message was always output when a language that did not correspond was passed.

What to do

It's easy to fix. You can set the following properties in application.yml (or application.properties).

application.yml


spring.messages.fallback-to-system-locale: false

If MessageSource was defined on Java side, it can be set by the following method.

messageSource.setFallbackToSystemLocale(false);

At the end

It was difficult to find the cause. And since it is a change in behavior that is discovered depending on the environment, even if there is no problem in testing in your own country, it may become a troublesome problem that it will be discovered if you deploy it on a foreign server, so be careful.

Recommended Posts

Unexpected behavior of default message in org.springframework.context.MessageSource.getMessage ()
[FCM] Implementation of message transmission using FCM + Spring boot
Going out of message (Spring boot)
About the error message Invalid redeclaration of'***'
Unexpected behavior of default message in org.springframework.context.MessageSource.getMessage ()
[Ruby] Behavior of evaluation of conditional expression in while
Behavior of ThreadPoolTaskExecutor
Summary of how to implement default arguments in Java
Output in multiples of 3
About the default behavior of decimal point rounding using java.text.NumberFormat
Differences in default behavior of memory and CPU recognition on kubernetes (GKE) for each Java version