【问题标题】:Grails i18n From Database but Default Back To FileGrails i18n 来自数据库但默认返回文件
【发布时间】:2011-11-11 21:39:09
【问题描述】:

this blog article 之后,我启用了我的应用程序以从数据库加载 i18n 消息。它工作得很好。但是,我不想管理数据库中的所有消息。所以我想说如果我在数据库中没有找到代码,然后使用默认机制加载它。

这是我所拥有的:

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;
  }
}

我尝试调用 super.resolveCode(code, locale) 但导致编译错误。而且我很难追踪 Grails 默认使用的 AbstractMessageSource 的实现来查看源代码。

更新:感谢 doelleri,我现在意识到我需要做的就是扩展 ResourceBundleMessageSource。不幸的是,这种方法存在几个问题。我的 resources.groovy 文件中有以下内容:

messageSource(DatabaseMessageSource)

首先,如果我只是扩展 ResourceBundleMessageSource 并覆盖 resolveCode 方法,则该方法永远不会被调用。所以在我的 else 块中,调用 super.resolveCode 没有实际意义。

然后我尝试使用来自 ResourceBundleMessageSource 的所有代码来实现我的 DatabaseMessageSource 类,但我显然在 resources.groovy 中遗漏了一些东西,因为默认包没有连接起来。

所以在这一点上,我仍然不知道我需要做什么。我想先检查一下数据库。如果代码不存在,则恢复为与 ResourceBundleMessageSource 相同的默认行为。

【问题讨论】:

  • 你做过这个工作吗?

标签: grails internationalization


【解决方案1】:

我建议在一个新 bean 中保留一个 bundle-message-source 并将其注入您的 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;
    }
}

这样,在备用解决方案中,消息将从适当的messages_*.properties 文件中读取,只需从一个资源包消息源请求它即可。请注意,您应该使用PluginAwareResourceBundleMessageSource,否则您可能会错过插件中的一些重要消息。

【讨论】:

    【解决方案2】:

    您可以改为扩展 ReloadableResourceBundleMessageSource(原始 grails 消息包,似乎不是最终的),然后应用此代码:

    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;
      }
    }
    

    您还可以在 Resources.groovy 中重新配置您的消息资源:

     beans = {
        messageSource(com.mycompany.DatabaseMessageSource) {
            basename = "WEB-INF/grails-app/i18n/messages"
        }
     }
    

    【讨论】:

    • 不,使用 ReloadableResourceBundleMessageSource 也不起作用。它甚至没有进入我设置断点的 DatabaseMessageSource 类。唯一呈现的消息是消息标记库使用中提供的默认消息。
    • 我猜想resources.groovy 中的布线并不好,即没有覆盖默认的messageSource 配置。还要检查resources.groovy的配置,我原来的配置是错误的,即使用beans {..}并且不要忘记com.mycompany....或者你使用的任何前缀
    【解决方案3】:
    AbstractMessageSource 中的

    resolveCode(code, locale) 是一个抽象方法,因此您将无法调用它。请尝试扩展 ResourceBundleMessageSourceReloadableResourceBundleMessageSource

    【讨论】:

    • 啊哈!谢谢。 ResourceBundleMessageSource 可能是我需要的。我会在早上测试它并报告。非常感谢。
    • 事实证明,简单地扩展 ResourceBundleMessageSource 是行不通的。方法resolveCode永远不会被调用,如果我尝试以与在实际类中编码的完全相同的方式实现它(我下载了源代码),它不会根据我正在做的事情正确连接它的所有捆绑信息在 resources.groovy 文件中。我已经更新了我的问题以反映这一点。
    【解决方案4】:

    虽然它不是特定于 Grails,但我们在 Griffon 创建了 CompositeResourceBundle 和 DelegatingResourceBundle 作为我们自己的 i18n 插件的一部分(源代码位于 http://svn.codehaus.org/griffon/plugins/griffon-i18n/trunk/src/main/griffon/plugins/i18n/)。

    ExtendedResourceBundleMessageSource 展示了如何使用这些类。

    【讨论】:

    • 谢谢 aalmiray。我真的需要尽可能恢复到默认的 Spring / Grails。您的代码看起来像是在自己处理加载包。我需要 Grails 以 grails 加载它们的方式加载包。我只需要添加首先在数据库中查找消息的功能。也许我现在太累了,无法得到它。但我也认为诀窍在于我如何在 resources.groovy 中定义我的 bean,这可能需要一个 grails 答案。
    【解决方案5】:

    我强烈建议您使用Copycopter (http://copycopter.com) 来管理 i18n 密钥内容。它将允许您的团队使用友好的界面轻松地即时更新密钥,并且您将能够根据需要设置默认值。这样,当需要更新密钥时,就不会有人来找您了。

    ThoughtBot 是一家强大的网络开发咨询公司,支持该产品。很结实。

    您的代码将如下所示:

    mail :to => member.email,
         :subject => I18n.translate("member_mailer.reminder_to_sign_in.#{underscored_number_of_days}.subject",
                                    :default => %{You have not signed in for #{humanized_number_of_days}})
    

    i18n 密钥是在您第一次使用时在 copytcopter 上即时生成的。它真的很容易使用。

    看看,值得。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 2014-12-24
      相关资源
      最近更新 更多