Translating model attribute name - ruby-on-rails

I'm trying to translate an attribute name in Rails (3.2) to something more human readable, specifically for error messages, but I keep getting the original DB column name. Here's my en.yml file
activerecord:
attributes:
user:
encrypted_password: "Password"
errors:
models:
user:
attributes:
encrypted_password:
blank: "can't be blank"
I also tried this as seen here
activerecord:
models:
user: Dude
attributes:
user:
encrypted_password: "Password"
The interesting thing is that the second translation (for errors) works, but not the first. What am I missing ?

Related

Error messages in nested attribute

I've three models called Account,User and AccountPermission.
I'm creating the Account via AccountPermission while creating user.
However, If a problem occurs related with Account :name, the system throws something like that below.
Account permissions account name has already been taken
So, I just need to fix this error message.
I've tried to add a message attribute to my validation. It is just appending to actual message.
I've also tried locale thing. Still just appending
en:
activerecord:
errors:
models:
account:
attributes:
name:
taken: 'bla bla'
As far as I see in ActiveModel. This message's structure comes from below
locale/en.yml in ActiveModel
en:
errors:
format: "%{attribute} %{message}"
So, Is there any way edit this message painless ? If I even delete the model name, It's enough.
Error message is concatenated from the error itself and the attribute name, which is account_permissions/account.name in the provided error.
You can add locale for your attribute names like so:
en:
activerecord:
attributes:
account: # this is model name
name: "Name"
or
en:
activerecord:
attributes:
account_permissions/account:
name: "Account name"

Rails custom validation error message not working

My understanding is that I can customize error messages in the localization files. I'm currently trying to customize the error message for an invalid username field on my User model:
User.rb
class User < ActiveRecord::Base
validates :username, length: { within: 3..25 },
format: /\A(?=.*[a-z])[a-z\d]+\Z/i,
uniqueness: true
en.yml (localization file)
en:
activerecord:
errors:
models:
user:
attributes:
username:
format: "CUSTOM MESSAGE!"
The error message I receive, however, is the default "is invalid" message (or "Username is invalid" if I get the full_messages version).
Have a look here. There is no format key in the errors/messages. You need to override the invalid key.
en:
activerecord:
errors:
models:
user:
attributes:
username:
invalid: "CUSTOM MESSAGE!"

Form validation message with aliased attribute name

I'm using Stripe within a model class. I have a strike_token attribute that I am validating presences of and creating a custom message like so:
validates :stripe_token, presence: { message: 'Please enter valid card info' }
When the form is submitted and not valid, the error message is, "Stripe token Please enter valid card info"
I don't want Stripe token in the error message. I have other validations as well that would be suited for the default, so I don't want to change the default error behavior.
It would be better if I could alias the Stripe token attribute to something like :card_info without actually having that as an attribute on the model.
So the message could be made to read, "Card info cannot be blank"
You can do as given below:
Just remove the :message part from validation.
# config/locales/en.yml
en:
activerecord:
attributes:
model_name:
stripe_token: ""
errors:
models:
model_name:
attributes:
stripe_token:
blank: "Card info cannot be blank!"
OR
# config/locales/en.yml
en:
activerecord:
attributes:
model_name:
stripe_token: "Card info"
errors:
models:
model_name:
attributes:
stripe_token:
blank: " cannot be blank!"
Replace model_name with your model name in small letters. Please check Fully custom validation error message with Rails for more details.
Update
# config/locales/en.yml
en:
activerecord:
attributes:
model_name:
stripe_token: "Card info"
Then use,
validates :stripe_token, presence: { message: ' cannot be blank!' }
Hope it helps :)

Translate Rails model association - not working

