Translate queued mails (localization)

I have been struggling to get this done in a more efficient way. Currently I have it set up like this. Hopefully this helps someone in the future with this issue:

// 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
          )
     );
});

And use the following in your template:

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

Note: do not forget to restart your queue


If your emails inherits the built-in Illuminate\Mail\Mailable class you can build your own Mailable class that will take care of translations.

Create your own SendQueuedMailable class that inherits from Illuminate\Mail\SendQueuedMailable. Class constructor will take current app.location from config and remember it in a property (because laravel queues serializes it). In queue worker it will take the property back from config and set the setting to the current environment.

<?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);
    }
}

Then, create your own Mail class that inherits from 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)
        );
    }
}

And, voila, all your queued mailables inherited from App\Mailable class automatically will take care of current locale.


In Laravel 5.6 is a locale function added to Mailable: $infoMail->locale('jp'); Mail::queue($infoMail);