sebastyuiop
sebastyuiop

Reputation: 534

Rails 3 translations within models in production

I'm trying to translate an app into Japanese and everything was going smoothly until I put it into production.

As cache_classes is now true any translation within a model reverts to the default locale.

I know I'm probably supposed to target the translations directly in the yml file but I'm not sure how I would do that for the following simplified code:

class TimeseriesForecast < ActiveRecord::Base

  @@field_names = {
   :location_name => I18n.t('forecast_timeseries.location_name'),
   :local_date_time => I18n.t('forecast_timeseries.local_date_time'),
   :zulu_date_time => I18n.t('forecast_timeseries.zulu_date_time'),
   :temp_mean => I18n.t('forecast_timeseries.temp_mean')
  }

end

Many thanks

Upvotes: 1

Views: 3401

Answers (3)

ivanxuu
ivanxuu

Reputation: 852

Don't use I18n.t or translate method in your models. You can do this instead:

In your model

Use something like this to add internationalized errors to the name attribute of your model (Check documentation: ActiveModel/Errors/method-i-add):

self.errors.add(:name, :your_error_key) 
  # The error key could be something like :wrong_name

NOTE: Sometimes you won't even need to add errors with errors.add method. For example if you add validations in your model with somethind like this:

validates :name, presence: true

Rails will add an error with the key :blank (the key depens on the validation type). In other words rails internally will issue self.errors.add(:name, :blank)

In your locale

Then in your locale.jp.yml can use any of this (just one):

activerecord.errors.models.[model_name].attributes.[attribute_name]
activerecord.errors.models.[model_name]
activerecord.errors.messages
errors.attributes.[attribute_name]
errors.messages

In your case replace [model_name] with timeseries_forecast and [attribute_name] with your_error_key

For example:

en:
  errors:
    messages:
      your_error_key: "Your error message in english"

Upvotes: 2

Jens
Jens

Reputation: 1398

Your I18n.t() call is evaluated at compile time since you are defining class variables, not instance variables. You need to put your call to I18n.t where they will be evaluated at runtime.

But if you want to translate ActiveRecord field names, use human_attribute_name and provide your translations via YML. You do not need to manually provide translations, Rails handles it all for you automatically.

The respective documentation is at http://guides.rubyonrails.org/i18n.html Chapter 5.1.

Upvotes: 5

jimworm
jimworm

Reputation: 2741

Don't think you're improving performance by caching the names in the class. Make it a method instead.

class TimeseriesForecast < ActiveRecord::Base
  def self.field_names
    { :location_name => I18n.t('forecast_timeseries.location_name'),
      :local_date_time => I18n.t('forecast_timeseries.local_date_time'),
      :zulu_date_time => I18n.t('forecast_timeseries.zulu_date_time'),
      :temp_mean => I18n.t('forecast_timeseries.temp_mean') }
  end
end

# usage
TimeseriesForecast.field_names

Better yet, return just the actual fields and do the translation in the view, if you're gonna be strict MVC about it (some Rails methods - like collection_select - make it harder to do that though, hence the suggestion above).

Upvotes: 0

Related Questions