Update 1:
我发现如果您不需要担心 i18n 和应用程序文本的翻译,februaryInk 的答案非常接近正确。如果你把has_many :child_model
下您的所有验证,验证将以正确的顺序显示。然而,full_messages
似乎没有使用区域设置文件来翻译模型或属性名称,因此如果您需要翻译错误消息(我确实这样做),我的答案似乎仍然是一个不错的解决方案。
更新2:
在发布第一次更新后刚刚意识到我可以简化生成的代码messages
通过删除使用更新 1 中的发现进行排序的部分来列出很多内容,并只保留进行翻译的部分。这是我的新解决方案,它是我的更新 1 和原始解决方案的组合。有关的所有其他信息config/locales/xx.yml
and config/application.rb
对于此更新的解决方案,文件仍然与原始解决方案相同。
应用程序/模型/parent_model.rb
...
validates :name, # validations hash
validates :description, # validations hash
validates :others, # validations hash
has_many :child_models
accepts_nested_attributes_for :child_models
...
应用程序/模型/child_model.rb
...
validates :nested_1, # validations hash
validates :nested_2, # validations hash
...
应用程序/helpers/application_helper.rb
messages = resource.errors.messages.keys.map {|value| error_message_attribute(resource, value) + I18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join
private
def error_message_attribute(resource, symbol)
if symbol.to_s.split(".").length > 1
model_name, attribute_name = symbol.to_s.split(".")
model_class = model_name.singularize.camelize.constantize
model_class.model_name.human + I18n.t('space') + model_class.human_attribute_name(attribute_name).downcase
else
resource.class.human_attribute_name(symbol)
end
end
更新结束
我对我的进行了一些更改error_messages
函数于application_helper.rb
现在一切都按我想要的方式工作:主表单验证错误位于顶部,嵌套表单验证错误位于其下方,除了将嵌套表单错误移至主表单错误下外,错误的顺序不会改变。
我的解决方案是改变messages =
线路输入error_messages
如下所示并添加一个私有帮助器方法。 (这可能应该分为几个部分,以便于阅读和理解,但我在控制台中构建了它以获得我想要的内容,然后直接从那里粘贴)。
应用程序/helpers/application_helper.rb
messages = Hash[resource.errors.messages.keys.map.with_index(1) { |attribute, index| [attribute, [index, attribute.match(/\./) ? 1 : 0]] }].sort_by {|attribute, data| [data[1], data[0]]}.collect { |attributes| attributes[0]}.map {|value| error_message_attribute_name(resource, value) + I18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join
private
def error_message_attribute_name(resource, symbol)
if symbol.to_s.split(".").length > 1
model_name, attribute_name = symbol.to_s.split(".")
model_class = model_name.singularize.camelize.constantize
model_class.model_name.human + I18n.t('space') + model_class.human_attribute_name(attribute_name).downcase
else
resource.class.human_attribute_name(symbol)
end
end
该解决方案也应该适用于其他其他语言环境,因为我使用了I18n
得到所有的名字。您还必须添加以下内容:
配置/语言环境/en.yml
en:
space: " "
这样,模型和属性名称就可以在单词之间有或没有空格的语言中正确处理(我需要支持的第一个语言环境是中文,单词之间没有空格)。例如,如果您确实需要支持中文,您可以使用以下命令:
配置/语言环境/zh.yml
zh:
space: ""
如果您不必支持这种情况,则所有实例I18n.t('space')
可以替换为" "
。模型和属性名称也可以翻译为,但同样,如果您不需要支持英语以外的语言环境,则无需执行任何操作(尽管您可以使用en.yml
文件来更改显示的模型或属性的名称)。
作为一个例子使用en.yml
使用常见的作者/书籍示例更改显示的名称:
配置/语言环境/en.yml
en:
activerecord:
models:
author: "writer"
book: "manuscript"
attributes:
author:
name: "non de plume"
book:
name: "title"
published: "year"
本例中默认,没有上面的添加en.yml
, 将会:
- 名称不能为空。
- 书名不能为空。
- 出版的书不能为空。
但有了上面的补充en.yml
这将是:
- 羽毛名称不能为空。
- 稿件标题不能为空。
- 稿件年份不能为空。
当然,如果你有一个zh.yml
文件中包含适当的翻译,其中的任何内容都会显示出来。
如果您确实需要支持多个区域设置,请不要忘记将以下内容添加到config/application.rb
(这部分只是进行了表面测试,可能还需要一些额外的配置):
配置/应用程序.rb
config.i18n.available_locales = [:zh, :en]
config.i18n.default_locale = :en