2
  • I have a model with custom validations. I return the validation errors to the view as JSON using AJAX.
  • I need to show the error messages with the right locale but the messages show in English (default) for each locale.
  • When I return I18n.locale itself instead of the message (for troubleshooting) it shows "en" no matter what is the set locale.
  • I18n in controllers or views works as expected, this problem occurs only in the model.
  • The only configuration that I've made regarding locale is setting the default locale in the application config and setting the locale before each action in the application controller.
  • Another thing that I've noticed is that when I use root_path without providing the locale, it's using the default locale instead keeping the current locale like it should. I think those issues are connected

Edit:

  • When I print the locale parameter in controller#create, I get nil. For some reason I don't have the locale parameter at all.

model file:

validate :relevant_date_time

def relevant_date_time
    errors.add(:date_error, I18n.t("validations.date_error")) unless date_time_is_relevant?
end

application_controller:

before_action :set_locale

def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
end

Am I forgetting something?

Information I reviewed:

Community
  • 1
  • 1
Max Dubinin
  • 214
  • 3
  • 20

4 Answers4

1

I18n locale in controllers/views only applies to the action's context, it does not change your app's default locale setting, which is where your model is getting its locale from (as you have discovered).

The step you are missing is to pass the locale into your model from your action, which you could do by adding an attr_accessor :locale to your model, and then passing the locale through when creating/updating it in your controller:

# e.g. app/controllers/users_controller.rb
# user_params = { email: test@mail.com, password: 12345678 }
User.new(user_params.merge(locale: I18n.locale))

Then in your validation method you would be able to access the current locale with locale, so all you need to do is pass it to I18n.t:

errors.add(:date_error, I18n.t("validations.date_error", locale: locale)) unless date_time_is_relevant?
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
omnikron
  • 2,211
  • 17
  • 30
1

If you set locale at application_controller.rb, it will only have scope in all controllers and views NOT in models.

So you have to set locale inside model too. Same as you did at controller.

At controller

Model.new(params.merge(locale: I18n.locale))

Inside model

attr_accessible :locale      

before_validation() do
  I18n.local = locale
end

def relevant_date_time
  errors.add(:date_error, I18n.t("validations.date_error")) unless date_time_is_relevant?
end
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
forchetan01
  • 136
  • 10
  • It didn't work. Still shows that the locale is en. For some reason I don't have the locale parameter in my controller at all! Do you know why this could happen? – Max Dubinin Nov 07 '16 at 11:47
0

Solved by adding the following method in application controller:

  def default_url_options(options={})
    { locale: I18n.locale }
  end
Max Dubinin
  • 214
  • 3
  • 20
0

For anyone who is struggling with I18n in model validation, the solution could be not including any custom message keys in the models but

en:
  activerecord:
    errors:
      models:
        model_name:
          attributes:
            attr_name:
              taken: << or whatever error message like blank, too_long, too_short etc.

Credit t: https://stackoverflow.com/a/4453350/267693

Ken Ratanachai S.
  • 3,307
  • 34
  • 43