12

I have a nested attribute on which I perform presence validation. I am trying without success to provide translations for the attribute name that is returned in the full error message text.

The model is called Identity and contains an attribute called identity The model is nested within another with a has_many relationship.

A typical error message is currently returned like this

Identities identity can't be blank

I want to translate the attribute (by default Identities identity) into something else.

I have

en:
  activerecord:
    models:
      identity:
        identity: "whatever"

If I do this, I get an error

I18n::InvalidPluralizationData (translation data {:identity=>"whatever"} can not be used with :count => 1):

I have tried to add pluralisation data to this by altering the above to

en:
  activerecord:
    models:
      identity:
        identity:
          one: "one"
          other: "other"

This changes the error to

I18n::InvalidPluralizationData (translation data {:identity=>{:one=>"one", :other=>"other"}} can not be used with :count => 1):

I have also tried many instead of other without difference.

I have spent a few hours trying to make this work, having read other questions on Stack Overflow and elsewhere, without success. What is the correct way to write translations for attribute names ?

RAJ
  • 9,697
  • 1
  • 33
  • 63
starfry
  • 9,273
  • 7
  • 66
  • 96

3 Answers3

14

Adding some debugging output to the human_attribute_name method reveals what the i18n path should be.

The example has a user model with a has_many :identities relationship. The desired attribute is identity, an attribute of the Identity model, of which the User model has many.

I looked in gems/activemodel-4.0.1/lib/active_model, file translation.rb. The human_attribute_name method looks up the following path:

:"activerecord.attributes.user/identities.identity"

It also specifies the following as defaults, which are fallback translations:

:"activerecord.attributes.user/identities.identity"
:"activerecord.attributes.identities.identity"
:"attributes.identity"
"Identities identity"
"Identity"

the last two are strings, the first will match if none of the paths represented as symbols match available translations. So, in the case of no translations, the output will be the string "Identities identity" (the other string, "Identity" will never be used).

So, any of the following translation paths will work:

activerecord.attributes.user/identities.identity
activerecord.attributes.identities.identity
attributes.identity

The paths are tried in that order and the first to match is the one that will be used.

starfry
  • 9,273
  • 7
  • 66
  • 96
-1

Try this:

en:
  activerecord:
    errors:
      models:
        identity:
          attributes:
            identity:
              blank: 'Your new error message here'
Matt Gibson
  • 14,616
  • 7
  • 47
  • 79
-1

You can just provide translated values in front of db attribute names.

en:
  activerecord:
    attributes:
      identity: # this is model name
        identity: "translated attribute name"

You may want to read more about active model attribute localization

RAJ
  • 9,697
  • 1
  • 33
  • 63
  • are you sure? I get `can not load translations from ...: #`. I don't think that's valid yaml. – starfry Aug 04 '14 at 12:48
  • doesn't work for me. I tried in rails console `I18n.t 'activerecord.errors.attributes.identity.identity'` and that returns the expected value (so my yml is correct) but the attribute isn't translating in the error message :( – starfry Aug 04 '14 at 13:23
  • `activerecord.attributes.identity.identity` doesn't work either. After hacking the activemodel code to see what it's doing, I discovered that the requied yml is `activerecord.attributes.identities.identity`. I will provide more detail in an answer. – starfry Aug 04 '14 at 15:59