翻译排队的邮件(本地化)
Translate queued mails (localization)
我正在寻找一个可行的解决方案,翻译 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
]);
我遇到了同样的问题
在不扩展队列的情况下class最快/最肮脏的解决方案是为每个语言环境创建一个电子邮件模板。
然后当您创建队列时,select 本地模板即
Mail::queue('emails.'.App::getLocale().'notification', function($message)
{
$message->to($emails)->subject('hello');
});
如果本地设置为 IT(意大利语)这将加载视图 emails/itnotification。blade.php
正如我所说...脏!
因为这个方法实在是太可怕了所以才遇到的this answer
它对我有用,你实际上将电子邮件的整个翻译 html 版本发送到队列中,并有一个空白的 blade 文件在队列运行时回显变量。
我一直在努力以更有效的方式完成这项工作。目前我已经这样设置了。希望这对将来解决此问题的人有所帮助:
// 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) }}
注意:不要忘记重启队列
如果您的电子邮件继承了内置 Illuminate\Mail\Mailable
class,您可以构建自己的 Mailable class 来处理翻译。
创建您自己的 SendQueuedMailable
class,继承自 Illuminate\Mail\SendQueuedMailable
。
Class 构造函数将从配置中获取当前 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
class 继承自 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
class 继承的所有排队的邮件将自动处理当前的语言环境。
这是一个对我有用的解决方案。在我的示例中,我使用专用的 Job
class.
在队列中处理预订
当您在队列中调度作业时,传递语言环境,您希望您的电子邮件进入。例如:
ProcessBooking::dispatch($booking, \App::getLocale());
然后,在您的作业中 class(在我的示例中为 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 应用程序。如果你曾经 运行 遇到问题,当你清除缓存时,但排队 'stuff' (例如电子邮件)仍然显示旧内容,这是因为那个。这是来自 Laravel docs 的解释:
Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers.
在Laravel 5.6中是一个添加到Mailable的语言环境功能:
$infoMail->local('jp');
Mail::queue($infoMail);
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());
使用 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
我正在寻找一个可行的解决方案,翻译 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
]);
我遇到了同样的问题
在不扩展队列的情况下class最快/最肮脏的解决方案是为每个语言环境创建一个电子邮件模板。
然后当您创建队列时,select 本地模板即
Mail::queue('emails.'.App::getLocale().'notification', function($message)
{
$message->to($emails)->subject('hello');
});
如果本地设置为 IT(意大利语)这将加载视图 emails/itnotification。blade.php
正如我所说...脏!
因为这个方法实在是太可怕了所以才遇到的this answer 它对我有用,你实际上将电子邮件的整个翻译 html 版本发送到队列中,并有一个空白的 blade 文件在队列运行时回显变量。
我一直在努力以更有效的方式完成这项工作。目前我已经这样设置了。希望这对将来解决此问题的人有所帮助:
// 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) }}
注意:不要忘记重启队列
如果您的电子邮件继承了内置 Illuminate\Mail\Mailable
class,您可以构建自己的 Mailable class 来处理翻译。
创建您自己的 SendQueuedMailable
class,继承自 Illuminate\Mail\SendQueuedMailable
。
Class 构造函数将从配置中获取当前 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
class 继承自 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
class 继承的所有排队的邮件将自动处理当前的语言环境。
这是一个对我有用的解决方案。在我的示例中,我使用专用的 Job
class.
当您在队列中调度作业时,传递语言环境,您希望您的电子邮件进入。例如:
ProcessBooking::dispatch($booking, \App::getLocale());
然后,在您的作业中 class(在我的示例中为 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 应用程序。如果你曾经 运行 遇到问题,当你清除缓存时,但排队 'stuff' (例如电子邮件)仍然显示旧内容,这是因为那个。这是来自 Laravel docs 的解释:
Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers.
在Laravel 5.6中是一个添加到Mailable的语言环境功能: $infoMail->local('jp'); Mail::queue($infoMail);
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());
使用 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