简体   繁体   中英

In Grails, how can I get a ConfigObject of messages.properties for locale?

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.

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

I know this is old, but I came here looking to do the exact same thing. Using LocaleContextHolder to get the desired locale is a good starting point, although I decided to use RequestContextUtils . In my implementation, I wanted to use java's own locale resolution strategy. So here goes (currently using grails 2.1.2):

// Controller
import org.springframework.web.servlet.support.RequestContextUtils
import grails.converters.JSON


class I18nController {
    def strings() {
    ResourceBundle clientMessages = ResourceBundle.getBundle("com.example.ClientMessages",
        RequestContextUtils.getLocale(request),
        Thread.currentThread().contextClassLoader)
    render clientMessages as JSON
    }
}

When you serialize this thing using the default JSON marshaller, it's not what you want. So add this to your BootStrap.groovy inside the init closure:

    // JSON Marshaller to serialize ResourceBundle to string table.
    JSON.registerObjectMarshaller(ResourceBundle) { bundle ->
        def returnObject = [:]
        bundle.keys.each {
            returnObject."${it}" = bundle.getString(it)
        }
        returnObject
    }

And finally, put the resources you want to send to the javascript client side in your classpath. In my example, these would go in src/java/com/example/ClientMessages.properties.

size.small=Small
size.wide=Wide
size.large=Large

In the client, going to myapp/i18n/strings you will see the JSON like this:

{"size.small":"Small","size.wide":"Wide","size.large":"Large"}

So with this solution, you put all and only the strings you want to send to the javascript side for lookup, and put everything else in the grails i18n folder. One caveat is that the strings here are not available to g:message and vice versa. If anyone can figure out a solution to single out one basename in i18n for this purpose, I'd like to see it.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM