Grails i18n来自DB备份的属性文件?

时间:2011-11-28 14:43:59

标签: grails internationalization

我试图得到一个情况,我可以使用i18n属性文件备份数据库?

所以对于某些标准的东西,我想使用属性文件,但有些字段必须是最终用户可编辑的,所以我打算在数据库中使用i18n。所以真正的组合会很棒。如果在属性文件中找不到i18n代码,则在DB中进行查找。

知道如何解决这个问题吗?我看过帖子Grails i18n From Database but Default Back To File

但问题没有真正的答案,还有其他任何关于如何解决这个问题的建议?

4 个答案:

答案 0 :(得分:5)

将新的域类放入项目中:

class Message {
    String code
    Locale locale
    String text
}

将以下行添加到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"
    }
}

将以下类添加到src/groovy文件夹中:

class DatabaseMessageSource extends AbstractMessageSource {

    def messageBundleMessageSource

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

现在grails将尝试解析消息包中的消息。如果它不可用,它将从数据库中查找。您可以添加一些错误处理,但如果所有消息至少在一个地方都可用,则此版本可以正常工作。

有关详细信息,请参阅http://graemerocher.blogspot.com/2010/04/reading-i18n-messages-from-database.html


resources.groovy中所做更改的一些细节:

在此文件中,您可以定义可注入的groovy类,只需定义与resources.groovy中定义的名称相同的变量即可包含该类。例如。在此文件中,有messageSourcemessageBundleMessageSource,您可以将其包含在任何控制器或服务文件中。如果定义了此变量,则会创建括号中的类的实例。

在这种情况下,我们会覆盖常规messageSource以使用我们的自定义实现DatabaseMessageSource。因此I18n函数message现在将使用我们的自定义实现。

由于我们的自定义实现需要检查message.properties - 文件,我们会在第二个bean中保留原始消息源。通过在我们的自定义实现中定义此实例,我们仍然可以使用旧的实现(因此以通常的方式查找消息)。

答案 1 :(得分:1)

我不确定我知道你的意思

  

使用数据库备份的i18n属性文件

但是,如果您只是想要使用数据库表(而不是.properties文件)来解析消息密钥,那么您可以通过编写自己的MessageSource接口实现来实现此目的

class DBMessageSource implements MessageSource {
  String getMessage(MessageSourceResolvable resolvable, Locale locale) {
   // IMPLEMENT ME
  }

  String getMessage(String code, Object[] args, Locale locale) {
   // IMPLEMENT ME    
  }

  String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
   // IMPLEMENT ME    
  }
}

然后通过将以下内容添加到messageSource

,只需将resources.groovy bean的默认实现替换为您的实现
messageSource(DBMessageSource)

答案 2 :(得分:0)

在@crudolf的回答后,我实现了以下方法来实现我的目标。

class DatabaseMessageSource extends AbstractMessageSource {
    // the message bundle resource that holds all of the messages
    def messageBundleMessageSource

    // the default locale used when there is no correct results found
    // if a visitor (x) comes along with an unknown locale in the DB
    // then this locale will be used as fallback!
    Locale fallbackLocale = new Locale("nl", "NL")

    protected MessageFormat resolveCode(String code, Locale locale) {
        // first try to find the message in the messagebundles
        MessageFormat messageFormat = messageBundleMessageSource.resolveCode(code, locale)

        if(!messageFormat) {
            // no message found so lets find one in the database
            def message = Message.findByCodeAndLocale(code, locale) ?: Message.findByCodeAndLocale(code, fallbackLocale)
            if (message) {
                // found one create a message format!
                messageFormat = new MessageFormat(message.text, message.locale)
            } else {
                // not found! create a standard message format
                messageFormat = new MessageFormat(code, locale)
            }
        }
        return messageFormat
    }

}

答案 3 :(得分:0)