Rails:Rails4列挙型でi18nを使用する方法


回答:


52

特定のパターンも見つからなかったので、次のように追加しました。

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

任意の.ymlファイルに。それから私の見解では:

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

5
私は似たようでしたが、私は下に置く{locale}.activerecord.attributes.{model}.{attribute}と書いたt_enum(model, enum, value)列挙型の翻訳は、ラベルの翻訳に隣接するだろうように、ヘルパーメソッドを
クリス・ベック

77

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"

3
ドロップダウンでこれを使用する場合(つまり、単一の値を表示しない場合)、どのように処理しますか?
tirdadc 2017年

6
@tirdadc次のようなドロップダウンを処理できます:<%= f.select :status, User.statuses.keys.collect { |status| [User.human_enum_name(:status, status), status] } %>
Repolês

3
+1良い答え。これはビューの懸念事項であり、属性名を複数形にしないように、ビューヘルパーメソッドとして使用できるように調整しました。gist.github.com / abevoelker / fed59c2ec908de15acd27965e4725762次のようなビューで呼び出しますhuman_enum_name(@user, :status)
Abe Voelker

1
Repolêsごとに、ドロップダウンのベースモデルに別のクラスメソッドを追加することもできますself.human_enum_collection(enum_name)。コードは次のようになります send(enum_name.to_s.pluralize).keys.collect { |val| [human_enum_name(enum_name, val), val] }
armchairdj

32

ビューは次のとおりです。

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

そしてここにロケールファイルがあります:

en:
  activerecord:
    attributes:
      profile:
        genders:
          male: Male
          female: Female
          trans: Trans

1
しかし、この場合、単一レコードの翻訳を取得するにはどうすればよいですか?.human_attribute_name('genders.male')動作しないため
Stiig 2​​016

ありがとう、私の場合は魅力のように機能します!
マティス2017

私は、これらの目的のために軽量の宝石を作ったgithub.com/shlima/translate_enum
Aliaksandr

30

国際化を他の属性と同じように保つために、ここに示すように、ネストされた属性の方法に従いました。

クラスがある場合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}")

1
これは視覚的に魅力的ですが、フォームヘルパーactiverecord.attributes.<fieldname>label翻訳であるというレールの慣習を破ります
Chris Beck

5
:@ChrisBeck規則がRailsの国際化ガイドの説明は以下の表示されますguides.rubyonrails.org/...
danblaker

私の経験では、これはroleキーを使用しなくても機能します。ネストcoordinatorしてteacher真下に置くことができuserます。
Ryan CrispinHeneise20年

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

6

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])

4

これらの目的でTranslateEnumgemを使用してみてください

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 

1
この宝石も使用しています。私たちが評価したすべてのオプションの中で最もクリーンなアプローチを採用しており、十分に維持されています。
cseelus 2018年

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

これは、アクティブレコード、モンゴイド、またはゲッター/セッターを備えたその他のクラスで機能します。

https://github.com/viniciusoyama/translated_attribute_value


3

Rails 5のRepolêsAliaksandrの回答を組み合わせて、列挙型属性から単一の値または値のコレクションを変換できる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) %>

2

enum_helpgemを試してください。その説明から:

ActiveRecord :: Enum機能がI18nおよびsimple_formで正常に機能するように支援します。


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"

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

@user.roleそれが主な問題なので、どうですか。
コード-MonKy 2017年

最も簡単で、クリーンでエレガントな方法。
ファビアンウィンクラー

5
AnyModel.human_attribute_name(:i_dont_exist)=>「私は存在し
ませ

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

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

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

次に、selectで使用します。 my_something_list


0
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.enum(definitions)
    defind_i18n_text(definitions) if definitions.delete(:_human)
    super(definitions)
  end

  def self.defind_i18n_text(definitions)
    scope = i18n_scope
    definitions.each do |name, values|
      next if name.to_s.start_with?('_')
      define_singleton_method("human_#{name.to_s.tableize}") do
        p values
        values.map { |key, _value| [key, I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{key}")] }.to_h
      end

      define_method("human_#{name}") do
        I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{send(name)}")
      end
    end
  end
end


en:
  activerecord:
    enums:
      mymodel:
        my_somethings:
           my_enum_value: "My enum Value!"

enum status: [:unread, :down], _human: true
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.