-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Email locale set back to default, when locale set within Mailable #25691
Comments
Framework fixThe current implementation puts the full localization responsibility on the intermediate https://github.com/laravel/framework/blob/5.7/src/Illuminate/Mail/PendingMail.php#L162 protected function fill(Mailable $mailable)
{
return $mailable->to($this->to)
->cc($this->cc)
->bcc($this->bcc)
->locale($this->locale);
} To allow the Mailable itself to decide on locale, it should probably only pass on the locale when /**
* Populate the mailable with the addresses.
*
* @param \Illuminate\Mail\Mailable $mailable
* @return \Illuminate\Mail\Mailable
*/
protected function fill(Mailable $mailable)
{
return tap($mailable, function ($mailable) {
$mailable->to($this->to)
->cc($this->cc)
->bcc($this->bcc);
if ($this->locale) {
$mailable->locale($this->locale);
}
});
} App-level fixAn immediate app-level solution is adding an https://github.com/laravel/framework/blob/5.7/src/Illuminate/Mail/Mailable.php#L407 public function locale($locale)
{
$this->locale = $locale;
return $this;
} to: namespace App\Mail;
use Illuminate\Mail\Mailable as BaseMailable;
class Mailable extends BaseMailable
{
public function locale($locale)
{
$this->locale = $this->locale ?? $locale;
return $this;
}
} or: public function locale($locale)
{
$this->locale = $locale ?? $this->locale;
return $this;
} will ensure the already-assigned locale is never be erased. class AppointmentSummary extends \App\Mail\Mailable
{
// ... Complete solutionI have another framework pull request I never got around to for mailer/notification localization. For this: Mail::to($appointment->customer)->queue(new AppointmentSummary($appointment)); If the |
I think the problem lies here: https://github.com/laravel/framework/blob/5.7/src/Illuminate/Mail/Mailer.php#L135
From what I tested, this is what is used when you call I'm already using a custom Mailable, but I don't know the way to swap My end goals are:
EDIT: I have both points working now, but it requires me to set the same locale in 2 places: in 'preview' route, and in 'send' method of the controller. I think it useful to be able to 'bind' the locale to a Mailable in its constructor. It even seems to me like it was the intended behavior: When I am setting German locale in the Mailable's contructor and do this:
The email is sent in German (:+1:). When I do that:
The email defaults to English (:-1:). |
5.7.7 adds a class Customer implements HasLocalePreference
{
public function preferredLocale()
{
return $this->locale;
}
} Mail::to($appointment->customer)
->queue(new AppointmentSummary($appointment));
Mail::to($employee)
->locale($appointment->customer->locale)
->queue(new AppointmentSummary($appointment)); Mailable classes themselves should never have to refer to locale as the |
Please try the suggestion provided by @derekmd. |
Lol, you can't just close the issue without a proper fix in place. We had the same issue, and 'solved' it by setting locale on the Mail facade. But according to docs locale 'should' be set to the Mailable, so either docs need an update, or the fill method needs patching to honour $locale from Mailable before trying to overwrite it. Let us know what you prefer and we'll provide a PR if needed. |
@danijelk okay, I'll reopen this and have a thorough look later. |
The documentation mistakenly stated that due to a miscommunication when the localization feature was added. The docs have since been fixed to note the |
@derekmd thanks for pointing that out. |
Description:
Illuminate\Mail\Mailable
has a public methodlocale
, which allows to set a locale for a specific Mailable. It was added in #23178.I would like to set the locale in Mailable's constructor, based on the value of an object passed to Mailable, as in:
I'm setting the locale in the constructor, and not by chaining the
locale
method as isMail::to($appointment->customer->email)->locale($appointment->customer->locale)->send(new AppointmentSummary($appointment))
to avoid code duplication (the user should be able to preview the email before sending), and to be able to test whether the email was properly translated usingrender
method.Setting locale in the constructor (as I want) works fine for email preview purposes, but when I use the 'chaining' approach (
Mail::to($appointment->customer->email)->send(new AppointmentSummary($appointment))
without chaining on the locale, the locale set in constructor gets overwritten to default before sending.This is because
Mail::to()
returns aPendingMail
object, which sets back the mail locale to either default, or the one passed to it via chaining. That is:Mail::to($appointment->customer->email)
instantiates, and returnsPendingMail
PendingMail::send(new AppointmentSummary($appointment))
callsfill
its fill method, which refills the locale.And since the locale was sent on the
Mailable
, and not on the newly instantiatedPendingMail
, the locale set in the constructor of Mailable is forgotten by the time the mailable is sent.EDIT:
AppointmentSummary extends my custom Mailable, which overrides a default
render
method. This allows to display translated preview, but has nothing to do with the fact that you cannot set the locale in Mailable's constructor (the unexpected behavior that I am reporting here).The text was updated successfully, but these errors were encountered: