delayed_job and localization (i18n)

delayed_job is a nice gem for executing work in the background in Ruby On Rails.

But what happend to me is that mails did not get send correctly. I was expecting to get them send in german and not english (default locale).

What happend?

The controller did set it correctly depending on the user.

A new record was created that triggered an email to be send. Since delayed_job sends them asynchronously (exactly what i wanted) a job was created in the database and executed in the background.

But the backgroundjob defaulted to the default locale (english) and so the email had the wrong locale that was used for determing translations (I18n.t is used widely in my applications).

So now i had to come up with a solution.

  • Remember the locale when the job is created
  • set it while executing the job

delayed_job provides a nice API for integrating around job execution (lifecycle-hooks).

So what i did in my task-infrastructure:

1. Add a new Migration for having a attribute locale in the database to store the locale for the job

# Adds a locale attribute to delayed_jobs Table
class AddLocaleToDelayedJobs < ActiveRecord::Migration
  def change
    change_table :delayed_jobs do |t|
      t.string :locale # will hold the locale
    end
  end
end

2. Add an initializer that stores the locale when a job is created


Delayed::Worker.lifecycle.before(:enqueue) do |job|
  # If Locale is not set
  if(job.locale.nil? || job.locale.empty? && I18n.locale.to_s != I18n.default_locale.to_s)
    job.locale = I18n.locale
  end
end

3. Add an initializer that sets the locale around job execution


Delayed::Worker.lifecycle.around(:invoke_job) do |job, &block|
  # Store locale of worker
  savedLocale = I18n.locale

  begin
    # Set locale from job or if not set use the default
    if(job.locale.nil?)
      I18n.locale = I18n.default_locale
    else
      I18n.locale = job.locale
    end

    # now really perform the job
    block.call(job)

  ensure
    # Clean state from before setting locale
    I18n.locale = savedLocale
  end
end

4. Work normally and be happy that localization now also works in the background!

2 Gedanken zu „delayed_job and localization (i18n)“

Kommentare sind geschlossen.