(Quick Reference)

16 Internationalization

Version: 6.0.0

16 Internationalization

Grails supports Internationalization (i18n) out of the box by leveraging the underlying Spring MVC internationalization support. With Grails you are able to customize the text that appears in a view based on the user’s Locale. To quote the javadoc for the Locale class:

A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user. For example, displaying a number is a locale-sensitive operation—​the number should be formatted according to the customs/conventions of the user’s native country, region, or culture.

A Locale is made up of a language code and a country code. For example "en_US" is the code for US English, whilst "en_GB" is the code for British English.

16.1 Understanding Message Bundles

Now that you have an idea of locales, to use them in Grails you create message bundle file containing the different languages that you wish to render. Message bundles in Grails are located inside the grails-app/i18n directory and are simple Java properties files.

Each bundle starts with the name messages by convention and ends with the locale. Grails ships with several message bundles for a whole range of languages within the grails-app/i18n directory. For example:

  • messages.properties

  • messages_da.properties

  • messages_de.properties

  • messages_es.properties

  • messages_fr.properties

  • …​

By default Grails looks in messages.properties for messages unless the user has specified a locale. You can create your own message bundle by simply creating a new properties file that ends with the locale you are interested in. For example messages_en_GB.properties for British English.

16.2 Changing Locales

By default, the user locale is detected from the incoming Accept-Language header. You can provide users the capability to switch locales by simply passing a parameter called lang to Grails as a request parameter:

/book/list?lang=es

Grails will automatically switch the user’s locale and subsequent requests will use the switched locale.

By default, Grails uses SessionLocaleResolver as the localeResolver bean.

You can change the default locale easily:

grails-app/conf/spring/resources.groovy
import org.springframework.web.servlet.i18n.SessionLocaleResolver

beans = {
    localeResolver(SessionLocaleResolver) {
        defaultLocale= new Locale('es')
    }
}

Other localeResolver are available. For example, you could use save the switched locale in a Cookie:

grails-app/conf/spring/resources.groovy
import org.springframework.web.servlet.i18n.CookieLocaleResolver

beans = {
    localeResolver(CookieLocaleResolver) {
        defaultLocale= new Locale('es')
    }
}

Or fix the locale:

grails-app/conf/spring/resources.groovy
import org.springframework.web.servlet.i18n.FixedLocaleResolver

beans = {
    localeResolver(FixedLocaleResolver, new Locale('de'))
}

16.3 Reading Messages

Reading Messages in the View

The most common place that you need messages is inside the view. Use the message tag for this:

<g:message code="my.localized.content" />

As long as you have a key in your messages.properties (with appropriate locale suffix) such as the one below then Grails will look up the message:

my.localized.content=Hola, me llamo John. Hoy es domingo.

Messages can also include arguments, for example:

<g:message code="my.localized.content" args="${ ['Juan', 'lunes'] }" />

The message declaration specifies positional parameters which are dynamically specified:

my.localized.content=Hola, me llamo {0}. Hoy es {1}.

Reading Messages in Grails Artifacts with MessageSource

In a Grails artifact, you can inject messageSource and use the method getMessage with the arguments: message code, message arguments, default message and locale to retrieve a message.

import org.springframework.context.MessageSource
import org.springframework.context.i18n.LocaleContextHolder

class MyappController {

    MessageSource messageSource

    def show() {
        def msg = messageSource.getMessage('my.localized.content', ['Juan', 'lunes'] as Object[], 'Default Message', LocaleContextHolder.locale)
    }

Reading Messages in Controllers and Tag Libraries with the Message Tag

Additionally, you can read a message inside Controllers and Tag Libraries with the Message Tag. However, using the message tag relies on GSP support which a Grails application may not necessarily have; e.g. a rest application.

In a controller, you can invoke tags as methods.

def show() {
    def msg = message(code: "my.localized.content", args: ['Juan', 'lunes'])
}

The same technique can be used in tag libraries, but if your tag library uses a custom namespace then you must prefix the call with g.:

def myTag = { attrs, body ->
    def msg = g.message(code: "my.localized.content", args: ['Juan', 'lunes'])
}

16.4 Scaffolding and i18n

Grails scaffolding templates for controllers and views are fully i18n-aware. The GSPs use the message tag for labels, buttons etc. and controller flash messages use i18n to resolve locale-specific messages.

The scaffolding includes locale specific labels for domain classes and domain fields. For example, if you have a Book domain class with a title field:

class Book {
    String title
}

The scaffolding will use labels with the following keys:

book.label = Libro
book.title.label = Título del libro

You can use this property pattern if you’d like or come up with one of your own. There is nothing special about the use of the word label as part of the key other than it’s the convention used by the scaffolding.