Tuesday, October 6, 2009

Localized ActionMailer Templates for Rails

Rails actually does support localized templates, however, this does not apply for localized ActionMailer templates (yet?). Even if you add the correct locale to your mailer template names, ActionMailer does not choose the one based on the current locale.

It's really easy to fix this:

Just create a subclass of ActionMailer::Base and override the initialize_defaults method as shown below. Then let your mailers inherit from your new subclass.

    1 class ActionMailer::Localized < ActionMailer::Base
2
3 private
4
5 # we override the template_path to render localized templates (since rails does not support that :-( )
6 # This thing is not testable since you cannot access the instance of a mailer...
7 def initialize_defaults(method_name)
8 super
9 @template = "#{I18n.locale}_#{method_name}"
10 end
11
12 end

Define your desired template name as shown on line 9, just do not add your locale as dot-notation at the end of the file. E.g. method_name.de.text.plain.erb will not work.

8 comments:

Matt said...

Not exactly sure how all the localization stuff works in rails as I am still only learning.. I am working on an app that is sending emails out and they need to be localized. It appears as though it is using the gettext plugin.

Would the same fix apply to this? My concern is the call I18n.. isn't this the inbuilt method in reails? If you can shed any light would be much appreciated.

Andi Schacke said...

Hi Matt,

you can use the I18n methods in your mailer templates without any patches or fixes. But sometimes (especially in mails), it's easier to have completely different views for each language, i.e. your not calling I18n.translate to translate your text, but you have different files for the same view - one for each locale. that's why rails has the concept of localized views (http://guides.rubyonrails.org/i18n.html#localized-views). But localized views do not work for mail-templates, that's what this patch is for.

So, to summarize: If you prefer using I18n.translate calls to translate your mailer templates, you don't have to do anything. If you prefer having one mailer-template per language, you have to apply this fix...

Philip said...

I have tried this code and found that its working fine, but i am not being able to check with that how come i be able to send out bunch of emails.

Philip
Web Based Application Development

Andi Schacke said...

Hi Philip, I think I don't understand your question. Can you give an example?

Thanks
Andi

Daniel Abrahamsson said...

Hi Andi,

Here comes a code snippet that allows you to use the standard format (method_name.locale).


def initialize_defaults(method_name)
  super
  unless Dir["#{template_path}/#{method_name}.#{I18n.locale}*"].empty?
    @template = "#{method_name}.#{I18n.locale}"
  end
end

I also suggest that you posts this as a patch on the Rails 2.x branch in lighthouse (people will continue to use Rails 2.x for a long time, even after Rails 3, with its reworked ActionMailer, has been released).

Anyway, thank you for sharing your solution!

Richie said...

Hi,

Thanks for the code, this is exactly what I need.

However, where do I put this bit of code so it gets picked up when a mail is send?

Thanks again,

Richard.

Andi Schacke said...

Hi Richard,

place the code somewhere in the load path, e.g. in app/models/action_mailer/localized.rb. Then when creating a new Mailer, make it a subclass of the Localized Mailer:

class SignupMailer < ActionMailer::Localized
...
end

Hope that helps
Andi

Wildnet Technologies said...

I completely agree with these turnoffs. However, I think when it comes down to buying a house, you have to sacrifice on some things to stay within your budget.