globalize
gem is a great solution to add translations to your ActiveRecord
models. You can install it adding this to your Gemfile
:
gem 'globalize', '~> 5.0.0'
If you're using Rails 5
you will also need to add activemodel-serializers-xml
gem 'activemodel-serializers-xml'
Model translations allow you to translate your models' attribute values, for example:
class Post < ActiveRecord::Base
translates :title, :text
end
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => גלובאלייז2 שולט!
After you defined your model attributes that need to be translated you have to create a translation table, through a migration. globalize
provides create_translation_table!
and drop_translation_table!
.
For this migration you need to use up
and down
, and not change
. Also, in order to run this migration successfully, you have to define the translated attributes in your model first, like shown above. A proper migration for the previous Post
model is this:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string, text: :text
end
def down
Post.drop_translation_table!
end
end
You may also pass options for specific options, like:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table! title: :string,
text: { type: :text, null: false, default: "Default text" }
end
def down
Post.drop_translation_table!
end
end
In case you already have any existing data in your needing translation columns, you can easily migrate it to the translations table, by adjusting your migration:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
Make sure you drop the translated columns from the parent table after all your data is safely migrated. To automatically remove the translated columns from the parent table after the data migration, add the option remove_source_columns
to the migration:
class CreatePostsTranslationTable < ActiveRecord::Migration
def up
Post.create_translation_table!({
title: :string,
text: :text
}, {
migrate_data: true,
remove_source_columns: true
})
end
def down
Post.drop_translation_table! migrate_data: true
end
end
You may also add new fields to a previously created translations table:
class Post < ActiveRecord::Base
# Remember to add your attribute here too.
translates :title, :text, :author
end
class AddAuthorToPost < ActiveRecord::Migration
def up
Post.add_translation_fields! author: :text
end
def down
remove_column :post_translations, :author
end
end