如何在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:

https://github.com/viniciusoyama/translated_attribute_value

结合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é"