Mobility gem v1.0.5如何通过locale/fallthrough访问器验证模型翻译
Mobility v1.0.5 版本分Locale字段校验实现
核心逻辑
Mobility 默认会把翻译字段的校验错误挂载在虚拟属性(比如通用的:name属性)上,不会自动拆分映射到独立的locale访问器(比如:name_en、:name_de)。要实现错误精准对应到每个独立locale字段,只需要结合locale_accessors、fallthrough_accessors的插件特性,直接把校验规则绑定到分语言的独立访问器上——这样校验触发时,错误会天然存入对应属性的错误列表,完全匹配要求的ActiveModel::Errors结构。
配置步骤
1. 初始化Mobility核心插件
在初始化文件中明确启用所需插件,避免默认行为的干扰:
# config/initializers/mobility.rb Mobility.configure do |config| # 生成分语言独立访问器 name_en/name_de 等 config.plugins[:locale_accessors].enable # 启用空值跨语言兜底的fallthrough访问能力 config.plugins[:fallthrough_accessors].enable # 启用AR集成能力 config.plugins[:active_record].enable # 选用键值对存储作为默认翻译后端 config.default_backend = :key_value end
2. 模型中分Locale绑定校验规则
在模型中定义翻译字段后,遍历所有应用启用的可用locale,为每个locale对应的独立访问器编写校验规则,不要将校验直接绑定在虚拟的通用翻译属性上:
class Category < ApplicationRecord translates :name, type: :string # 遍历启用的locale逐一生成独立校验 I18n.available_locales.each do |locale| attr_name = "name_#{locale}".to_sym # 直接在分语言访问器上定义校验,错误会自动关联到对应属性 validates attr_name, uniqueness: { case_sensitive: false }, length: { maximum: 255 } end end
效果验证
对应测试场景,提前在数据库中存在一条name_en = 'Cat. 1'的已有记录时:
c = Category.new(name_en: 'Cat. 1', name_de: 'Kat. 1') c.valid? # => false # 输出错误结构完全匹配预期 c.errors.messages # => {:name_en=>["has already been taken"]} c.errors.details # => {:name_en=>[{:error=>:taken, :value=>"Cat. 1"}]}
在视图层直接读取错误列表即可生成要求的展示效果:
- Name (en): 已被占用
- Name (de): 校验通过
v1.0.5版本专属注意事项
- 该版本中
locale_accessors插件不会自动拆分虚拟翻译属性上的校验规则,直接在通用:name属性上编写的校验错误,始终会挂载在:name键下,无法生成按locale拆分的错误结构,必须逐locale在独立访问器上定义校验。 - 启用fallthrough访问器时,注意区分「当前locale的原始输入值」和「fallthrough获取的其他locale兜底值」,编写校验时优先判断原始输入是否为空,避免fallthrough的值被误判为当前locale的输入触发错误校验。
内容的提问来源于stack exchange,提问作者phlegx
相关产品推荐
相关产品推荐

