All rules

Sheath rule

blade-prefer-lang-helper

Prefer {{ __() }} over the @lang directive.
Package
Core
Category
Blade
Default severity
info by default
Auto-fix
Auto-fix available

as a dangerous fix. See Auto-fix.

Part of the migration preset.

#Why

@lang('key') and {{ __('key') }} perform the same lookup, and Laravel's localization documentation uses the helper throughout. Settling on one keeps a search for a translation key finding every use of it.

The forms differ in how they escape output:

Form Compiles to Escapes
@lang('key') echo app('translator')->get('key') No
{{ __('key') }} echo e(__('key')) Yes
{!! __('key') !!} echo __('key') No

@lang renders translations without escaping them. The helper form escapes by default.

#Examples

#Bad

<h1>@lang('messages.welcome')</h1>
<p>@lang('messages.greeting', ['name' => $user->name])</p>

#Good

<h1>{{ __('messages.welcome') }}</h1>
<p>{{ __('messages.greeting', ['name' => $user->name]) }}</p>
{{-- When the translation really does contain markup --}}
<p>{!! __('messages.terms_html') !!}</p>

#Auto-fix

The fix is dangerous and only runs under --fix --dangerous, because it adds escaping that was not there before. A translation string containing HTML renders as markup through @lang and as visible tags through {{ }}.

{{-- before --}}
@lang('messages.welcome')
{{-- after --}}
{{ __('messages.welcome') }}

Review the run. Where a translation is meant to carry markup, change those to {!! __('...') !!} rather than reverting to @lang.

Review translations inside <script> tags manually. HTML escaping can turn an apostrophe into visible entity text such as &#039;. Move the translation out of the script when possible, or use {!! __('...') !!} when raw output is intentional.

#What is never rewritten

The block form is a different directive. It compiles to $__env->startTranslation() and translates its own body, so it is left alone:

@lang(['name' => $user->name])
Welcome back, :name.
@endlang

@lang with no arguments opens the same kind of block, and is also left alone.

#Notes

  • Reported wherever a standalone @lang appears, including inside an attribute.
  • Arguments are carried over exactly as written.
  • Both forms are current Laravel. This is a consistency preference rather than a defect check.

#Related Rules