error-handling-spring-boot-starter
error-handling-spring-boot-starter copied to clipboard
Internationalization of error codes/messages
Hi,
I am currently evaluating this framework and I am kind of wondering if there is a possibility to achieve internalization of codes/messages. The framework I think expects the custom codes and messages to be part of application.properties. How message bundles can be utilised to achieve internalization in this scenario. If you can post some examples that would be helpful.
Best Regards
There is indeed no support for i18n in this library. This is kind of intentional. The goal is that the client would use the code
value to display an appropriate message to the user and the i18n would be done on the client side. The message
is intentionally in English so any developer that receives this, or sees it in a log file can understand it, no matter what language the actual user of the system is using.
As a workaround, you could define a bean in your application of type ErrorMessageMapper
:
@Bean
public ErrorMessageMapper errorMessageMapper(ErrorHandlingProperties properties, MessageSource messageSource) {
return new MyErrorMessageMapper(properties,messageSource);
}
With MyErrorMessageMapper
defined as:
public class MyErrorMessageMapper extends ErrorMessageMapper {
private final MessageSource messageSource;
public MyErrorMessageMapper(ErrorHandlingProperties properties, MessageSource messageSource) {
super(properties);
this.messageSource = messageSource;
}
// override all public methods here and use `messageSource` to get the translations from `messages.properties` and the other `messages_xx.properties` files that have the translations.
}
I did not test it, but normally that should work.
Another alternative is to use a custom superclass for all your exceptions.
For example:
public abstract class TranslatableRuntimeException extends RuntimeException {
@ResponseErrorProperty
private TranslatedItem translatedItem;
public TranslatableRuntimeException(String message, TranslatedItem translatedItem) {
}
public record TranslatedItem(
String key,
@Nullable String... parameters
) {
}
}
This would add translatedItem
into the JSON response. We can now remove that translatedItem
from the JSON and replace it with translatedMessage
that has the actual translated text based on the translatedItem
by writing a custom ApiErrorResponseCustomizer
:
@Configuration
public class ErrorHandlingConfiguration {
@Bean
public ApiErrorResponseCustomizer translatableRuntimeExceptionCustomizer(MessageSource messageSource) {
return new ApiErrorResponseCustomizer() {
@Override
public void customize(ApiErrorResponse response) {
TranslatedItem item = (TranslatedItem)response.getProperties().get("translatedItem");
if(item != null) {
response.getProperties().remove("translatedItem");
resonse.addErrorProperty("translatedMessage", messageSource.getMessage(item.key(), item.parameters(), LocaleContextHolder.getLocale());
}
}
}
}
}