40

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!

user229044
  • 232,980
  • 40
  • 330
  • 338
TomDogg
  • 3,803
  • 5
  • 33
  • 60

3 Answers3

54

The solution is to NOT 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 default key: "inclusion"

for reference, check out the respective Rails guide:

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

jan
  • 1,160
  • 1
  • 9
  • 11
TomDogg
  • 3,803
  • 5
  • 33
  • 60
  • I always forget the defaults for the activerecord error messages (and I need them every few months or so), thankfully Google helps me find this answer over and over again! – Justus Romijn Jun 14 '12 at 15:12
  • => The better way to approach this problem is the answer by @iain below. – Chris Hough Nov 02 '14 at 21:18
  • 2
    This doesn't address *why* OPs solution didn't work: the translation was interpreted when the project _initialized_, which happens every request in dev, but only once at boot in prod. To support multiple languages they must be interpreted at _runtime_, which @iain's solution addresses. TomDogg's solution only works if you can use the same default translation in every case, which isn't always the best UX. – Woahdae Oct 30 '15 at 22:28
  • For error messages, [this is a better link](https://guides.rubyonrails.org/i18n.html#error-message-interpolation) – niborg Jan 15 '20 at 19:36
18

You can use symbols, to specify translations:

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

And it will be translated with a particular scope. See the I18n guide for more details.

iain
  • 16,204
  • 4
  • 37
  • 41
  • The part following ":message =>" should be something along the lines of: I18n.t('activerecord.errors.models.[model_name].attributes.[attribute_name]') – TomDogg Dec 15 '10 at 17:28
  • Nope, this doesn't work. I suspect that in Rails, it is not possible to have translations in models (since they only get loaded once). – TomDogg Dec 15 '10 at 17:48
  • 4
    Use a Symbol as I did and place the translation in the appropriate place (as indicated in the guide). Don't call I18n.t here. My example is right. – iain Dec 15 '10 at 18:03
  • I forgot to mention: I'm on Rails 2.3. I suppose your solution works for Rails 3, but not for Rails 2.3? – TomDogg Dec 16 '10 at 08:52
  • It works on Rails 2.2 and upwards and I know for sure, because I contributed to that part. – iain Dec 16 '10 at 12:28
  • Thanks for getting back - It's strange b/C When I do as you say, I still get "undefined method `select_whatever' for model...", which leads me to think Rails doesn't accept a symbol in that place... – TomDogg Dec 16 '10 at 12:45
  • 1
    what if I need to send a variable to the i18n string. e.g. "the value %{value} is invalid" ? – MegaTux Aug 12 '15 at 16:12
5

OK, iain answer works, but I took very long time to figure out where should I put the :select_whatever.

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

OK your en.yml should look like this:

en:
  errors:
    messages:
      select_whatever: "error!!"
Sam YC
  • 10,725
  • 19
  • 102
  • 158