In the age of globalization, software applications are no longer limited by geographical boundaries.
As businesses expand their horizons, it becomes imperative for software developers to ensure their applications are accessible and user-friendly for audiences around the world.
This is where Internationalization (i18n) plays a pivotal role.
Author: Jeffrey Spaan
Created: 2024-10-03
Last updated: 2024-10-03
Internationalization is the process of designing and developing software applications that can be adapted to various languages, regions, and cultures without engineering changes.
While it may seem like an added complexity, the benefits are substantial:
-
Expanded Market Reach: By localizing your application, you open doors to new markets and audiences, thereby increasing your user base and potential revenue streams.
-
Enhanced User Experience: Users feel more comfortable and engaged when they interact with applications in their native language. It fosters trust and loyalty, leading to higher user retention rates.
-
Compliance and Accessibility: In many regions, providing applications in local languages is a legal requirement. By adhering to internationalization standards, you ensure compliance and accessibility for all users.
Spring Boot simplifies the process of internationalization through its built-in support for message bundles and locale resolution. Here's how it works:
For this basic example we will start with a simple REST endpoint which we can call to see the i18n implementation at work.
Lets create an application using the dependencies as previewed:
Because it is just that easy to use. Want to know more about Project Lombok? Click this link
This Spring Framework dependency will provide us with all the necessary functionality to create and manage our REST endpoints.
Now that the Spring Boot application is created, it is time to configure i18n Internationalization.
Within your src/main/resources/application.yml
file, setup the following configuration:
spring:
messages:
basename: i18n/messages
encoding: UTF-8
cache-duration: 60
fallback-to-system-locale: false
logging-language: en
If you are using a application.properties file, the configuration is as follows:
spring.messages.basename=i18n/messages
spring.messages.encoding=UTF-8
spring.messages.cache-duration=60
spring.messages.fallback-to-system-locale=false
spring.messages.logging-language=en
The basename
points to the folder where the messages bundle files are located.
The folder must always be located within folder: src/main/resources
i18n
points to the folder, messages
points to the name with which the bundle file names start.
Messages bundle files store the code and the value for our messages.
In the src/main/resources
folder, create a folder named i18n
Here we will create the messages bundle files for our three languages: English, German and Dutch.
English must be our standard language if no language tag is provided in the REST calls.
messages.properties
= our standard language file, in this example containing the English messages.
messages_de.properties
= containing the German messages.
messages_nl.properties
= containing the Dutch messages.
In each of the messages bundle files, we will configure 6 codes:
hello.world.log
hello.world
hello.name.log
hello.name
hello.multi.log
hello.multi
Example messages.properties
file:
hello.world = Hello World! This is the English message.
hello.world.log = DemoController hello endpoint logging message.
hello.name = Hello {0}
hello.name.log = DemoController hello name endpoint logging message with name {}.
hello.multi = Hello {0}, you are {1} years old and you live in {2}
hello.multi.log = DemoController hello multi endpoint logging message with name {}, age {} and city {}.
Now that i18n Internationalization is configured in our Spring Boot application, it is time to use the newly implemented funcationality.
For this, we will create some REST endpoints using the standard Spring Web implementation.
DemoController.java
@RestController
@RequestMapping(value = "/api/v1")
@Slf4j
public record DemoController(I18nService i18nService) {
@GetMapping("/hello")
public String hello() {
log.info(i18nService.getLogMessage("hello.world.log"));
return i18nService.getMessage("hello.world");
}
@GetMapping("/hello/{name}")
public String helloSingleArg(@PathVariable String name) {
log.info(i18nService.getLogMessage("hello.name.log"), name);
return i18nService.getMessage("hello.name", name);
}
@GetMapping("/hello/multi")
public String helloMultiArg() {
log.info(i18nService.getLogMessage("hello.multi.log"), "John", 30, "Oakland");
return i18nService.getMessage("hello.multi", "John", String.valueOf(30), "Oakland");
}
}
@RestController
is a Spring Boot annotation, stating that this class handles our requests.
@RequestMapping
is used to map requests to controller methods. In this case our endpoint starts with /api/v1
@Slf4j
is the most commonly used logging annotation for Spring Boot applications.
Now the fun begins.
The I18nService
is specifically designed to receive both message codes
with and without arguments.
Apart from that, it automatically retrieves the HttpServletRequest
, enabling the access to the user's request and retrieving their locale (local language).
It is a powerful and essential tool within our i18n Internationalization implementation.
I18nService.java
@Service
@RequiredArgsConstructor
public class I18nService {
private final MessageSource messageSource;
private final HttpServletRequest request;
// The logging language is set within the application.yml file
@Value("${spring.messages.logging-language}")
private String loggingLanguage;
public String getLogMessage(String code) {
return messageSource.getMessage(code, null, Locale.of(loggingLanguage));
}
public String getMessage(String code, @Nullable String... args) {
return messageSource.getMessage(code, args, request.getLocale());
}
}
@Service
is a Spring Boot annotation, stating that this class handles our business logic.
- This method retrieves a log message using the provided message code.
- It utilizes the MessageSource bean to get the message based on the preferred loggingLanguage configured in the
application.yml
file. - The loggingLanguage is retrieved from the
application.yml
file using the@Value
annotation. - It returns the localized log message corresponding to the given message code.
- This method retrieves a message using the provided message code and arguments.
- It also utilizes the MessageSource bean to get the message based on the locale obtained from the HttpServletRequest object.
- The method allows passing additional arguments to be formatted into the message if placeholders are defined in the message code.
- It returns the localized message with arguments replaced, corresponding to the given message code.
- To test the REST endpoints, a tool like Postman can be used to send HTTP GET requests.
- A Postman collection is added within the repository
src/main/resources/postman/collection-to-import.json
- When making requests, the
Accept-Language
header should be set to specify the desired language. - You can use language codes like
en
for English,de
for German, ornl
for Dutch. - Setting the
Accept-Language
header informs the server about the preferred language for the response, allowing the application to return localized messages accordingly.
Endpoint: http://localhost:8081/api/v1/hello
Header: Key Accept-Language
- Value en
, de
or nl
Endpoint: http://localhost:8081/api/v1/hello/{name}
Header: Key Accept-Language
- Value en
, de
or nl
Endpoint: http://localhost:8081/api/v1/hello/multi
Header: Key Accept-Language
- Value en
, de
or nl
The logging messages are shown within the Spring Boot application terminal.
If you have any questions in regard to this repository and/or documentation, please do reach out.
Don't forget to:
- Star the repository
- Follow me for more interesting repositories!