Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails i18n From Database but Default Back To File

Following this blog article I enabled my application to load i18n messages from the database. It works great. However, I don't want to manage all messages in the database. So I'd like to be able to say if I don't find the code in the database, then load it using the default mechanism.

Here is what I have:

class DatabaseMessageSource extends AbstractMessageSource {
  protected MessageFormat resolveCode(String code, Locale locale) {
    Message msg = Message.findByCodeAndLocale(code, locale)
    def format = null
    if (msg) {
      format = new MessageFormat(msg.text, msg.locale)
    }else{
      // What do I do here to grab it from the file
    }
    return format;
  }
}

I tried calling super.resolveCode(code, locale) but that resulted in compile errors. And I'm having a hard time tracking down the implementation of AbstractMessageSource that Grails is using by default to look at the source.

UPDATE: Thanks to doelleri I now realize what I need to do is something like extending the ResourceBundleMessageSource. Unfortunately, there are several issues with this approach. I have the following in my resources.groovy file:

messageSource(DatabaseMessageSource)

First of all, if I simply extend ResourceBundleMessageSource and override the resolveCode method, that method never gets called. So in my else block, calling super.resolveCode is moot.

I then attempted to just implement my DatabaseMessageSource class with all the code from ResourceBundleMessageSource but I'm apparently missing something in resources.groovy because the default bundles aren't getting wired up.

So at this point, I'm still lost on what I need to do. I want to first check the database. If the code doesn't exist, revert to the same default behavior as ResourceBundleMessageSource.

like image 656
Gregg Avatar asked Nov 11 '11 21:11

Gregg


2 Answers

I would propose to keep one bundle-message-source in a new bean and inject it into your DatabaseMessageSource.

resources.groovy:

// Place your Spring DSL code here
beans = {
    messageSource(DatabaseMessageSource) {
        messageBundleMessageSource = ref("messageBundleMessageSource")
    }    
    messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
        basenames = "WEB-INF/grails-app/i18n/messages"
    }
}

DatabaseMessageSource.groovy:

class DatabaseMessageSource extends AbstractMessageSource {

    def messageBundleMessageSource

    protected MessageFormat resolveCode(String code, Locale locale) {
         Message msg = Message.findByCodeAndLocale(code, locale)
         def format
         if(msg) {
             format = new MessageFormat(msg.text, msg.locale)
         }
         else {
             format = messageBundleMessageSource.resolveCode(code, locale)
         }
         return format;
    }
}

This way, in fallback solution, the message will be read from the appropriate messages_*.properties file, by just requesting it from one resource bundle message source. Note that you should use the PluginAwareResourceBundleMessageSource, otherwise you could miss some important messages from your plugins.

like image 183
Chris Avatar answered Nov 07 '22 02:11

Chris


You may extend ReloadableResourceBundleMessageSource (the original grails message bundle, which does not seem to be final) instead and then apply this code:

class DatabaseMessageSource extends ReloadableResourceBundleMessageSource {
  protected MessageFormat resolveCode(String code, Locale locale) {
    Message msg = Message.findByCodeAndLocale(code, locale)
    def format = null
    if (msg) {
      format = new MessageFormat(msg.text, msg.locale)
    }else{
      format = super.resolveCode(code,locale)
    }
    return format;
  }
}

You may also reconfigure your message resources in Resources.groovy:

 beans = {
    messageSource(com.mycompany.DatabaseMessageSource) {
        basename = "WEB-INF/grails-app/i18n/messages"
    }
 }
like image 35
fixitagain Avatar answered Nov 07 '22 04:11

fixitagain