From aeef1b023771112ab0503cd48affef4a9980f6f4 Mon Sep 17 00:00:00 2001 From: Derek MacDonald Date: Sun, 23 Sep 2018 21:47:52 -0400 Subject: [PATCH] Notifiables can set preferred locale --- .../Notifications/NotificationSender.php | 20 +++- .../SendingNotificationsWithLocaleTest.php | 94 +++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Notifications/NotificationSender.php b/src/Illuminate/Notifications/NotificationSender.php index 6cf909374a3f..235728372bb2 100644 --- a/src/Illuminate/Notifications/NotificationSender.php +++ b/src/Illuminate/Notifications/NotificationSender.php @@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Traits\Localizable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Contracts\Translation\HasLocalePreference; use Illuminate\Database\Eloquent\Collection as ModelCollection; class NotificationSender @@ -95,7 +96,7 @@ public function sendNow($notifiables, $notification, array $channels = null) continue; } - $this->withLocale($notification->locale ?? $this->locale, function () use ($viaChannels, $notifiable, $original) { + $this->withLocale($this->preferredLocale($notifiable, $notification), function () use ($viaChannels, $notifiable, $original) { $notificationId = Str::uuid()->toString(); foreach ((array) $viaChannels as $channel) { @@ -105,6 +106,23 @@ public function sendNow($notifiables, $notification, array $channels = null) } } + /** + * Get the locale for the notification preferred by this notifiable. + * + * @param mixed $notifiable + * @param mixed $notification + * + * @return string|null + */ + protected function preferredLocale($notifiable, $notification) + { + return $notification->locale ?? $this->locale ?? value(function () use ($notifiable) { + if ($notifiable instanceof HasLocalePreference) { + return $notifiable->preferredLocale(); + } + }); + } + /** * Send the given notification to the given notifiable via a channel. * diff --git a/tests/Integration/Notifications/SendingNotificationsWithLocaleTest.php b/tests/Integration/Notifications/SendingNotificationsWithLocaleTest.php index 741249e51717..b22aca7c1372 100644 --- a/tests/Integration/Notifications/SendingNotificationsWithLocaleTest.php +++ b/tests/Integration/Notifications/SendingNotificationsWithLocaleTest.php @@ -14,6 +14,7 @@ use Illuminate\Foundation\Events\LocaleUpdated; use Illuminate\Notifications\Channels\MailChannel; use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Contracts\Translation\HasLocalePreference; use Illuminate\Support\Facades\Notification as NotificationFacade; /** @@ -45,6 +46,7 @@ protected function getEnvironmentSetUp($app) '*' => [ '*' => [ 'en' => ['hi' => 'hello'], + 'es' => ['hi' => 'hola'], 'fr' => ['hi' => 'bonjour'], ], ], @@ -155,6 +157,83 @@ public function test_mail_is_sent_with_locale_updated_listeners_called() $this->assertSame('en', Carbon::getLocale()); } + + public function test_locale_is_sent_with_notifiable_preferred_locale() + { + $recipient = new NotifiableEmailLocalePreferredUser([ + 'email' => 'test@mail.com', + 'email_locale' => 'fr', + ]); + + $recipient->notify(new GreetingMailNotification()); + + $this->assertContains('bonjour', + app('swift.transport')->messages()[0]->getBody() + ); + } + + public function test_locale_is_sent_with_notifiable_preferred_locale_for_multiple_recipients() + { + $recipients = [ + new NotifiableEmailLocalePreferredUser([ + 'email' => 'test@mail.com', + 'email_locale' => 'fr', + ]), + new NotifiableEmailLocalePreferredUser([ + 'email' => 'test.2@mail.com', + 'email_locale' => 'es', + ]), + NotifiableLocalizedUser::forceCreate([ + 'email' => 'test.3@mail.com', + ]), + ]; + + NotificationFacade::send( + $recipients, new GreetingMailNotification() + ); + + $this->assertContains('bonjour', + app('swift.transport')->messages()[0]->getBody() + ); + $this->assertContains('hola', + app('swift.transport')->messages()[1]->getBody() + ); + $this->assertContains('hi', + app('swift.transport')->messages()[2]->getBody() + ); + } + + public function test_locale_is_sent_with_notification_selected_locale_overriding_notifiable_preferred_locale() + { + $recipient = new NotifiableEmailLocalePreferredUser([ + 'email' => 'test@mail.com', + 'email_locale' => 'es', + ]); + + $recipient->notify( + (new GreetingMailNotification())->locale('fr') + ); + + $this->assertContains('bonjour', + app('swift.transport')->messages()[0]->getBody() + ); + } + + public function test_locale_is_sent_with_facade_selected_locale_overriding_notifiable_preferred_locale() + { + $recipient = new NotifiableEmailLocalePreferredUser([ + 'email' => 'test@mail.com', + 'email_locale' => 'es', + ]); + + NotificationFacade::locale('fr')->send( + $recipient, new GreetingMailNotification() + ); + + $this->assertContains('bonjour', + app('swift.transport')->messages()[0]->getBody() + ); + } } class NotifiableLocalizedUser extends Model @@ -165,6 +244,21 @@ class NotifiableLocalizedUser extends Model public $timestamps = false; } +class NotifiableEmailLocalePreferredUser extends Model implements HasLocalePreference +{ + use Notifiable; + + protected $fillable = [ + 'email', + 'email_locale', + ]; + + public function preferredLocale() + { + return $this->email_locale; + } +} + class GreetingMailNotification extends Notification { public function via($notifiable)