“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it. Currently working for InPay...”

Rob Lacey (contact@robl.me)
Senior Software Engineer, Brighton, UK

I18n Translations with a database backend

Having used Rails I18n translations in yaml for some time, we’ve recently started thinking about how users might want to customise content on the fly, without editing flat files and reloading our application. In my mind it should read from the database.

I found the Il8n Backend Database plugin, however it appears its not Rails 3 compliant yet and we can cope with and probably should build the interface for updating our own translations

https://github.com/dylanz/i18n_backend_database

It seems there was support for ActiveRecord in the i18n gem, but it has since been moved out into the i18n-active_record gem.

./Gemfile

gem 'i18n-active_record', 
  :git => 'git://github.com/svenfuchs/i18n-active_record.git',
  :require => 'i18n/active_record'

./config/initializers/i18n.rb

I18n.backend = I18n::Backend::ActiveRecord
Translation  = I18n::Backend::ActiveRecord::Translation

./db/migrate/20101218175356_create_translations.rb

class CreateTranslations < ActiveRecord::Migration

  def self.up
    create_table :translations do |t|
      t.string   :locale
      t.string   :key
      t.text     :value
      t.text     :interpolations
      t.boolean  :is_proc, :default => false
    end
  end

  def self.down
    drop_table :translations
  end

end

irb

irb(main):001:0> I18n.t('loathsome')
=> "loathsome"
irb(main):002:0> Translation.create(:locale => :en, :key => 'loathsome', :value => 'dave')
=> #<I18n::Backend::ActiveRecord::Translation id: 1, locale: :en, key: "loathsome", value: "dave", interpolations: nil, is_proc: false>
irb(main):003:0> I18n.t('loathsome')
=> "dave"

So fairly simple start, it shouldn’t be too difficult to build an interface to handle this.

You can even keep the existing flat files as a fallback if the translations don’t exist in the database.

./config/initializers/i18n.rb

I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
Translation = I18n::Backend::ActiveRecord::Translation