Anyone has some tips as how to translate model associations in Rails?
For example: I have a Person model, which can have many Phone. However, a Person needs to have at least one Phone. I'm not able to translate that validation. The best I could do was this:
validates_presence_of :phones, :message => "At least one phone is required."
And on my YAML, I replaced this line to omit the %{attribute}:
format: ! '%{message}'
This way only my message is displayed, and I avoid the un-translated field name to be displayed.
This is causing me a lot of headache, because some gems simply don't allow me to pass :message => "something describing the error", so I wanted to configure all the error messages through my YAML.
Also, with some models I'm able to translate their attributes, while with others I'm not. For example:
activerecord:
attributes:
additional_info:
account_manager: "Manager"
This works. I can see on my form "Manager". However, when this field has an error, Rails will display it as "Additional info account manager can't be blank".
I tried this:
activerecord:
errors:
models:
additional_info:
attributes:
account_manager: "Manager"
But no luck.
I did read the docs, but no clue on why it's happening.
Here are the valid key paths for Rails 4.1:
# Basic Attribute on Model
activerecord:
attributes:
#{model_class.model_name.i18n_key}:
#{attribute_name}:
"Localized Value"
# Attribute on Nested Model
activerecord:
attributes:
#{model_class.model_name.i18n_key}/#{association_name}:
#{attribute_name}:
"Localized Value"
#{association_name}:
#{attribute_name}:
"Fallback Localized Value"
So, given this model (which has the i18n_key of :person):
class Person
has_many :friends
end
You'd have these locale definitions:
activerecord:
attributes:
person:
first_name:
"My Name"
person/friends:
first_name:
"My Friend's Name"
friends:
first_name:
"A Friend's Name"
If your model is a namespace, such as:
class MyApp::Person
has_many :friends
end
the i18n_key becomes :my_app/person and your / key starts to wear out:
activerecord:
attributes:
my_app/person:
first_name:
"My Name"
my_app/person/friends:
first_name:
"My Friend's Name"
friends:
first_name:
"A Friend's Name"
Rails 3.2 has changed this behavior. The way I've posted before is deprecated.
Now, in order to translate associations, there is the need to add a slash (instead of nesting everything). So instead of this:
activerecord:
attributes:
person:
additional_info:
account_manager: "Manager"
The correct now is:
activerecord:
attributes:
person:
additional_info/account_manager: "Manager"
Also, I figured out that has_many associations are being translated differently from that. If you want to translate those, the following example may help:
activerecord:
attributes:
emails:
address: "E-mail field"
Instead of the model name, like I did above, you need to pass the association name, in this case emails.
Check this comment and pull request for more info:
https://github.com/rails/rails/commit/c19bd4f88ea5cf56b2bc8ac0b97f59c5c89dbff7#commitcomment-619858
https://github.com/rails/rails/pull/3859

Trouble on using the i18n gem with "resources of resources"

I am using Ruby on Rails 3.1 and I would like to know how to correctly handle internationalization related to "resources of resources". That is, ...
... in my config/routes.rb file I have:
resources :users do
resource :account
end
... in my app/models/users/account.rb file I have:
class Users::Account < ActiveRecord::Base
validates :firstname,
:presence => true
...
end
... in my config/locales/models/user/account/en.yml file I have:
en:
activerecord:
errors:
messages:
presence: "custom presence message - english"
... in my config/locales/models/user/account/it.yml file I have:
it:
activerecord:
errors:
messages:
presence: "custom presence message - italian"
The above code doesn't display in front end the "custom presence message" (it still displays the default RoR presence message: can not be blank). Furthermore if in my app/models/users/account.rb file I use:
class Users::Account < ActiveRecord::Base
validates :firstname,
:presence => { :message => t(:presence) } # Here I try to use the i18n helper method
...
end
I get the following error:
NoMethodError (undefined method `t' for #<Class:0x000001075bbc80>)
Why I get the NoMethodError?
Is the problem related to how I am organizing in directories my locale files? At this time (as stated in the official RoR guide) my file system is:
config/locales/defaults/en.yml
config/locales/defaults/it.yml
config/locales/models/user/en.yml
config/locales/models/user/it.yml
config/locales/models/user/account/en.yml
config/locales/models/user/account/it.yml
In few words, I would like to display my "custom presence message" only on validating "resources of resources" kind of Users::Account. How can I do that?
I also tried to state the following code in the config/locales/models/user/account/en.yml file
en:
activerecord:
errors:
models:
user:
account:
attributes:
firstname:
blank: "custom presence message - english"
but it doesn't work. Anyway the following works but I need different translations for different attributes (as I tried to state in the previous code example):
en:
activerecord:
errors:
messages:
blank: "custom presence message - english"
ok, due to this: https://github.com/rails/rails/issues/1402 last comment nested model look-up is removed
so try maybe something like
activerecord:
errors:
models:
users:
account:
attributes:
first_name:
blank: "You should fill up first name field to complete that"
and change inside :message hash to
I18n.t(:"activerecord.errors.models.users.account.attributes.first_name.blank")
and try avoid nested models ;-)
update:
after some debuging this will work:
activerecord:
errors:
models:
"users/account":
attributes:
first_name:
blank: "You should fill up first name field to complete that"

Resources