Resolving i18n Messages Outside GSPs and Controllers in Grails

Occasionally I need to use a message from an i18n resource in a service or domain object and every time I forget how. It’s a piece of cake in a controller or GSP because the message method is available, but when it’s not what do I do?

How Do I Lookup a Message Code Without the Tag Lib?

Here’s the code I use in one of my services:

    class MyService {
        //Autowire the grails application bean
        def grailsApplication

        private def getMessage(Locale locale) {
            def appCtx = grailsApplication.getMainContext()
            return appCtx.getMessage("message.code",
                                     ["arg1", "arg2"],
                                     "default message",
                                     locale)
        }
    }

So it’s just a case of using the GrailsApplication bean to get hold of the Spring ApplicationContext and from there you can use one of a few methods to resolve the message code.

But Don’t Pass an Empty List

There’s a potential gotcha in that you can’t pass an empty list to the getMessage methods:

appCtx.getMessage("message.code", [], "default message", locale)

fails with an error something like:

Caused by: groovy.lang.MissingMethodException: No signature of method:
     org.codehaus.groovy.grails.commons.spring.
     GrailsWebApplicationContext.getMessage()
 is applicable for argument types:
 (java.lang.String, java.util.ArrayList,
     java.lang.String, java.util.Locale)
 values: [test.message, [], default message, en_GB]

But this will work

appCtx.getMessage("message.code",
                  null,
                  "default message",
                  locale)

so will this

appCtx.getMessage("message.code",
                  new Object[0],
                  "default message",
                  locale)

and this

appCtx.getMessage("message.code",
                  [] as Object[],
                  "default message",
                  locale)

Do You Really Need to?

Having attempted this a few times I’ve found that it’s important I ask myself the question “Should I be accessing message bundles outside the controller”. Often you can’t avoid it – maybe you need to send an email or write to an internationalised log file. Other times, and this is especially true in domain objects, it’s best to pass message codes around and delegate the lookup to a piece of code that knows the user’s locale. Since the locale may vary between requests you will be sure of using the correct value if you resolve messages in the controller.

As a rule, if the message I’m resolving is destined for a view I will always resolve the message in the GSP.

Advertisement

6 thoughts on “Resolving i18n Messages Outside GSPs and Controllers in Grails

    • Hi Yuval, did you create the code in a service (in the services directory). If you did then the grailsApplication object should be injected by the container.

      If you didn’t then that will be your problem!

      If you need to access the grailsApplication outside of an autowired bean then you’ll have to get it from the spring application context directly, otherwise you can set your bean up using the Spring DSL and wire it up manually (more here).

      Dave

    • This won’t be relevant anymore for you, but anyway, I am doing it as follows:

      ApplicationContext applicationContext = (ApplicationContext) ServletContextHolder.getServletContext().getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT);

      applicationContext.getMessage(“long_live_slash_msg”, null, Locale.ITALY);

  1. Pingback: Blog bookmarks 09/13/2010 « My Diigo bookmarks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s