【问题标题】:Grails i18n from property files backed up by a DB?来自数据库备份的属性文件的 Grails i18n?
【发布时间】:2011-11-28 14:43:58
【问题描述】:

我想找到一种情况,我可以使用由数据库备份的 i18n 属性文件?

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

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

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

【问题讨论】:

标签: grails internationalization


【解决方案1】:

在你的项目中加入一个新的领域类:

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中。通过在我们的自定义实现中定义这个实例,我们仍然可以使用旧的实现(因此以通常的方式查找消息)。

【讨论】:

  • 非常感谢您的示例代码!对我来说,这是我不知道的事情的组合。 resources.groovy 的配置还是有点困难。为了完全理解,您能否详细说明它的配置?更具体..messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) { basenames = "WEB-INF/grails-app/i18n/messages" }
  • 我将发布您的建议的实施解决方案,您能否快速查看代码并告诉我一切是否正常。我在运行您的示例时遇到了小错误。但也许我错过了什么!谢谢!
  • 我更新了回复,因此您对resources.groovy中的更改有更多详细信息。
  • 您知道在 basenames 属性中添加通配符的方法吗?我们有多个属性文件。将它们全部输入是没有问题的,但是有一个通配符会很好。你知道这是否可用?
  • 这条线到底是什么意思? messageBundleMessageSource = ref("messageBundleMessageSource")
【解决方案2】:

我不确定我知道你的意思

使用数据库备份的 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 bean 的默认实现替换为您的实现,方法是将以下内容添加到resources.groovy

messageSource(DBMessageSource)

【讨论】:

  • 我正在尝试将两者结合起来,所以如果在属性文件中找不到代码,我想在 db 表中查找它们。这使用户能够在需要时修改某些特定字段。因此 95% 的字段将在属性文件中,5% 在 db 表中。
  • 好的,那么你需要一个 MessageSource 的实现,它首先检查属性文件,然后检查数据库
【解决方案3】:

在@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
    }

}

【讨论】:

    【解决方案4】:

    看看https://github.com/goeh/grails-i18n-dbhttps://github.com/halfbaked/grails-localizations。两者都提供了一个 GUI 来管理本地化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多