【问题标题】:Inheriting Rails i18n validation error messages in the subclass在子类中继承 Rails i18n 验证错误消息
【发布时间】:2013-02-15 00:37:41
【问题描述】:

我的理解

假设我有一个带有方便验证的类,例如:

User < ActiveRecord::Base
    validates :username, :format => {/regex/}, :message => :name_format
end

在这种情况下,我可以使用i18n 使错误消息可翻译,方法是在我的/config/locals/en.yml 中包含以下内容:

en:
    activerecord:
        errors:
            models:
                user:
                    attributes:
                        username:
                            name_format: 'has the way-wrong format, bro!'

这很好,通常非常方便。

我想知道的:

我的问题是:当我有继承自 User 的子类时会发生什么:

UserSubclassOne < User
    # extra stuff
end
UserSubclassTwo < User
    # extra stuff
end
...
UserSubclassEnn < User
    # extra stuff
end

现在的问题是 Rails 找不到翻译 user_subclass_one.attributes.username.name_format

它抱怨:

translation missing:
en.activerecord.errors.models.user_subclass_one.attributes.username.name_format

我希望 Rails 在 en.yml 中搜索字符串时会查找 UserSubclassOneUser 的层次结构,然后注意它何时被“命中”,但是(除非我做了什么可怕的错误)显然这不会发生。

一个明显的解决方案是将en.yml.en.errors.models 中的数据复制为useruser_subclass_oneuser_subclass_two 等,但我的Rails-sense 告诉我这是非常错误的。

各位,有什么想法吗?

潜在并发症:

User 定义在一个 gem MyGem 中,它包含在 Rails 引擎中 MyEngine 包含在完整的 Rails 应用程序 MyApp 中,它定义了 UserSubclassOne, ..., UserSubclassEnn .不过我认为这并不重要,因为验证是在MyGem::User 中运行的,这是en.yml 文件所在的位置——只是想让人们知道以防万一。

终极问题/解决方案:

所以问题出在命名空间上。回想一下MyApp(定义UserSubclassOne)使用MyGem(定义User)。原来User实际上在命名空间MyGem中(不一定总是这样),所以User开头的完整声明行不是:

User < ActiveRecord::Base

而是

MyGem::User < ActiveRecord::Base

.

当 i18n gem 查找类层次结构时,它会注意到这个命名空间并搜索 my_gem/user,而不是简单地搜索 usermy_gem.usermy_gem: user 等。

因此我不得不将我的 en.yml 文件更改为: /config/locals/en.yml:

en:
    activerecord:
        errors:
            models:
                my_gem/user:
                    attributes:
                        username:
                            name_format: 'has the way-wrong format, bro!'

还有宾果游戏!

【问题讨论】:

    标签: ruby-on-rails validation inheritance i18n-gem rails-i18n


    【解决方案1】:

    所以问题出在命名空间上。回想一下MyApp(定义UserSubclassOne)使用MyGem(定义User)。原来User实际上在命名空间MyGem中(不一定总是这样),所以User开头的完整声明行不是:

    User < ActiveRecord::Base
    

    而是

    MyGem::User < ActiveRecord::Base
    

    .

    当 i18n gem 查找类层次结构时,它会注意到这个命名空间并搜索my_gem/user,而不是简单地搜索usermy_gem.usermy_gem: user 等。

    因此我不得不将我的 en.yml 文件更改为: /config/locals/en.yml:

    en:
        activerecord:
            errors:
                models:
                    my_gem/user:
                        attributes:
                            username:
                                name_format: 'has the way-wrong format, bro!'
    

    还有宾果游戏!

    【讨论】:

    • 迟到的谢谢。我一直在拔头发。我知道这是与命名空间相关的,但如果没有这个帮助,我无法加载错误。 Rails Engine 规范几乎没用。他们完全忽略了这个相当重要的细节。
    【解决方案2】:

    根据 i18n 的 Rails Guides 关于 Error Message Scopes (5.1.1) 的 Active Record 验证错误消息,您尝试执行的操作应该有效:

    考虑一个对 name 属性进行验证的 User 模型,如下所示:

    class User < ActiveRecord::Base
      validates :name, :presence => true
    end
    

    <...>

    当您的模型另外使用继承时,将在继承链中查找消息。

    例如,您可能有一个继承自 User 的 Admin 模型:

    class Admin < User
      validates :name, :presence => true
    end
    

    然后 Active Record 将按以下顺序查找消息:

    activerecord.errors.models.admin.attributes.name.blank
    activerecord.errors.models.admin.blank
    activerecord.errors.models.user.attributes.name.blank
    activerecord.errors.models.user.blank
    activerecord.errors.messages.blank
    errors.attributes.name.blank
    errors.messages.blank
    

    这样,您可以在模型继承链以及属性、模型或默认范围的不同点为各种错误消息提供特殊翻译。

    所以,在你的情况下,假设你的类看起来像这样:

    app/models/user.rb

    User < ActiveRecord::Base
      validates :username, :format => {/regex/}, :message => :name_format
    end
    

    app/models/user_subclass.rb

    UserSubclass < User
      validates :username, :format => {/regex/}, :message => :name_format
    end
    

    你的 config/locales/en.yml 看起来像:

    en:
      activerecord:
        errors:
          models:
            user:
              attributes:
                username:
                  name_format: 'has the way-wrong format, bro!'
    

    那么在UserSubClass 上搜索验证的消息应该是:

    activerecord.errors.models.user_sublcass.attributes.username.name_format # fail
    activerecord.errors.models.user_sublcass.name_format                     # fail
    activerecord.errors.models.user.attributes.username.name_format          # success
    activerecord.errors.models.user.name_format
    # ...
    

    假设您的模型文件和 yaml 文件看起来与上面的相似,那么您提到的潜在并发症可能是问题所在,但显然我无法确定。

    【讨论】:

    • +1 供参考!我会继续尝试看看是我搞砸了还是 Rails 没有按承诺行事。解决后,如果合适,我会将此答案标记为已接受。
    • 所以事实证明主要问题确实是“潜在的并发症”。 UserClass 的正确键应该是 my_gem/user_class(而不是简单的 user_class 甚至 my_gem.user_class)。
    • 说得好!您能否将此详细信息添加为您的问题的编辑,以供其他有类似问题的人参考?另外,您能否将最终解决方案放入您的问题中(并接受此答案),或者将其放入您自己的答案中并接受。
    • 会的,保罗!感谢您的温柔刺激;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 2011-05-08
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    相关资源
    最近更新 更多