Internationalise your multi-module Spring Boot Application

Alistair working at his desk alongside Rhys

Alistair pinpoints how and where to define your user-facing strings.

You've probably already read about the file. It allows you to define any strings you wish to present to an end-user.

To retrieve one of these strings in code you first need to get a MessageSource. This is provided via spring dependency injection.

Constructor injection:

@Service // Or some other `Component` annotation
class SomeService( private val messageSource: MessageSource )

Property injection:

private lateinit var messageSource: MessageSource

Then you can call getMessage:

messageSource.getMessage("title.example", null, LocaleContextHolder.getLocale())

args can be provided for string replacement. For example:

messageSource.getMessage("message.hello", arrayOf("Joe Bloggs"), LocaleContextHolder.getLocale())


Notice above, we pass LocaleContextHolder.getLocale() as a Locale to the getMessage call. This tells the MessageSource which language to provide.

LocaleContextHolder provides the current Locale that spring is aware of. This is a powerful mechanism. We don't need to add any custom code to our RestController's or otherwise to determine Locale. Callers can set the locale as a request header and spring will make that available.

To provide other language strings we add a new messages file,

To learn more, check out this guide.


When modularizing your application you may run into trouble. By default the files from each module will conflict with each other. Only one set of messages will be available.

To avoid this, all your messages files need to have different names. A good convention to follow is to use your module name. For example:,,,

Now we need to expose these to the MessageSource. By default, only files named will be found.

In your file add:


Notice we do not include the language extension or the file extension here.

That's it. You can now provide strings in each of your different modules.

Looking for something else?

Search over 400 blog posts from our team

Want to hear more?

Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!