如何在Rails 4枚举中使用i18n

时间:2014-04-03 03:25:24

标签: ruby-on-rails-4 enums

Rails 4 Active Record Enums很棒,但使用i18n进行翻译的正确模式是什么?

15 个答案:

答案 0 :(得分:51)

从Rails 5开始,所有模型都将继承自ApplicationRecord

class User < ApplicationRecord
  enum status: [:active, :pending, :archived]
end

我使用这个超类来实现翻译枚举的通用解决方案:

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"

答案 1 :(得分:42)

我也没有找到任何特定的模式,所以我只是添加:

en:
  user_status:
    active:   Active
    pending:  Pending...
    archived: Archived

到任意.yml文件。然后在我看来:

I18n.t :"user_status.#{user.status}"

答案 2 :(得分:29)

以下是一个观点:

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

答案 3 :(得分:20)

为了使国际化与我遵循嵌套属性方式的任何其他属性相似,您可以看到here

如果您有课程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}")

答案 4 :(得分:7)

型号:

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

答案 5 :(得分:5)

详细说明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])

答案 6 :(得分:4)

尝试将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 

答案 7 :(得分:3)

我为此创造了一个宝石。

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

它适用于活动记录,mongoid或任何其他具有getter / setter的类:

https://github.com/viniciusoyama/translated_attribute_value

答案 8 :(得分:3)

结合RepolêsAliaksandr的答案,对于Rails 5,我们可以构建2个方法,允许您从枚举属性转换单个值或值集合。

.yml文件中设置翻译:

en:
  activerecord:
    attributes:
      user:
        statuses:
          active: "Active"
          pending: "Pending"
          archived: "Archived"

在所有模型继承的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) %>

答案 9 :(得分:2)

试试enum_help宝石。从其描述:

  

帮助ActiveRecord :: Enum功能与I18n和simple_form一起正常工作。

答案 10 :(得分:2)

这是我使用的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"

答案 11 :(得分:2)

模特:

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

答案 12 :(得分:1)

我更喜欢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é"

答案 13 :(得分:0)

另一种方式,我发现使用模型中的问题更方便

关注:

module EnumTranslation
  extend ActiveSupport::Concern

  def t_enum(enum)
    I18n.t "activerecord.attributes.#{self.class.name.underscore}.enums.#{enum}.#{self.send(enum)}"
  end
end

YML:

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

答案 14 :(得分:0)

您只需添加帮助程序:

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!"

然后将其与您的选择:my_something_list

一起使用