0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LaravelのMailalbeクラスのlocale()はsubjectには効かずにbodyのみしか言語切り替えできない

Last updated at Posted at 2025-10-06

ドキュメント等にも書いてなかったのでLaravelでメールの多言語化対応する方の参考になれば!

結論

Mail::to()->locale()メール本文のみに適用され、subjectには効かない。
→ 理由はsubjectの翻訳タイミングがMailableクラスのインスタンス生成時に確定してしまうから

本文は実際にメールが送信される時点で翻訳されるため、locale()の影響を受ける

Mailableクラスでlocale情報を受け取りそれをもとにtrans()の第3引数に指定すると確実

メール送信の流れ

1. Mailableインスタンス生成
   ↓
   [envelope()実行 → subject翻訳] ← この時点でアプリのlocaleで翻訳される
   ↓
2. Mail::to()->locale('ja')->send()
   ↓
   [locale設定を保存]
   ↓
3. キューに入る
   ↓
4. 実際の送信時
   ↓
   [content()実行 → 本文翻訳] ← この時点で指定されたlocaleで翻訳される

何が起きているか

Mailableクラスの構造(Laravel 9以降)

class WelcomeMail extends Mailable
{
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: __('mail.welcome_subject'),  // ①
        );
    }

    public function content(): Content
    {
        return new Content(
            view: 'emails.welcome',  // ②
        );
    }
}

① envelope()のsubject翻訳タイミング

  • envelope()メソッド実行時に__('mail.welcome_subject')が実行される
  • この時点では現在のアプリケーションのlocaleが使われる
  • 翻訳された文字列がEnvelopeオブジェクトとして保存される

② content()の本文翻訳タイミング

  • viewは実際にレンダリングされるまで翻訳されない
  • locale()で指定されたlocaleが送信時に適用される
  • そのため、正しいlocaleで翻訳される

コード例

// 現在のアプリlocaleが'en'の場合

$mail = new WelcomeMail();
// この時点でenvelope()が実行され、subjectは'Welcome!'(英語)に確定

Mail::to('user@example.com')
    ->locale('ja')
    ->send($mail);

// 結果:
// subject: "Welcome!" (英語のまま) ❌
// 本文: 日本語で表示される ✅

解決方法

Constructorでlocaleを受け取り、trans()で明示的に指定

<?php

namespace App\Mail;

use App\Enums\LanguageCode;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class WelcomeMail extends Mailable implements ShouldQueue
{
    use Queueable;
    use SerializesModels;

    /**
     * Create a new message instance.
     *
     * @param string $userName ユーザー名
     * @param LanguageCode $languageCode 言語コード
     */
    public function __construct(
        private readonly string $userName,
        private readonly LanguageCode $languageCode
    ) {
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: trans('mail.welcome_subject', [], $this->languageCode->value),
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            text: 'emails.welcome',
            with: [
                'userName' => $this->userName,
                'greeting' => trans('mail.welcome_greeting', [], $this->languageCode->value),
            ],
        );
    }
}

使用例

// コントローラーやサービスクラスで
$userLanguage = LanguageCode::from($user->language);

Mail::to($user->email)
    ->locale($userLanguage->value)
    ->send(new WelcomeMail($user->name, $userLanguage));
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?