resque_mailer icon indicating copy to clipboard operation
resque_mailer copied to clipboard

Support for locale (and timezone)

Open fabn opened this issue 10 years ago • 2 comments

I've used your gem in an existing project which send localized emails and on first deploy I got some issues due to missing locale support. Here's my use case, I have a mailer which uses layouts and those layouts shows localized links something like

<%= link_to t('some_key'), some_url %>

I was sending messages directly in the controller and links and other translated stuff is localized correctly since in controller I18n.locale is set according to user locale. When I moved to resque_mailer obviously that code has stopped to work.

In my project I was able to retrieve user locale from the mailer and I've solved with this code in my mailer, but this is not always possible.

def mailer(user_id)
  @user = User.find(user_id)
  I18n.with_locale(@user.locale) { mail(...) }
end

The same issue can appear if mail content is timezone dependent (wasn't my case) so this should be handled by gem.

This could be solved with something like

# in deliver
env = {locale: I18n.locale, timezone: Time.zone.name}
resque.enqueue(@mailer_class, @method_name, env, *@args)
# in perform
I18n.with_locale(env['locale']) do
  Time.use_zone(env['timezone']) do
    message = self.send(:new, action, *args).message
    message.deliver              
  end
end

This however would change main methods signatures, so it would need some specs.

What do you think? Are you interested in this kind of PR? Otherwise you should mention this issue in readme.

fabn avatar Oct 16 '13 14:10 fabn

Hmm interesting. I admittedly haven't had the need to send localized emails myself, but if others have this issue it's certainly a concern.

That said, I don't love the solution of changing the global state to achieve it, and changing the method signature is undesirable, potentially breaking for users with mail in-queue... So that would have to be managed. Otoh to your point, it stinks if users have to create a locale field to reference for each mailer method that cares of course. This is also Rails-specific and not all users of RM are using Rails, so that's something to consider.

Happy to discuss further. Thanks for pointing this out.

zapnap avatar Oct 21 '13 14:10 zapnap

You can automatically pass and restore the current locale https://gist.github.com/glebm/5725347

# pop and set locale from the args before running
module PerformWithLocale
  def perform(*args)
    I18n.with_locale(args.pop) do
      super(*args)
    end
  end
end

module DeliverWithLocale
  def deliver
    # @args are not used when rendered inline, only when enqueueing
    @args << I18n.locale.to_s
    super
  end
end

#= resque_mailer locale support
if defined?(Resque::Mailer)
  module Resque::Mailer
    # push locale onto the args when queueing
    MessageDecoy.send :prepend, DeliverWithLocale
    # pop when dequeueing
    ClassMethods.send :prepend, PerformWithLocale
  end
end

glebm avatar Oct 10 '14 22:10 glebm