Как я могу отправлять электронные письма в Rails 3, используя язык получателя?

Как я могу отправлять письма в почтовой программе, используя локаль получателя. У меня есть предпочтительный язык для каждого пользователя в базе данных. Обратите внимание, что это отличается от текущей локали (I18n.locale), поскольку текущий пользователь не обязательно должен быть получателем. Таким образом, сложно использовать почтовик в другой локали, не меняя I18n.locale:

def new_follower(user, follower)
  @follower = follower
  @user = user
  mail :to=>@user.email
end

Использование I18n.locale = @user.profile.locale перед mail :to=>... решит проблему почтовой программы, но изменит поведение остальной части потока.


person Jose    schedule 22.08.2010    source источник
comment
Более того, я получаю ошибку SystemStackError: слишком глубокий уровень стека при попытке изменить локаль через I18n.locale = независимо от того, что   -  person Jose    schedule 23.08.2010
comment
У меня та же проблема; и есть активная ошибка Rails: rails .lighthouseapp.com/projects/8994/tickets/   -  person Don Werve    schedule 24.09.2010


Ответы (7)


Я считаю, что лучший способ сделать это — использовать отличный метод I18n.with_locale, он позволяет вам временно изменить I18n.locale внутри блока, вы можете использовать его следующим образом:

def new_follower(user, follower)
  @follower = follower
  @user = user
  I18n.with_locale(@user.profile.locale) do
    mail to: @user.email
  end
end

И он изменит локаль только для отправки электронного письма, сразу же изменив ее после окончания блокировки.

Источник: http://www.rubydoc.info/docs/rails/2.3.8/I18n.with_locale

person Miguelgraz    schedule 17.04.2013

Этот ответ был грязным взломом, который игнорировал метод with_locale I18n, который находится в другом ответе. Оригинальный ответ (который работает, но вы не должны его использовать) приведен ниже.

Быстро и грязно:

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
person jimworm    schedule 15.07.2011
comment
Это решение - единственное решение, которое сработало для меня, хотя я пробовал большинство ответов, перечисленных в этом посте. Спасибо @jimworm - person wael34218; 14.09.2012
comment
Существует метод I18n.with_locale - person Brandon Bloom; 07.11.2013

в самой последней версии рельсов в настоящее время достаточно использовать «I18n.locale = account.locale» в контроллере и создавать несколько представлений со следующей стратегией именования welcome.html.erb, welcome.it.html.erb и, например, welcome.fr.html.erb

person koen    schedule 06.06.2011
comment
Это работает для меня. Вы также можете установить локаль в почтовой программе. - person Nico; 08.11.2011

Ничто из вышеперечисленного на самом деле не работает, начиная с версии 3, чтобы переводить как тему, так и контент, и быть уверенным, что локаль возвращена к исходной... поэтому я сделал следующее (все почтовые программы наследуются от этого класса:

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

Вам просто нужно установить локаль, прежде чем вызывать метод mail():

set_locale @user.locale

Вы можете использовать метод i18n_subject, который охватывает текущий путь, чтобы все было структурировано:

mail(:subject => i18n_subject(:name => @user.name)
person Vincent Peres    schedule 22.09.2011
comment
по моему мнению, reset_locale должен установить для I18n.locale начальное значение, а не значение по умолчанию. все остальное кажется в порядке. Благодарность - person Dorian; 03.10.2011

Этот простой плагин был разработан для Rails 2, но, похоже, работает и в Rails 3.

http://github.com/Bertg/i18n_action_mailer

С его помощью вы можете сделать следующее:

def new_follower(user, follower)
  @follower = follower
  @user = user
  set_locale user.locale
  mail :to => @user.email, :subject => t(:new_follower_subject)
end

Тема и почтовые шаблоны затем переводятся с использованием локали пользователя.

person Kusti    schedule 30.08.2010
comment
Спасибо! Но какой плагин вы имеете в виду? :) - person Jose; 30.08.2010
comment
Ой, ссылку забыл! :D Вот он, плагин i18n_action_mailer. - person Kusti; 31.08.2010
comment
К сожалению, это не соответствует моей цели, так как у меня есть разные представления для каждой локали: welcome.es.erb, welcome.en.erb и т. д. Плагин только перегружает методы t и l. - person Jose; 03.09.2010
comment
Правда, если мне это нужно, мне нужно использовать дополнительный партиал для их обработки, который просто говорит: = render :partial => template_#{I18n.locale} и т. д., а затем назовите представления, например, welcome_es.erb и т. д., немного уродливее, чем вы упомянули, но все же всего одна дополнительная строка. - person Kusti; 24.11.2010
comment
... и если вы используете макеты, которые необходимо перевести, вам нужно добавить «layout email_#{I18n.locale}» в каждый метод почтовой программы, что тоже немного уродливо, поэтому более чистое решение определенно приветствуется. - person Kusti; 24.11.2010

Вот обновленная версия, которая также поддерживает сокращенную запись «.key», поэтому вам не нужно указывать каждую клавишу целиком.

http://github.com/larspind/i18n_action_mailer

person Calvin Correli    schedule 20.09.2010
comment
Спасибо за плагин. Однако по-прежнему не удается выбрать подходящее представление в соответствии с локалью в Rails 3. - person Jose; 28.09.2010

Проблема с упомянутыми плагинами заключается в том, что они работают не во всех ситуациях, например, выполнение User.human_name или User.human_attribute_name(...) не будет правильно переведено. Ниже приведен самый простой и гарантированный метод работы:

вставьте это куда-нибудь (в инициализаторы или плагин):

  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)

а затем в своем классе почтовой программы запустите свой метод, установив желаемую локаль, например:

  def welcome(user)
    I18n.locale = user.locale
    # etc.
  end
person Jim Soho    schedule 13.11.2010
comment
Этот код отображает следующую ошибку alias_method': undefined method create!' для класса `ActionMailer::Base' (NameError), когда я пытался запустить его на рельсах 3.2.8 - person wael34218; 14.09.2012