Localized REST responses in Quarkus

January 20th 2023 Quarkus

It is not too uncommon that REST responses have to be localized because they are displayed directly in the user interface. However, I could not find an example of this in the Quarkus documentation. Localization is only mentioned in the context of data validation and the approach used there isn't applicable to other use cases.

Since Quarkus is based on Vert.x, its support for localization is also directly available. You only need to inject the RoutingContext where you need it, for example in a resource class:

class GreetingResource(
    private val routingContext: RoutingContext
) {
    // ...
}

This gives you access to two methods with language preferences from the Accept-Language HTTP header, which has already been parsed for you.

The preferredLanguage method returns the first element listed in the header. You can use it to load the appropriate ResourceBundle if it is available, or fall back to a default if it is not:

val locale = Locale.forLanguageTag(routingContext.preferredLanguage()?.tag() ?: "en")
val messages = ResourceBundle.getBundle("messages", locale)

The acceptableLanguages method returns a list of all languages from the header, already sorted by priority. You can use it to load the ResourceBundle for the first supported language or fall back to a default if no language from the list is supported:

val fallbackLocale = Locale.forLanguageTag("en")

val messages = ResourceBundle.getBundle("messages", object: ResourceBundle.Control() {
    override fun getCandidateLocales(baseName: String?, locale: Locale?):
            List<Locale> {
        return routingContext.acceptableLanguages().map {
            Locale.forLanguageTag(it.tag())
        } + fallbackLocale
    }
})

You can find an example project with both approaches in my GitHub repository. The last commit uses acceptableLanguages, the one before that preferredLanguage. Tests document the behavior for different values of the Accept-Language header.

If a functionality you need does not seem to be directly supported (or documented) by Quarkus, you should also check the Vert.x documentation. If you find a solution for it, it is likely that it will work in Quarkus as well, since it is built on top of Vert.x. As shown in this blog post, this also applies to accessing parsed language preferences from the Accept-Language HTTP header.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License