Introduction
Sometimes you need to notify someone who isn't a User in your database — a one-off email to a prospect, an SMS to a shipping carrier's webhook endpoint, a Slack alert to a channel that isn't tied to any specific user. Laravel's Notification::route() is the escape hatch, and ->locale() makes sure the recipient gets the message in their language, not yours.
Key Concepts
- On-demand notification: A notification dispatched without a notifiable model. You pass the delivery addresses directly to
Notification::route(). - Localized notification: A notification rendered in a specific locale, overriding the app default for this one send.
Real World Context
A signup form that invites a friend needs to email someone who doesn't have an account yet. A status page needs to alert an ops Slack channel that isn't a Team model. A multilingual SaaS needs to email Japanese customers in Japanese even though the app default is English.
Deep Dive
On-demand delivery
phpuse Illuminate\Support\Facades\Notification; use App\Notifications\InvoiceOverdue; Notification::route('mail', 'billing@acme.example') ->route('slack', 'https://hooks.slack.com/services/...') ->route('vonage', '+15551234567') ->notify(new InvoiceOverdue($invoice));
Each route() call pairs a channel name with a delivery address. When notify() runs, Laravel builds a transient "anonymous notifiable" and dispatches the notification as usual.
Localizing a single send
php$user->notify( (new InvoiceOverdue($invoice))->locale('ja') );
Or from the facade:
phpNotification::locale('ja')->send($user, new InvoiceOverdue($invoice));
The notification is rendered with App::setLocale('ja') active, so every __('messages.greeting') call inside toMail() resolves against the Japanese translation files. After the send, the locale snaps back to the request default.
Per-user localization
If your User model stores a preferred locale, implement HasLocalePreference:
phpuse Illuminate\Contracts\Translation\HasLocalePreference; class User extends Authenticatable implements HasLocalePreference { public function preferredLocale(): string { return $this->locale ?? 'en'; } }
Now every notification sent to a User is auto-localized — no explicit ->locale() call needed.
Common Pitfalls
- Hardcoding recipient strings in your notification class — keep addresses on the caller side via
route(), so the notification class stays reusable. - Forgetting that
->locale()only affects translation lookups — it doesn't magically translate the static strings you wrote inline in theMailMessage. Run everything through__()ortrans()so localization actually kicks in.
Best Practices
- Implement
HasLocalePreferenceonUseronce — then every notification is auto-localized and you never forget. - Centralize webhook URLs in config — don't hardcode
https://hooks.slack.com/...in the controller.
Summary
Notification::route()sends to addresses that aren't bound to a model.->locale('ja')renders a single notification in a specific language.HasLocalePreferenceon the notifiable model auto-localizes every send.