Translate model nested attribute validation message
Asked Answered
J

3

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 ?

Jackquelinejackrabbit answered 4/8, 2014 at 11:13 Comment(0)
J
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.

Jackquelinejackrabbit answered 4/8, 2014 at 16:34 Comment(0)
A
-1

Try this:

en:
  activerecord:
    errors:
      models:
        identity:
          attributes:
            identity:
              blank: 'Your new error message here'
Andros answered 4/8, 2014 at 11:48 Comment(1)
That translates the error message ok, but I want to translate the attribute name.Jackquelinejackrabbit
G
-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

Gamester answered 4/8, 2014 at 12:39 Comment(3)
are you sure? I get can not load translations from ...: #<Psych::SyntaxError: (...): did not find expected key while parsing a block mapping at line 126 column 13>. I don't think that's valid yaml.Jackquelinejackrabbit
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 :(Jackquelinejackrabbit
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.Jackquelinejackrabbit

© 2022 - 2024 — McMap. All rights reserved.