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

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...

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,

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

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,

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

http://railscasts.com/episodes/211-validations-in-rails-3

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

http://railscasts.com/episodes/211-validations-in-rails-3

I don't see why.

Best,

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

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.

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"

We've done it in the Kete app (http://github.com/kete/kete), 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

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

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).

https://github.com/kete/kete/commit/5cd0e3fc728e76e88856e9dbec8d34639883924e

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:

https://github.com/kete/kete/blob/master/config/initializers/all_extensions.rb#L98-107

Regards
Kieran

Thanks for all the input!