I have darebusters.com running on Heroku and I have a worker running Delayed Job (DJ) activated. This allows me to handle heavy tasks such as video processing and payment transactions asynchronously, so the dynos can get right back to serving requests.
I also use DJ to send out emails, and a typical asynchronous call sending a message from one user to another – scheduling a delayed job – used to look like this:
UserMailer.send_later(
:deliver_message,
@recipient,
current_user,
params[:message]
)
Since darebusters.com is an internationalized website currently offering users the choice between English and German, this has proved a slight challenge, however. We have the usual internationalization (i18n) bells and whistles: Flags to select the language, and remembering the user’s language selection in session, cookie and in the users database table. By default, a delayed job will simply run with the default locale of the site. It has no way of accessing the context it was invoked in, so it cannot set the locale from session or cookie. The job only knows what it can work it from the arguments it was created with.
It looks like an easy problem to solve. DJ shouldn’t have to know about locales, the code should just set I18n.locale from @recipient.locale. That’s exactly how I initially thought I had solved it: In the UserMailer.message method I set the locale, and then passed parameters to render the mail. The catch is, however, that I use a slight hack to get support for localized ActionMailer templates, i.e. when the locale is set to de it will render the message.de.text.plain.erb view rather than the message.en.text.plain.erb view. The template to render is selected before UserMailer.message is invoked, so at that time it’s too late to set the correct locale. In fact, I needed the entire job to run in a locale specified when the job as scheduled.
For this purpose, I created a custom delayed method to be invoked by DJ: LocalizedJob.
This code should be placed in /lib/. I want the send_later_with_i18n to be available on all objects just like DJ’s own send_later, so I also also created an initializer to extend the Object class:
This code should be placed in /config/initializers/. I am now able to replace all my send_later calls with send_later_with_i18n calls, storing the required locale with job to be extracted when it’s run:
UserMailer.send_later_with_i18n(
:deliver_message,
@recipient.locale,
@recipient,
current_user,
params[:message]
)
So on darebusters.com, Germans get all their mails in German – no matter what locale the sender used (although the actual message written by the sender is of course not translated ;) – and everyone else gets mails in English. Now that was a real Ruby fairytale.
Hello, I'm Casper Fabricius. I have developed for the web for 10 years, and have been enjoying Ruby on Rails for the past 5.
My experience covers communities, shopping solutions, multi-language sites, heavy back-end lifting and a wide selection of more traditional websites. I like to integrate Ruby with Java and .NET through JRuby and IronRuby when it makes sense. I am passionate about test- and behavior-driven development, but at the same time I am pragmatic and believe in getting things done.
I live in Copenhagen, Denmark, where I work for a fantastic company: Podio. I do not currently take on freelance assignments.