I18n in model validations: Possible or not?

Hi there,

I have the following validation in a model:

validates_inclusion_of :whatever, :in => [true, false], :message =>
I18n.t(‘please_select_whatever’)

It seems that the translation does not work in production mode: in all
languages it’s always the english translation that gets diplayed
(probably because I set english as the default locale in my app…?).

So I am assuming that we can’t translate validations in models, because
models get loaded only once - when the server is booted (and then, the
default locale would be applied).

Am I right? If yes, how would you solve this problem?

Thanks for your help!
Tom

On Wed, Dec 15, 2010 at 10:13 AM, Tom Ha [email protected] wrote:

So I am assuming that we can’t translate validations in models, because
models get loaded only once - when the server is booted (and then, the
default locale would be applied).

Am I right? If yes, how would you solve this problem?

Thanks for your help!
Tom

try passing the argument as a lambda function

:message =>lambda { I18n.t(‘please_select_whatever’) }

i havent try it but it makes sense

:message =>lambda { I18n.t(‘please_select_whatever’) }

Thanks for the suggestion - unfortunately, it doesn’t change the
outcome…

On Wed, Dec 15, 2010 at 11:16 AM, Marnen Laibow-Koser
[email protected]wrote:

Best,

since that is the default behavior i assumed ‘please_select_whatever’
is a
dynamic value taken from the model, if its not the case
everything should word without the need of doing the translation in the
model

Tom Ha wrote in post #968590:

:message =>lambda { I18n.t(‘please_select_whatever’) }

Thanks for the suggestion - unfortunately, it doesn’t change the
outcome…

Perhaps you should just have the validation routine generate the
translation key (in other words, leave off I18n.t), then apply the
translation in the view layer.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

then apply the
translation in the view layer.

Thanks… In that case, how could that be done if I have the following
partial, for the error messages?

<%= error_messages_for :whatever_model, :header_message => nil, :message
=> nil %>

Tom Ha wrote in post #968598:

then apply the
translation in the view layer.

Thanks… In that case, how could that be done if I have the following
partial, for the error messages?

<%= error_messages_for :whatever_model, :header_message => nil, :message
=> nil %>

I don’t think it can. You’d need to use the errors array instead.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Radhames Brito wrote in post #968604:

you are going to need to create a custom validation and add the field to
the
locales it seems

#211 Validations in Rails 3 - RailsCasts

I don’t see why.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Dec 15, 2010, at 6:13 AM, Tom Ha wrote:

So I am assuming that we can’t translate validations in models, because
models get loaded only once - when the server is booted (and then, the
default locale would be applied).

Am I right? If yes, how would you solve this problem?

In particular see the table in section “5.1.2 Error Message
Interpolation”

http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models

In particular see the table in section “5.1.2 Error Message
Interpolation”

Thanks, that helped. The following works:

In the model:

validates_inclusion_of :whatever, :in => [true, false], :message =>
I18n.t(‘activerecord.errors.models.my_model.attributes.whatever.please_select_whatever’)

In config/locales/en.yml:

en:
activerecord:
errors:
models:
my_model:
attributes:
whatever:
please_select_whatever: “Please select whatever.”

In the model:

validates_inclusion_of :whatever, :in => [true, false], :message =>

I18n.t(‘activerecord.errors.models.my_model.attributes.whatever.please_select_whatever’)

In config/locales/en.yml:

en:
activerecord:
errors:
models:
my_model:
attributes:
whatever:
please_select_whatever: “Please select whatever.”

Nope, this doesn’t work. I suspect it’s still the same problem: it seems
not possible to have translations in models (since they only get loaded
once).

It may work for the default “keys” (for “validates_presence_of :name”
the key would be “blank”), but not the custom ones.

you are going to need to create a custom validation and add the field to
the
locales it seems

We’ve done it in the Kete app (GitHub - kete/kete: Kete was developed by Horowhenua Library Trust and Katipo Communications Ltd. to build a digital library of Horowhenua material.), but I
can’t recall the trick. I’ll check with the guy that did it an see if
he has an answer for you…

Cheers,
Walter

It may work for the default “keys” (for “validates_presence_of :name”
the key would be “blank”), but not the custom ones.

To sum it up: The solution is NOT to include any custom message keys
in the models, like…

:message =>
I18n.t(‘activerecord.errors.models.my_model.attributes.whatever.please_select_whatever’)

The model will then apply the default message keys, for example
“:inclusion” in the case of “validates_inclusion_of”

…and in config/locales/en.yml you need to have:

en:
activerecord:
errors:
models:
my_model:
attributes:
whatever:
inclusion: “Please select whatever.” # see key:
“inclusion”

I’ll check with the guy that did it an see if he has an answer for you…

Thanks - why not, if there’s a better/more elegant trick than the
solution above (it works…).

Cheers,
Tom

That’s what I get for skimming…

We used lambda which I believe was already shown.

from Kete’s app/models/choice.rb:

validates_uniqueness_of :label, :message => lambda {
I18n.t(‘choice_model.must_be_unique’) }

Kieran, feel free to update with more info, if there are more details
to point out.

Cheers,
Walter

On Thu, Dec 16, 2010 at 9:07 AM, Walter McGinnis

Hey,

In order to get locales working at runtime, I made the ActiveRecord
validations call a proc (IIRC, similar to how Rails 3 does it now).

If you’re using a Rails gem, or Rails is vendored, and you don’t want
it to be lost when upgrading, put it in an all_extensions.rb
initializer, like I did here:

Regards
Kieran


Kieran Pilkington
http://twitter.com/k776 - http://k776.tumblr.com

Thanks for all the input!