Reading message.properties(i18n) file programmatically

Nakul Pant
TechCret Software
Published in
3 min readApr 30, 2020
In this blog, we will see how can we access the properties file in Spring Boot programmatically.

Some time back I was working on a use case to get the localized messages from the database instead of message.properties. Since the application was a multi-tenant application we needed to provide the message customization feature to our users as well.

Sounds good? But the main issue was where to store the default messages. As it would have been hectic to every time create the entries in the database for every tenant. The problem became more hectic when we started developing the application. So to overcome this problem we used the properties file to contain default messages for each category like validations, API responses, etc.

This properties file then will be loaded at the booting up of the application and will create the messages with their keys into the databases. I will cover internationalized messages from the database in a separate story.

So let’s start with a basic example of how to get this done.

So here’s our properties file that had the validation messages.

So these messages were the default messages that will be created for every tenant in the database. Next, we create a database schema to hold these records in the database. We are using MongoDB for the database.

Here locale will store the language code, the key will store the message key from the properties file, the content will store the message content from the properties file. tenantId stores the unique key of the tenant for which the message record is created. For simplification, I have categorized the message types to be of types of VALIDATION, API, etc stored in messageType.

@UniqueMessageKey(message = “validation.message.key.exists”) is a custom validator to check that duplicate message keys don’t get created for every tenant. You can read more about Custom Validators in my previous blog here.

Now we will need a service class that processes our properties file and stores them in the database.

Our validation service class implements the InitializingBean which will call afterPropertiesSet() overridden method after the initialization. The properties field is a hashmap which will store the key values from the properties file and will be used for other processing. MessageRepository is our repository class for the Message model.

Next, we load the validation.properties as a classpath resource in the afterPropertiesSet() method. We will use to load our resource as properties instance.
PropertiesLoaderUtils.loadProperties() is a convenient method that loads a resource for programmatically accessing the content as key-value. We iterate on this properties instance and store the key-value based message in our defined properties map.

Now we create a method in this service class that will be used to create the database records of these messages for all tenants.

In this createValidationMessagesForAllTenants() method, we iterate over the properties map and create database records for the messages per tenants. For the sake of simplicity, we are using default locale in this example.

Looks good so far. But what if we have to add/modify a new property? Do we have to create a new record every time? Let's add one more method which will update the records in the database.

This updateValidationMessagesForAllTenants() will check if a record exists by the message key, if not then this will create the new message record for the tenants.

Now you must be wondering that we have created these two methods but we aren’t using these methods anywhere. So let’s create a service that will be bootstrapping these messages on application startup and updating the records if changed.

Our MessageBootstrap.java is a service class that contains a method createData() that can be called in your application-level bootstrap which caters to the application level bootstrapping of data. We have a boolean flag isUpdatingMessagesAllowed that can be turned on or off to allow updating of messages. This can be achieved in various ways but for simplicity, I have taken it in the method itself.

In our next story, we will see how to configure and use these database aware localized messages in our application.

--

--