MongoDB-based Backend::Store implementation for I18n gem

Currently I’m working on a web project on top of rails 3 and mongodb.

Recently we faced the necessity of changing I18n backend from simple to something more dynamic (in fact, we wanted to allow the non-geeks from our team to participate in the internationalization process via web interface).

I googled for “mongodb i18n”, “mongo_mapper i18n”, “mongodb i18n backend”, etc. and found nothing, so I wrote my own implementation of mongodb backend for I18n, called mongo-i18n (in fact, «wrote» is too strong a word — all that I needed to do was to implement three methods of the store interface:)

You can grab the sources here or you can install the gem via command line:

gem install mongo-i18n

Usage:

I recommend to start with Chain backend while mongodb collection is empty, and move to entirely mongodb-based backend when you populate your database with all I18n messages.

Begin with:

collection = Mongo::Connection.new['my_app_related_db'].collection('i18n')
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::KeyValue.new(MongoI18n::Store.new(collection)), I18n.backend)

And finish with:

collection = Mongo::Connection.new['my_app_related_db'].collection('i18n')
I18n.backend = I18n::Backend::KeyValue.new(MongoI18n::Store.new(collection)

If you are already using a mongodb ORM in your project (and I suppose you are, why else would you be reading this article? :), I recommend using the existing database connection.

collection = MongoMapper.database.collection('i18n')
I18n.backend = I18n::Backend::KeyValue.new(MongoI18n::Store.new(collection))

Free Christmas gift, the rake file to import en.yml into mongodb:

 1 # usage:
 2 # bundle exec rake locale:file RAILS_ENV=production
 3 # if you want to export a different locale (not en.yml), provide locale option, as follows:
 4 # bundle exec rake locale:file RAILS_ENV=production locale=ru
 5 
 6 require 'mongo-i18n'
 7 
 8 def write_to_database(sc, path, value)
 9   key = path.join('.')
10   sc[key] = value.to_json
11 end
12 
13 # traverse through hash
14 def traverse(sc, obj, path)
15   case obj
16   when Hash
17     obj.each do |k,v| 
18       traverse(sc, v, path + [k]) 
19     end
20   when Array
21     obj.each {|v| traverse(sc, v) }
22   else # end values
23     write_to_database(sc, path, obj)
24   end
25 end
26 
27 namespace :locale do
28   desc <<-eos
29     Exports $app/config/locale/$locale.yml contents to mongodb database. 
30     If locale is not specified, default (en) locale file will be exported.
31   eos
32   task :file do
33     locale = ENV['locale'] || "en"
34     environment = ENV['RAILS_ENV']   || "development"
35     # I keep mongodb connection descriptor in config/mongodb.yml
36     config = YAML::load(File.read(Rails.root.join('config/mongodb.yml')))
37     collection = Mongo::Connection.new[config["development"]["database"]].collection('i18n')
38     store = MongoI18n::Store.new(collection)
39     
40     dump = YAML::load(File.open(Rails.root.join("config","locales", "#{locale}.yml")))
41 
42     traverse(store, dump, [])
43   end
44 end

Any feedback would be welcome.

blog comments powered by Disqus