views:

79

answers:

2

In Grails, I would like to get a ConfigObject reference to the loaded messages properties file for the current locale. Or some way to easily read in the messages properties (for the current locale) in it's entirety. I want to convert it to JSON and send it back to the client to be used to lookup strings via javascript.

In essence I want to do something like this:

def props = new java.util.Properties()
props.load(... the right message bundle ...);
def messages = new ConfigSlurper().parse(props)
render messages as JSON

I'm assuming there's a more graceful way to do this. The messageSource interface only allows you to get a message for a particular key. I want the entire resource bundle so I can convert it to JSON.

+1  A: 

The implementation type of MessageSource is org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource. Perhaps there are methods on this class (or one of it's parents), that will allow you to get a reference to the entire set of Properties.

The following looks like it might work (though I haven't tested it):

// Get a reference to the message Source either via dependency injection or looking-up
// the bean in the application context
def messageSource
Properties messages = messageSource.getProperties("messages.properties").properties
// Now convert the Properties instance to JSON using your favorite Java-JSON library

This is not a great solution as the getProperties(filename) method is protected, so you should not be able to call it, but you can because of a bug in Groovy. It also makes some implicit assumptions about the implementation type of mesageSource.

Don
like you said, it's probably not the best solution since you are making blind assumptions of the implementation behind the interface. Thanks for the answer!
mbrevoort
agreed, but sometimes you have to sacrifice some OO purity in order to get things done
Don
+1  A: 

I found a workable solution of just loading the properties directly from the proper messages properties bundle based on the current locale.

It looks like I can just load the file with a path relative to the root of the application. This worked for running locally both with the embedded tomcat and as a war ('grails run-app' and 'grails run-war') but I haven't tested deployed to a container to know if the path will be resolved properly.

Here's my test controller:

import grails.converters.*
import org.springframework.context.i18n.LocaleContextHolder as LCH 

class I18nController {

    def index = {
        def locale = LCH.getLocale().toString();
        def langSuffix = ( locale == "en" ) ? "" : "_${locale}" 
        def props = new java.util.Properties()
        props.load( new FileInputStream( "grails-app/i18n/messages${langSuffix}.properties" ) )
        render ( new ConfigSlurper().parse(props) ) as JSON
    }

}

Can be accessed like:

http://localhost:8080/myapp/i18n
http://localhost:8080/myapp/i18n?lang=es
http://localhost:8080/myapp/i18n?lang=en
mbrevoort
Are you sure this code is right? I'd expect to see `params.lang` referenced somewhere within the `index` closure
Don
the call to the LocaleContextHolder takes that into account already
mbrevoort