继承Rails i18n子类中的验证错误消息

时间:2013-02-15 00:37:41

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

我的理解

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

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在UserSubclassOne中搜索字符串时会查找Useren.yml的层次结构,然后注意它何时获得'点击',但是(除非我做了一些可怕的错误)显然这不会发生。

一个明显的解决方案是复制en.yml.en.errors.modelsuseruser_subclass_oneuser_subclass_two等数据,但我的Rails-sense告诉我这是错误的

任何想法,伙计们?

潜在的并发症:

User在包含在Rails引擎MyGem中的gem MyEngine中定义,该引擎包含在定义{{1}的完整Rails应用MyApp中},...,UserSubclassOne。我不认为这应该很重要,因为验证是在UserSubclassEnn中运行的,这是MyGem::User文件所在的位置 - 只是想让人们知道,以防万一。

终极问题/解决方案:

事实证明问题是命名空间。回想一下en.yml(定义{{​​1}})使用MyApp(定义{{​​1}})。事实证明UserSubclassOne实际上在命名空间MyGem中(这不一定总是如此),因此User开头的完整声明行不是:

User

而是

MyGem

当i18n gem查找类层次结构时,它会注意到此命名空间并搜索User,而不仅仅是User < ActiveRecord::Base MyGem::User < ActiveRecord::Base my_gem/user等。< / p>

因此我不得不将我的user文件更改为: my_gem.user

my_gem: user

和宾果!

2 个答案:

答案 0 :(得分:6)

事实证明问题是命名空间。回想一下MyApp(定义{{​​1}})使用UserSubclassOne(定义{{​​1}})。事实证明MyGem实际上在命名空间User中(这不一定总是如此),因此User开头的完整声明行不是:

MyGem

而是

User

当i18n gem查找类层次结构时,它会注意到此命名空间并搜索User < ActiveRecord::Base ,而不仅仅是MyGem::User < ActiveRecord::Base my_gem/useruser等。< / p>

因此我不得不将我的my_gem.user文件更改为: my_gem: user

en.yml

和宾果!

答案 1 :(得分:2)

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

  

考虑具有name属性验证的User模型,如下所示:

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

&LT; ...剪断...&GT;

     

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

     

例如,您可能拥有从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
     

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

因此,在您的情况下,假设您的类看起来像这样:

应用/模型/ user.rb

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

应用/模型/ 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文件看起来与上面的相似,那么您提到的潜在复杂问题可能就是问题,但显然我无法确定。