ActiveModel::Errors 中的编码问题
Encoding issues in ActiveModel::Errors
I18n 从 utf-8 格式的 yml 中读取,translate 将从 utf-8 转换为 utf-8。
我的遗留代码严重依赖于 ActiveModel::Errors.full_messages,
例如,
# note: the message is not utf-8 encoding
validates_length_of :title,:maximum => 2,:message => 'abc'.encode("shift_jis")
在视图中,它使用:
item.errors.full_messages.each do |msg|
end
错误将类似于:
I18n.t(:title) + " " + 'abc'
其实在full_message函数中,真正的源代码是这样的:
def full_message(attribute, message)
return message if attribute == :base
attr_name = attribute.to_s.tr('.', '_').humanize
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
I18n.t(:"errors.format", {
default: "%{attribute} %{message}",
attribute: attr_name,
message: message
})
end
现在的问题是:%{attribute}是utf-8,%{message}不是utf-8,所以调用full_message会报错。
我能想到的解决方案有几种:
1) 将错误消息更改为 utf-8(还有很多其他非 utf-8 的字符串),因此我必须到处处理 utf-8 和非 utf-8 的组合在源代码中,并在它们组合在一起时进行适当的转换。
2) 找到一种枚举错误消息的方法(类似于full_messages),但实现方式不同。我试图查看 ActiveModel::errors 的 API,但找不到内部 API 以便我可以列举错误。
3) 改变 I18n.t 默认行为,使其 return 成为非 utf-8。
4) 改变 ActiveModel::Errors.full_messages 所以它 return 是非 utf-8.
第二个选项实际上是最好的选项,但我不确定如何像 full_messages 一样枚举错误消息。我找不到任何 public API 到 return 错误的内部数据结构?
最后两个选项需要注入 ruby 库,我不知道是否可行。
请给我一些提示。谢谢。
您可以更改 ruby(和 rails)中几乎所有内容的行为。
只需在 config/initializers 中创建一个新的初始化文件,内容如下:
#monkeypatch_i18n.rb
(i don't know the exact path of active_model/errors.full_messages)
module ActiveModel
module Errors
def full_messages
#new logic
end
end
end
这会覆盖默认方法。
此致,
卷麻.
编辑:
一个更干净的解决方案可能是:
#lib/monkey_patch_i18n.rb
module ActiveModel
module Errors
def full_messages
#new logic
end
end
end
#config/initializers/init_i18n.rb
require "#{Rails.root}/lib/monkey_patch_i18n.rb"
I18n 从 utf-8 格式的 yml 中读取,translate 将从 utf-8 转换为 utf-8。
我的遗留代码严重依赖于 ActiveModel::Errors.full_messages,
例如,
# note: the message is not utf-8 encoding
validates_length_of :title,:maximum => 2,:message => 'abc'.encode("shift_jis")
在视图中,它使用:
item.errors.full_messages.each do |msg|
end
错误将类似于:
I18n.t(:title) + " " + 'abc'
其实在full_message函数中,真正的源代码是这样的:
def full_message(attribute, message)
return message if attribute == :base
attr_name = attribute.to_s.tr('.', '_').humanize
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
I18n.t(:"errors.format", {
default: "%{attribute} %{message}",
attribute: attr_name,
message: message
})
end
现在的问题是:%{attribute}是utf-8,%{message}不是utf-8,所以调用full_message会报错。
我能想到的解决方案有几种:
1) 将错误消息更改为 utf-8(还有很多其他非 utf-8 的字符串),因此我必须到处处理 utf-8 和非 utf-8 的组合在源代码中,并在它们组合在一起时进行适当的转换。
2) 找到一种枚举错误消息的方法(类似于full_messages),但实现方式不同。我试图查看 ActiveModel::errors 的 API,但找不到内部 API 以便我可以列举错误。
3) 改变 I18n.t 默认行为,使其 return 成为非 utf-8。
4) 改变 ActiveModel::Errors.full_messages 所以它 return 是非 utf-8.
第二个选项实际上是最好的选项,但我不确定如何像 full_messages 一样枚举错误消息。我找不到任何 public API 到 return 错误的内部数据结构?
最后两个选项需要注入 ruby 库,我不知道是否可行。
请给我一些提示。谢谢。
您可以更改 ruby(和 rails)中几乎所有内容的行为。
只需在 config/initializers 中创建一个新的初始化文件,内容如下:
#monkeypatch_i18n.rb
(i don't know the exact path of active_model/errors.full_messages)
module ActiveModel
module Errors
def full_messages
#new logic
end
end
end
这会覆盖默认方法。
此致, 卷麻.
编辑: 一个更干净的解决方案可能是:
#lib/monkey_patch_i18n.rb
module ActiveModel
module Errors
def full_messages
#new logic
end
end
end
#config/initializers/init_i18n.rb
require "#{Rails.root}/lib/monkey_patch_i18n.rb"