How can I send mails in a mailer using the recipient\'s locale. I have the preferred locale for each user in the database. Notice this is different from the current locale (I18n
Here's an updated version that also supports the '.key' short-hand notation, so you don't have to spell out each key in its entirety.
http://github.com/larspind/i18n_action_mailer
None of the above is really working since the version 3 to translate both subject and content and be sure that the locale is reseted back to the original one... so I did the following (all mailer inherit from that class:
class ResourceMailer < ActionMailer::Base
def mail(headers={}, &block)
I18n.locale = mail_locale
super
ensure
reset_locale
end
def i18n_subject(options = {})
I18n.locale = mail_locale
mailer_scope = self.class.mailer_name.gsub('/', '.')
I18n.t(:subject, options.merge(:scope => [mailer_scope, action_name], :default => action_name.humanize))
ensure
reset_locale
end
def set_locale(locale)
@mail_locale = locale
end
protected
def mail_locale
@mail_locale || I18n.locale
end
def reset_locale
I18n.locale = I18n.default_locale
end
end
You just need to set the locale before you call the mail() method:
set_locale @user.locale
You can use the i18n_subject method which scope the current path so everything is structured:
mail(:subject => i18n_subject(:name => @user.name)
The problem with the mentioned plugins are that they don't work in all situations, for example doing User.human_name or User.human_attribute_name(...) will not translate correctly. The following is the easiest and guaranteed method to work:
stick this somewhere (in initializers or a plugin):
module I18nActionMailer def self.included(base) base.class_eval do include InstanceMethods alias_method_chain :create!, :locale end end module InstanceMethods def create_with_locale!(method_name, *parameters) original_locale = I18n.locale begin create_without_locale!(method_name, *parameters) ensure I18n.locale = original_locale end end end end ActionMailer::Base.send(:include, I18nActionMailer)
and then in your mailer class start your method by setting the desired locale, for example:
def welcome(user) I18n.locale = user.locale # etc. end
This simple plugin was developed for rails 2 but seems to work in rails 3 too.
http://github.com/Bertg/i18n_action_mailer
With it you can do the following:
def new_follower(user, follower)
@follower = follower
@user = user
set_locale user.locale
mail :to => @user.email, :subject => t(:new_follower_subject)
end
The subject and mail templates are then translated using the user's locale.
I believe the best way to do this is with the great method I18n.with_locale
, it allows you to temporarily change the I18n.locale
inside a block, you can use it like this:
def new_follower(user, follower)
@follower = follower
@user = user
I18n.with_locale(@user.profile.locale) do
mail to: @user.email
end
end
And it'll change the locale just to send the email, immediately changing back after the block ends.
Source: http://www.rubydoc.info/docs/rails/2.3.8/I18n.with_locale
This answer was a dirty hack that ignored I18n's with_locale
method, which is in another answer. The original answer (which works but you shouldn't use it) is below.
Quick and dirty:
class SystemMailer < ActionMailer::Base
def new_follower(user, follower)
@follower = follower
@user = user
using_locale(@user.profile.locale){mail(:to=>@user.email)}
end
protected
def using_locale(locale, &block)
original_locale = I18n.locale
I18n.locale = locale
return_value = yield
I18n.locale = original_locale
return_value
end
end