问题 Grails i18n从数据库但默认返回文件


以下 这篇博客文章 我启用了我的应用程序从数据库加载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(代码,语言环境)但导致编译错误。而且我很难跟踪Grails正在使用的AbstractMessageSource的实现来查看源代码。

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

messageSource(DatabaseMessageSource)

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

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

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


12966
2017-11-11 21:39


起源

你有没有这个工作? - Marco


答案:


我建议在一个新的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,否则你可能会错过插件中的一些重要消息。


11
2017-11-20 19:41





您可以扩展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"
    }
 }

1
2017-11-15 08:35



不,使用ReloadableResourceBundleMessageSource也不起作用。它甚至没有进入我设置断点的DatabaseMessageSource类。呈现的唯一消息是消息taglib用法中提供的默认消息。 - Gregg
我猜想不知何故,resources.groovy中的连线不好,即没有覆盖默认的messageSource配置。还要检查resources.groovy的配置,我的原始配置是错误的,即使用 beans {..} 并且不要忘记com.mycompany ....或者你使用的任何前缀 - fixitagain
关于这个问题的任何消息? - fixitagain


AbstractMessageSource中的resolveCode(代码,语言环境)是一种抽象方法,因此您无法调用它。尝试扩展 ResourceBundleMessageSource会 要么 ReloadableResourceBundleMessageSource 代替。


0
2017-11-13 23:35



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


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

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


0
2017-11-14 22:14



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


我强烈建议你使用 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上即时生成。它真的很容易使用。

看看,这是值得的。


0
2017-11-21 20:23



你为什么要投票? - Quentin