Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails i18n - How to translate enum of a model

I've got the following model:

class Person < ActiveRecord::Base
  enum gender: [:female, :male]
  ...
end

Then I added the selection of the gender to its form, like this:

<%= form_for ([@person]) do |f| %>
  ...
  <div class="form-group">
    <%= f.collection_radio_buttons :gender, Person.genders, :first, :first %>
  </div>
  ...
<% end %>

But instead of displaying the constant as a string I want to translate it to Portuguese.

I already tried to add it to the pt.yml file under people but didn't work.

pt:
 activerecord:
   attributes:
     female: Feminino
     male: Mascúlino

I know this question is very similar to How to use i18n with Rails 4 enums but that question is already marked as answered and I'm searching for a better and simpler solution...

Thank you for taking your time to help me :)

like image 904
jbatista Avatar asked Mar 30 '17 11:03

jbatista


1 Answers

After reading How to use i18n with Rails 4 enums answers more carefully I came to this solution:

  1. According rails guides - "In the event you need to access nested attributes within a given model, you should nest these under model/attribute at the model level of your translation file" -

the yml file should look like this:

pt:
 activerecord:
   attributes:
     person/gender:
       female: Feminino
       male: Mascúlino
  1. We need to create a method to return a translated enum since there isn't any method capable of translating an entire enum at once. Rails just has the method to translate a value given a key, i.e People.human_attribute_name("gender.female").

Ok, we'll create a new method but where should we put it?

I think Helpers are the best place to put it because I'm changing the enum values in order to easily attach them to the form collection, although most of the answers suggested to put it in the Models.

Now my person_helper.rb looks like this:

def human_attribute_genders
  Hash[Person.genders.map { |k,v| [k, Person.human_attribute_name("gender.#{k}")] }]
end

And my view:

<%= f.collection_radio_buttons :gender, human_attribute_genders, :first, :second %>

Pretty simple and it works just fine!

If anyone has any suggestion to improve my solution I would be happy to hear it from you :)

For example, I could extract the method to application_helper.rb like this:

def human_attribute_enum(model_name, enum_attr, attr_name)
  Hash[enum_attr.map { |k,v| [k, I18n.t("activerecord.attributes.#{model_name}/#{attr_name}.#{k}")] }]
end

But it'd require passing a lot of parameters in the view...

like image 81
jbatista Avatar answered Oct 19 '22 11:10

jbatista