'Rails model using only default locale
- 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:
- http://guides.rubyonrails.org/i18n.html
- Access translation file (i18n) from inside rails model
- Rails 3 translations within models in production
- http://www.eq8.eu/blogs/10-translating-locales-for-rails-model-errors
- https://lingohub.com/frameworks-file-formats/rails5-i18n-ruby-on-rails/
- Change locale at runtime in Rails 3
Solution 1:[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
Solution 2:[2]
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: [email protected], 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?
Solution 3:[3]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Deepak Mahakale |
| Solution 2 | Deepak Mahakale |
| Solution 3 | Ken Ratanachai S. |
