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.
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.
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"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With