翻译排队的邮件(本地化)

时间:2015-03-05 22:34:59

标签: php email laravel laravel-5

我正在寻找一个有效的解决方案,以便在翻译排队的电子邮件。 不幸的是,所有电子邮件都使用默认语言环境(在app.locale下定义)。

我们假设,我们在管道中有两封电子邮件,一封用于英语en用户,另一封用于日语jp用户。

我应该将哪些数据传递到Mail门面,以翻译(本地化)排队的电子邮件

  // User model
  $user = User:find(1)->first();

  Mailer::queue($email, 'Party at Batman\'s cave (Batcave)', 'emails.party-invitation', [

    ...

    'locale' => $user->getLocale(), // value: "jp", but does not work
    'lang' => $user->getLocale(), // value: "jp", but does not work
    'language' => $user->getLocale(), // value: "jp", but does not work
  ]);

7 个答案:

答案 0 :(得分:7)

我一直在努力以更有效的方式完成这项工作。目前我的设置是这样的。希望这有助于将来解决这个问题:

// Fetch the locale of the receiver.
$user = Auth::user();
$locale = $user->locale;
Mail::queue('emails.welcome.template', ['user' => $user, 'locale' => $locale], function($mail) use ($user, $locale) {
     $mail->to($user->email);
     $mail->subject(
          trans(
               'mails.subject_welcome',
               [], null, $locale
          )
     );
});

在模板中使用以下内容:

{{ trans('mails.welcome', ['name' => ucfirst($user['first_name'])], null, $locale) }}

答案 1 :(得分:3)

如果您的电子邮件继承了内置的Illuminate\Mail\Mailable类,您可以构建自己的Mailable类来处理翻译。

创建自己的SendQueuedMailable类,该类继承自Illuminate\Mail\SendQueuedMailable。 类构造函数将从配置中获取当前app.location并在属性中记住它(因为laravel队列将其序列化)。 在队列工作器中,它将从配置中恢复属性并将设置设置为当前环境。

<?php

namespace App\Mail;

use Illuminate\Contracts\Mail\Mailer as MailerContract;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Mail\SendQueuedMailable as IlluminateSendQueuedMailable;

class SendQueuedMailable extends IlluminateSendQueuedMailable
{
    protected $locale;

    public function __construct(MailableContract $mailable)
    {
        parent::__construct($mailable);

        $this->locale = config('app.locale');
    }

    public function handle(MailerContract $mailer)
    {
        config(['app.locale' => $this->locale]);
        app('translator')->setLocale($this->locale);

        parent::handle($mailer);
    }
}

然后,创建一个继承自Mail

Illuminate\Mail\Mailable
<?php

namespace App\Mail;

use Illuminate\Contracts\Queue\Factory as Queue;
use Illuminate\Mail\Mailable as IlluminateMailable;

class Mailable extends IlluminateMailable
{
    public function queue(Queue $queue)
    {
        $connection = property_exists($this, 'connection') ? $this->connection : null;

        $queueName = property_exists($this, 'queue') ? $this->queue : null;

        return $queue->connection($connection)->pushOn(
            $queueName ?: null, new SendQueuedMailable($this)
        );
    }
}

而且,瞧,从App\Mailable类继承的所有排队的mailables将自动处理当前的语言环境。

答案 2 :(得分:3)

在Laravel 5.6中,是一个添加到Mailable的语言环境功能: $ infoMail-> locale('jp'); Mail :: queue($ infoMail);

答案 3 :(得分:0)

这是一个对我有用的解决方案。在我的示例中,我使用专用的Job类在队列中处理预订。

当您在队列中分派作业时,传递区域设置,您希望收到电子邮件。例如:

ProcessBooking::dispatch($booking, \App::getLocale());

然后,在您的工作类(我的示例中为ProcessBooking)中将区域设置存储在属性中:

protected $booking;
protected $locale;

public function __construct(Booking $booking, $locale)
{
    $this->booking = $booking;
    $this->locale = $locale;
}

并在您的handle方法暂时切换区域设置:

public function handle()
{
    // store the locale the queue is currently running in
    $previousLocale = \App::getLocale();

    // change the locale to the one you need for job to run in
    \App::setLocale($this->locale);

    // Do the stuff you need, e.g. send an email
    Mail::to($this->booking->customer->email)->send(new NewBooking($this->booking));

    // go back to the original locale
    \App::setLocale($previousLocale);
}

为什么我们需要这样做?

排队电子邮件获取默认语言环境,因为队列工作人员是单独的Laravel应用程序。如果您遇到问题,那么当您清除缓存时,排队的内容就会出现问题。 (例如电子邮件)仍然显示旧内容,因为它。以下是Laravel docs的解释:

  

请记住,队列工作程序是长期存在的进程,并将引导的应用程序状态存储在内存中。因此,他们在启动后不会注意到代码库中的更改。因此,在部署过程中,请务必重新启动队列工作程序。

答案 4 :(得分:0)

Laravel 5.7.7引入了HasLocalePreference接口来解决此问题。

class User extends Model implements HasLocalePreference
{
    public function preferredLocale() { return $this->locale; }
}

现在,如果您使用Mail::to()函数,Laravel将以正确的语言环境发送邮件。

还引入了Mail可链接的locale()函数。

Mail::to($address)->locale($locale)->send(new Email());

答案 5 :(得分:0)

使用 preferredLocale() 是“官方”方式。

您可以实现 HasLocalePreference 并将方法 preferredLocale() 添加到通知模型(如@Peter-M 建议的那样):

use Illuminate\Contracts\Translation\HasLocalePreference;

class User extends Model implements HasLocalePreference
{
    /**
     * Get the user's preferred locale.
     *
     * @return string
     */
    public function preferredLocale()
    {
        return $this->locale;
    }
}

然后您只需将通知发送到该模型,区域设置将自动应用于您的电子邮件模板

$user->notify(new InvoicePaid($invoice));

这也适用于排队的邮件通知。

在此处阅读更多信息: https://floyk.com/en/post/how-to-change-language-for-laravel-email-notifications

答案 6 :(得分:-1)

我遇到了同样的问题

如果不扩展队列类,最快/最脏的解决方案是为每个语言环境创建一个电子邮件模板。

然后在创建队列时,选择本地模板,即

Mail::queue('emails.'.App::getLocale().'notification', function($message) 
{
    $message->to($emails)->subject('hello');
});

如果本地设置为IT(意大利语)这将加载查看电子邮件/ itnotification.blade.php

正如我所说......肮脏!

由于这种方法实际上非常糟糕,我遇到了this answer 它为我工作,你实际上将整个翻译过的html版本的电子邮件发送到队列中,并有一个空白的刀片文件,当队列运行时回显变量。