Upcoming Globalize feature: an alternative way of storing model translations
As the title of Saimons blog post mentions this feature deals with a different implementation of model translations.
With Globalize you'd say, for example:
def Page <ActiveRecord::Base translates :title end
Now, traditionally, your database schema would - regardless of how many languages you'd have to deal with in your application - include a
pages table with one column named
title, right? This column would hold the base_language translations of titles. All other translations would go into a separate table named
globalize_translations - a central storage table for all translations of all your "translates-ed" attributes.
For example, the page
title value "I18n the easy way" would be stored directly in the
pages table (assuming that English is the
base_language of our app). The German translation "I18n leicht gemacht" of this title would go into the
globalize_translations table however.
This approach has some obvious advantages like that the translation of your application is entirely separated from the rest of your application/data. But there are some serious drawbacks also, most importantly being less flexible due to the necessity to
JOIN in the
globalize_translations table. For example, Globalize hasn't been able to support the standard
:selectbehaviour of ActiveRecord (which in turn breaks, ahem, ... disables other ActiveRecord default stuff like
Enter Saimons Alternative Model Translations ...
Saimons approach turns things around from a traditional Globalize perspective. His alternative implementation of
- requires you to store your translations directly in the model tables on the one hand but
- allows you to leverage all the
ActiveRecord::Base::findfunctionality you're used to without any restrictions on the other hand (such as not being able to use :include and :select in the traditional approach)
As Saimon told me you'll be able to switch this behaviour on by putting Globalize::DbTranslate.keep_translations_in_model = true in your environment.rb. But you'll also be able to overwrite this per model, in class scope: self.keep_translations_in_model = true.
To store the translation data directly in the model table you have to have a column per supported language per translated attribute. That is, for the
title attribute above, we'd have three db columns when there are three languages supported:
class CreatePages <ActiveRecord::Migration def self.up create_table :pages do |t| t.column :title, :string t.column :title_de, :string t.column :title_fr, :string end end end
It's been noted that this might get a bit cumbersome as soon as you've more than very few attributes to translate and very few languages to support. (On the other hand, one might come up with some automation support based on
ActiveRecord::Migrations to manage this kind of stuff.) Also, what if you want to add new languages in an entirely dynamic way, e.g. through a web interface? Well, of course, as always ... peoples mileages vary and there's no silverbullet to whatever job you're trying to get done.
What Saimons approach is buying you is the removal of a beforehand necessary
JOIN. Depending on your situation - that's probably quite a lot.
Also, as a side-effect of this all the translations will be pre-loaded with your models, so switching the
locale won't result in an additional database hit.
I'd love to see your comments though!