Recently I needed to store text data in multiple languages at the same time. After a quick googling I found a globalize gem which does exactly what I need.
But there are couple issues with it:
- doesn’t support rails 5 yet;
- creates additional tables to store translated data;
- requires you to reference models in migration, which is anti-pattern.
It’s somewhat OK to live with 2 and 3, but not with 1 if you are on rails 5.
That’s why I’ve created another solution and extracted it into a gem.
The idea is very simple: save all translation data in one field. It’s possible to do so even with serializable attribute, but much better is to use
jsonb type in PostgreSQL 9.4. It’s indexed and you can query it just like any data.
ActiveRecord supports jsonb since 4.2 so you can work with those fields just like with hashes.
So, let’s save translatable text data under a key, representing locale:
Now, with a very little abstraction you can do this:
Also, it’s very easy to manage multiple languages in a single form if you treat them as nested attributes:
Together with nested_form_fields you can add/delete translations dynamically in a single form.
This very simple idea illustrates yet another use case for
jsonb type. Don’t be afraid of it.
However, it requires you to write raw SQL queries, like this:
But, imo this is better than joins with additional tables.