如何在Rails 4枚举中使用i18n
Rails 4 Active Record Enums很好,但是用i18n翻译的正确模式是什么?
我没有find任何具体的模式,所以我只是补充说:
en: user_status: active: Active pending: Pending... archived: Archived
到一个任意的.yml文件。 那么在我看来:
I18n.t :"user_status.#{user.status}"
从Rails 5开始,所有的模型都将inheritance自ApplicationRecord
。
class User < ApplicationRecord enum status: [:active, :pending, :archived] end
我使用这个超类来实现翻译枚举的通用解决scheme:
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def self.human_enum_name(enum_name, enum_value) I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") end end
然后我在我的.yml
文件中添加翻译:
en: activerecord: attributes: user: statuses: active: "Active" pending: "Pending" archived: "Archived"
最后,要获得我使用的翻译:
User.human_enum_name(:status, :pending) => "Pending"
这里是一个观点:
select_tag :gender, options_for_select(Profile.gender_attributes_for_select)
这里是一个模型(你可以将这段代码实际上移入一个助手或者一个装饰器)
class Profile < ActiveRecord::Base enum gender: {male: 1, female: 2, trans: 3} # @return [Array<Array>] def self.gender_attributes_for_select genders.map do |gender, _| [I18n.t("activerecord.attributes.#{model_name.i18n_key}.genders.#{gender}"), gender] end end end
这里是locale文件:
en: activerecord: attributes: profile: genders: male: Male female: Female trans: Trans
为了保持国际化与任何其他属性类似,我遵循嵌套属性的方式,你可以看到这里 。
如果你有一个class级User
:
class User < ActiveRecord::Base enum role: [ :teacher, :coordinator ] end
像这样的一个yml
:
pt-BR: activerecord: attributes: user/role: # You need to nest the values under model_name/attribute_name coordinator: Coordenador teacher: Professor
您可以使用:
User.human_attribute_name("role.#{@user.role}")
模型:
enum stage: { starting: 1, course: 2, ending: 3 } def self.i18n_stages(hash = {}) stages.keys.each { |key| hash[I18n.t("checkpoint_stages.#{key}")] = key } hash end
地点:
checkpoint_stages: starting: Saída course: Percurso ending: Chegada
而在视图(.slim)上:
= f.input_field :stage, collection: Checkpoint.i18n_stages, as: :radio_buttons
详细阐述user3647358的答案,您可以非常接近您在翻译属性名称时习惯的内容。
区域文件:
en: activerecord: attributes: profile: genders: male: Male female: Female trans: Trans
通过调用I18n#t来翻译:
profile = Profile.first I18n.t(profile.gender, scope: [:activerecord, :attributes, :profile, :genders])
我为此创造了一个gem。
http://rubygems.org/gems/translated_attribute_value
添加到你的gemfile:
gem 'translated_attribute_value'
如果您有用户的状态字段:
pt-BR: activerecord: attributes: user: status_translation: value1: 'Translation for value1' value2: 'Translation for value2'
在你看来,你可以这样打电话:
user.status_translated
它与积极的logging,mongoid或任何其他类与getter / setters:
结合Repolês和Aliaksandr的答案,对于Rails 5,我们可以构build两种方法,允许您从enum属性中翻译单个值或一组值。
在.yml
文件中设置翻译:
en: activerecord: attributes: user: statuses: active: "Active" pending: "Pending" archived: "Archived"
在所有模型inheritance的ApplicationRecord
类中,我们定义了一个处理单个值转换的方法,另一个处理数组的方法是调用它:
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def self.translate_enum_name(enum_name, enum_value) I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") end def self.translate_enum_collection(enum_name) enum_values = self.send(enum_name.to_s.pluralize).keys enum_values.map do |enum_value| self.translate_enum_name enum_name, enum_value end end end
在我们看来,我们可以翻译单一的价值观:
<p>User Status: <%= User.translate_enum_name :status, @user.status %></p>
或者是枚举值的整个集合:
<%= f.select(:status, User.translate_enum_collection :status) %>
试试enum_help gem。 从其描述:
帮助ActiveRecord ::枚举function与I18n和simple_form正常工作。
t_enum
是我使用的t_enum
帮助器方法。
<%= t_enum(@user, :status) %>
enum_helper.rb :
module EnumHelper def t_enum(inst, enum) value = inst.send(enum); t_enum_class(inst.class, enum, value) end def t_enum_class(klass, enum, value) unless value.blank? I18n.t("activerecord.enums.#{klass.to_s.demodulize.underscore}.#{enum}.#{value}") end end end
user.rb :
class User < ActiveRecord::Base enum status: [:active, :pending, :archived] end
en.yml :
en: activerecord: enums: user: status: active: "Active" pending: "Pending..." archived: "Archived"
该模型:
class User < ActiveRecord::Base enum role: [:master, :apprentice] end
语言环境文件:
en: activerecord: attributes: user: master: Master apprentice: Apprentice
用法:
User.human_attribute_name(:master) # => Master User.human_attribute_name(:apprentice) # => Apprentice
另一种方式,我发现使用模型的关注点更方便一些
关心 :
module EnumTranslation extend ActiveSupport::Concern def t_enum(enum) I18n.t "activerecord.attributes.#{self.class.name.underscore}.enums.#{enum}.#{self.send(enum)}" end end
阳明:
fr: activerecord: attributes: campaign: title: Titre short_description: Description courte enums: status: failed: "Echec"
查看:
<% @campaigns.each do |c| %> <%= c.t_enum("status") %> <% end %>
不要忘记在你的模型中增加关注:
class Campaign < ActiveRecord::Base include EnumTranslation enum status: [:designed, :created, :active, :failed, :success] end
你可以简单地添加一个帮手:
def my_something_list modes = 'activerecord.attributes.mymodel.my_somethings' I18n.t(modes).map {|k, v| [v, k]} end
并通常设置:
en: activerecord: attributes: mymodel: my_somethings: my_enum_value: "My enum Value!"
然后使用它与您的select: my_something_list
尝试使用TranslateEnum gem来达到这些目的
class Post < ActiveRecord::Base enum status: { published: 0, archive: 1 } translate_enum :status end Post.translated_status(:published) Post.translated_statuses @post = Post.new(status: :published) @post.translated_status
我更喜欢application_helper中的一个简单的助手
def translate_enum(object, enum_name) I18n.t("activerecord.attributes.#{object.model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{object.send(enum_name)}") end
然后在我的YML文件中:
fr: activerecord: attributes: my_model: my_enum_plural: pending: "En cours" accepted: "Accepté" refused: "Refusé"