Rails: How to use i18n with Rails 4 enums

后端 未结 16 2121
天涯浪人
天涯浪人 2020-11-28 04:10

Rails 4 Active Record Enums are great, but what is the right pattern for translating with i18n?

相关标签:
16条回答
  • 2020-11-28 04:39

    Combining the answers from Repolês and Aliaksandr, for Rails 5, we can build 2 methods that allow you to translate a single value or a collection of values from an enum attribute.

    Set up the translations in your .yml file:

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

    In the ApplicationRecord class, from which all models inherit, we define a method that handles translations for a single value and another one that handles arrays by calling it:

    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 
    

    In our views, we can then translate single values:

    <p>User Status: <%= User.translate_enum_name :status, @user.status %></p>
    

    Or the entire collection of enum values:

    <%= f.select(:status, User.translate_enum_collection :status) %>
    
    0 讨论(0)
  • 2020-11-28 04:40

    I've created a gem for this.

    http://rubygems.org/gems/translated_attribute_value

    Add to your gemfile:

    gem 'translated_attribute_value'
    

    If you have a status field for user:

    pt-BR:
      activerecord:
        attributes:
          user:
            status_translation:
              value1: 'Translation for value1'
              value2: 'Translation for value2'
    

    And in your view you can call like this:

    user.status_translated
    

    It works with active record, mongoid or any other class with getter/setters:

    https://github.com/viniciusoyama/translated_attribute_value

    0 讨论(0)
  • 2020-11-28 04:42

    Yet another way, I find it a bit more convenient using a concern in models

    Concern :

    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"
    

    View :

    <% @campaigns.each do |c| %>
      <%= c.t_enum("status") %>
    <% end %>
    

    Don't forget to add concern in your model :

    class Campaign < ActiveRecord::Base
      include EnumTranslation
    
      enum status: [:designed, :created, :active, :failed, :success]
    end
    
    0 讨论(0)
  • 2020-11-28 04:43

    You can simply add a helper:

    def my_something_list
      modes = 'activerecord.attributes.mymodel.my_somethings'
      I18n.t(modes).map {|k, v| [v, k]}
    end
    

    and set it up as usually:

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

    then use it with your select: my_something_list

    0 讨论(0)
  • 2020-11-28 04:45

    Starting from Rails 5, all models will inherit from ApplicationRecord.

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

    I use this superclass to implement a generic solution for translating enums:

    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
    

    Then I add the translations in my .yml file:

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

    Finally, to get the translation I use:

    User.human_enum_name(:status, :pending)
    => "Pending"
    
    0 讨论(0)
  • 2020-11-28 04:47

    The model:

    class User < ActiveRecord::Base
      enum role: [:master, :apprentice]
    end
    

    The locale file:

    en:
      activerecord:
        attributes:
          user:
            master: Master
            apprentice: Apprentice
    

    Usage:

    User.human_attribute_name(:master) # => Master
    User.human_attribute_name(:apprentice) # => Apprentice
    
    0 讨论(0)
提交回复
热议问题