我正在寻找一个有效的解决方案,以便在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
]);
答案 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版本的电子邮件发送到队列中,并有一个空白的刀片文件,当队列运行时回显变量。