как изменить локаль в электронной почте, отправляемой с контроллера - laravel 5.4

Я успешно отправляю электронные письма с этим фрагментом кода:

 \App::setLocale('pl');
 Mail::send('emails.new_'.$itemtype, ['object' => $object, 'email' =>     $email_recipee], function ($m) use ( $email_recipee, $object, $itemtype) {
 $m->to($email_recipee, 'Title')->subject(' Subject of email');
 //
 });

Но электронные письма переводятся на en, язык приложения по умолчанию.

Мой вопрос

Как заставить Laravel отправлять электронную почту с локалью, объявленной только для определенного электронного письма (у каждого получателя установлен другой язык).

Что я пробовал:

  • \App::setLocale('pl'); непосредственно перед командой Mail
  • установка моего рабочего промежуточного программного обеспечения в контроллере глобально в __construct():

    $this->middleware('setLocale'); // sets the locale to the recipee locale

грязный (?) раствор

На данный момент я просто добавляю строку в представление электронной почты:

{{ \App::setLocale($lead->client->lang)}}

Есть ли лучший способ сделать это? Спасибо.


person Peter    schedule 09.02.2017    source источник
comment
Да, App::setLocale($locale) это путь.   -  person EddyTheDove    schedule 09.02.2017
comment
Если у вас есть каталог app/Mail с вашими электронными письмами, вы можете установить это в конструкторе. Если вы все еще не используете старый способ отправки электронных писем.   -  person EddyTheDove    schedule 09.02.2017
comment
Как вы решили это?   -  person Adam    schedule 25.01.2018


Ответы (4)


То, что вы предложили, должно работать. Просто измените локаль перед отправкой почты. Однако вы должны обязательно сбросить локаль:

$temp = \App::getLocale();
\App::setLocale($user->language);
\Mail::to($user)->send(new OrderShipped($order));
\App::setLocale($temp);

Поскольку это немного раздуто, вы можете упростить это до

\App\Mail\SendMail::to($user, '\App\Mail\OrderShipped', [$order]);

если вы создадите следующий класс SendMail:

<?php

namespace App\Mail;

use App\User;

class SendMail
{

  /**
   * Send Mail to correct emailadress and set correct language
   * @param  User   $user
   * @param  String $classname
   * @param  Array  $data
   * @return void
   */
  public static function to(User $user, String $class, Array $params)
  {
    $temp = \App::getLocale();
    \App::setLocale($user->lang);

    $reflection_class = new \ReflectionClass($class);
    $mailclass = $reflection_class->newInstanceArgs($params);

    \Mail::to($user)->send($mailclass);

    \App::setLocale($temp);
  }
}

Возможно, также полезно знать, что вы можете получить свой языковой контент и без setLocale . Например, __('birthday_parole', [], 'pl') попытается дать вам полированную версию, несмотря на настройки setLocale.

person Adam    schedule 25.01.2018

TL;DR: Просто установите поле $locale в объекте класса Mailable:

class ResetPassword extends Mailable
{
   // ...

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(User $user, string $token)
    {
        $this->user = $user;
        $this->token = $token;
        /*
         * Set locale of mail to User's locale
         */
        $this->locale = $this->user->locale; // <-- of course adapt this line to YOUR User model :]
    }

Долгая история:

Есть черта Localizable. Он объявляет метод withLocale, который вызывает заданную функцию, заключенную в указанную локаль. Под обволакиванием я подразумеваю: запомнить текущую локаль, установить новую локаль, вызвать функцию, восстановить запомненную локаль.

Пример использования можно найти в \Illuminate\Mail\Mailable::send:

public function send(MailerContract $mailer)
{
    return $this->withLocale($this->locale, function () use ($mailer) {
        Container::getInstance()->call([$this, 'build']);

        return $mailer->send($this->buildView(), $this->buildViewData(), function ($message) {
            $this->buildFrom($message)
                 ->buildRecipients($message)
                 ->buildSubject($message)
                 ->runCallbacks($message)
                 ->buildAttachments($message);
        });
    });
}

Однако этот метод дает нам представление о том, как изменить локаль для почты — в первой строке стоит $this->locale. Действительно, в Mailable определено это поле:

class Mailable implements MailableContract, Renderable
{
   // ...

    /**
     * The locale of the message.
     *
     * @var string
     */
    public $locale;
person jacek.ciach    schedule 29.06.2020
comment
Это должно быть помечено как ответ. На мой взгляд, самый чистый ответ. Спасибо. - person Baspa; 05.05.2021

Вы можете использовать Mailable class документы. В конструкторе __construct(User $user) вы можете ввести подсказку пользователю , и установите локаль оттуда:

            <?php

            namespace App\Mail;

            use Illuminate\Bus\Queueable;
            use Illuminate\Mail\Mailable;
            use Illuminate\Queue\SerializesModels;
            use Illuminate\Contracts\Queue\ShouldQueue;
            use App\User;

            class Welcome extends Mailable
            {
                use Queueable, SerializesModels;

                protected $user;

                /**
                 * Create a new message instance.
                 *
                 * @return void
                 */
                public function __construct(User $lead)
                {
                    \App::setLocale($lead->client->lang);
                    $this->user = $lead;
                    $this->subject = trans('welcome_title');
                }

                /**
                 * Build the message.
                 *
                 * @return $this
                 */
                public function build()
                {
                    return $this->view('emails.welcome')->with('user', $this->user);
                }
            }
person Marco Cazzaro    schedule 10.02.2017
comment
Спасибо за ответ - завтра проверю. Извините за задержку. Питер - person Peter; 10.02.2017
comment
Но тогда вы навсегда меняете локаль, верно? Вам не нужно переключать его обратно? - person Adam; 25.01.2018
comment
Находясь в очереди, почтовый запрос завершится с этой конкретной локалью, но это не повлияет на исходный запрос. - person Marco Cazzaro; 26.01.2018
comment
Для меня все, что мне нужно было добавить, это: \App::setLocale(strtolower($leads-›page)); в NewLead.php - person Brad Ahrens; 10.09.2018

Для тех, кто использует Laravel 6.* и просматривает этот пост, похоже, что в последнее время все изменилось.

Теперь вы можете определить локаль внутри самого контроллера, просто добавив ->locale() в файл Mail.

Например:

Mail::to($request->user())->locale('es')->send(
    new OrderShipped($order)
);

Для получения дополнительной информации см. официальную документацию.

Удачного кодирования!

person Brad Ahrens    schedule 21.02.2020
comment
Спасибо, я только что протестировал ваше решение, и оно работает в Laravel 8. - person Yevgeniy Afanasyev; 03.03.2021