Today I want to show you a project I’ve started over a year ago, during Mendicant University core skills course. For those who don’t know, Mendicant University is a group of skilled software developers that offer courses, mentoring, and help out the community, started by Gregory Brown, and that nowadays counts with some other awesome folks as part of the staff. I highly recommend taking a look at and enrolling.
Back to I18n, during Mendicant University we were supposed to create a project in Ruby, not specifically with Rails, and I decided to scratch my own itch by trying to solve a problem we usually have in Brazil: receiving date/time/numeric input from user interface. I know and have already used the delocalized gem, and it works quite nice, but sometimes I felt a bit uncomfortable about how it handled some parts of localization/parsing. This is mainly due to the need to monkey patch both ActiveRecord to handle input, and ActionView to handle output. Besides that, and most important, I had to come up with some project and I thought that’d be a good challenge :D.
The main goal of this project is to provide a proxy object to use with your ORM (currently ActiveRecord only) that will be responsible for localizing and parsing the date/time/numeric attributes when getting or setting their values, respectively. Lets see some quick examples:
# Include the proxy in your model class Product < ActiveRecord::Base include I18n::Alchemy end # Grab your object from the database @product = Product.first # Instantiate the localized proxy @localized = @product.localized
Now that we have a localized proxy for the
@product object, we can get/set numeric attributes with localized values, such as:
@localized.price = "1.99" @product.price # => 1.99 @localized.price # => "1.99" I18n.with_locale :pt do @localized.price = "1,88" @product.price # => 1.88 @localized.price # => "1,88" end
And also date/time attributes, for instance:
@localized.released_at = "12/31/2011" @product.released_at # => Date.new(2011, 12, 31) @localized.released_at # => "12/31/2011" I18n.with_locale :pt do @localized.released_at = "31/12/2011" @product.released_at # => Date.new(2011, 12, 31) @localized.released_at # => "31/12/2011" end
I18n Alchemy can also receive a hash of attributes, the same way you use with your models when calling
new. That means you can use it like this:
# You could be using params[:product] for instance. I18n.with_locale :pt do @localized = @product.localized(:price => "1,88") @product.price # => 1.88 @localized.price # => "1,88" end
The parsing/localization formats are basically the same ones you already use in your Rails application. You can check the basic locale configuration for I18n Alchemy in its README on github.
I18n Alchemy is a small and new project which solves most of the problems we commonly face when dealing with localization and parsing of date/time/numeric values. It is tested with Rails 3.0, 3.1 and 3.2 and works with all the basic methods, such as
update_attributes and nested attributes as well.
It was a really fun time creating it during Mendicant University, and it took a long time until I decided to release it as a gem. There is still a bunch of things to do, but I wanted to ask you to give it a try and let me know about any feedback you have.
As a side note, if you are interested in knowing more about the design decisions that led this project, you may want to take a look at Gregory Brown's post on Ruby Best Practices, entitled "Issue #23: SOLID Design Principles", more specifically in the Open/closed principle topic.
I'm releasing the first 0.0.1 version today, and I hope you find it useful. Have any comments? Let us know!