Zum Hauptinhalt springen

Was ist Lokalisierung?

Die Lokalisierung von Laravel stellt einen bequemen Mechanismus bereit, um Übersetzungen für unterschiedliche Sprachen abzurufen. Sie unterstützt mehrsprachige Anwendungen. Es gibt zwei Wege, Übersetzungen zu verwalten:
VorgehenEigenschaften
PHP-DateienSchlüssel-Wert-Arrays wie lang/ja/messages.php. Ideal, wenn Übersetzungen z. B. für Validierungsfehler nach Feature strukturiert werden sollen.
JSON-DateienÜbersetzungen direkt als Schlüssel in lang/ja.json. Empfohlen für Anwendungen mit vielen Übersetzungen.
Neue Laravel-Anwendungen enthalten kein Verzeichnis lang. Um es anzulegen, veröffentlichen Sie es mit dem Artisan-Befehl lang:publish.
php artisan lang:publish

Locale konfigurieren

Standard-Locale

Die Standardsprache legen Sie in config/app.php über locale fest. Üblich ist die Steuerung per Umgebungsvariable APP_LOCALE in der .env.
// config/app.php
'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
# .env
APP_LOCALE=de
APP_FALLBACK_LOCALE=en
fallback_locale ist die Ausweichsprache, falls keine Übersetzung für die aktuelle Sprache existiert.

Locale zur Laufzeit ändern

Mit App::setLocale() können Sie die Locale pro Request ändern.
use Illuminate\Support\Facades\App;

Route::get('/greeting/{locale}', function (string $locale) {
    if (! in_array($locale, ['en', 'de', 'fr'])) {
        abort(400);
    }

    App::setLocale($locale);

    // ...
});

Aktuelle Locale abfragen

use Illuminate\Support\Facades\App;

$locale = App::currentLocale();

if (App::isLocale('de')) {
    // Ausführung, wenn die aktuelle Sprache Deutsch ist
}

Sprachdateien anlegen

PHP-Datei

Legen Sie PHP-Dateien im Verzeichnis lang/{Sprachcode}/ an. Sie liefern ein Schlüssel-Wert-Array zurück.
/lang
    /en
        messages.php
    /de
        messages.php
<?php

// lang/de/messages.php

return [
    'welcome' => 'Willkommen in der Anwendung!',
    'goodbye' => 'Bis bald!',
];
Für Sprachen mit regionalen Varianten verwenden Sie ISO-15897-konforme Verzeichnisnamen, z. B. en_GB statt en-gb.

JSON-Datei

Bei vielen Übersetzungen empfiehlt sich das JSON-Format. Legen Sie im Verzeichnis lang/ eine JSON-Datei pro Sprachcode an.
/lang
    en.json
    de.json
Die Standard-Übersetzung (z. B. Englisch) dient als Schlüssel.
{
    "Welcome to our application!": "Willkommen in unserer Anwendung!",
    "I love programming.": "Ich programmiere leidenschaftlich gern.",
    "Logout": "Abmelden",
    "Dashboard": "Dashboard"
}
Da der englische Satz selbst als Schlüssel dient, funktioniert die englische Ausgabe automatisch. In Sprachen ohne eigene Übersetzungsdatei wird der Schlüssel (das englische Original) unverändert angezeigt.

Wann welches Format?

  • Wenn Sie Nachrichten z. B. für Validierungsfehler nach Feature strukturieren möchten
  • Wenn Sie Laravels eingebaute Übersetzungen (validation.php, auth.php usw.) überschreiben
  • Wenn Sie eine hierarchische Schlüsselverwaltung benötigen
// lang/de/validation.php
return [
    'required' => 'Das Feld :attribute ist erforderlich.',
    'email' => 'Das Feld :attribute muss eine gültige E-Mail-Adresse sein.',
];
  • Wenn viele UI-Texte vorkommen und das Ausdenken von Schlüsseln lästig wird
  • Wenn Sie Templates direkt auf Englisch schreiben und andere Sprachen per Übersetzungsdatei ergänzen
  • Wenn Sie Internationalisierung nachträglich einführen
{{-- Englisch direkt im Blade-Template --}}
{{ __('Welcome to our application!') }}

Übersetzungen abrufen

Helper __()

Am gebräuchlichsten. Bei PHP-Dateien schreiben Sie „Dateiname.Schlüssel”.
// PHP-Datei: Schlüssel 'welcome' in lang/de/messages.php
echo __('messages.welcome');
// => Willkommen in der Anwendung!

// JSON: Übersetzungsschlüssel wird direkt übergeben
echo __('I love programming.');
// => Ich programmiere leidenschaftlich gern.
Ist keine Übersetzung vorhanden, wird der Schlüssel unverändert zurückgegeben.
echo __('messages.not_exists');
// => messages.not_exists (Schlüssel wird 1:1 zurückgegeben)

Verwendung in Blade-Templates

In Blade-Templates verwenden Sie {{ __() }}.
{{-- PHP-Datei --}}
<h1>{{ __('messages.welcome') }}</h1>

{{-- JSON --}}
<button>{{ __('Logout') }}</button>

{{-- @lang-Direktive (nicht mehr empfohlen; nur zur Rückwärtskompatibilität) --}}
@lang('messages.welcome')
Die Direktive @lang gilt als veraltet. Aktuell wird {{ __() }} empfohlen.

Platzhalter

In Übersetzungen können Sie Platzhalter im Format :name verwenden.
// lang/de/messages.php
return [
    'welcome' => 'Willkommen, :name!',
    'greet'   => 'Hallo, :Name!',   // Anfangsbuchstabe groß
    'shout'   => 'HEY :NAME!',      // Komplett in Großbuchstaben
];
Das zweite Argument von __() enthält die Ersetzungswerte.
echo __('messages.welcome', ['name' => 'Tanaka']);
// => Willkommen, Tanaka!

echo __('messages.greet', ['name' => 'taro']);
// => Hallo, Taro! (Name mit großem Anfangsbuchstaben)

echo __('messages.shout', ['name' => 'taro']);
// => HEY TARO! (NAME komplett großgeschrieben)
In Blade-Templates funktioniert das genauso.
<p>{{ __('messages.welcome', ['name' => $user->name]) }}</p>

Pluralformen

Die Pluralregeln unterscheiden sich je nach Sprache. In Laravel trennen Sie Singular und Plural mit |.

Einfacher Plural

// lang/de/messages.php
return [
    'apples' => 'Es gibt einen Apfel|Es gibt mehrere Äpfel',
];
Auch in JSON möglich:
{
    "There is one apple|There are many apples": "Es gibt einen Apfel|Es gibt mehrere Äpfel"
}
Mit trans_choice() übergeben Sie die Anzahl.
echo trans_choice('messages.apples', 1);
// => Es gibt einen Apfel

echo trans_choice('messages.apples', 5);
// => Es gibt mehrere Äpfel

Pluralformen mit Bereich

Detailliertere Bereichsangaben sind möglich.
'apples' => '{0} Keine Äpfel|[1,19] Ein paar Äpfel|[20,*] Viele Äpfel',
echo trans_choice('messages.apples', 0);
// => Keine Äpfel

echo trans_choice('messages.apples', 10);
// => Ein paar Äpfel

echo trans_choice('messages.apples', 50);
// => Viele Äpfel

Platzhalter in Pluralformen

Mit :count geben Sie die Anzahl aus. Zusätzliche Werte übergeben Sie im dritten Argument.
// lang/de/messages.php
return [
    'minutes_ago' => '{1} vor :value Minute|[2,*] vor :value Minuten',
    'items'       => ':count Artikel vorhanden',
];
echo trans_choice('messages.minutes_ago', 5, ['value' => 5]);
// => vor 5 Minuten

echo trans_choice('messages.items', 3);
// => 3 Artikel vorhanden

Sprachdateien von Paketen überschreiben

Für Sprachdateien von Drittanbieter-Paketen können Sie in lang/vendor/{Paketname}/{Sprachcode}/ gleichnamige Dateien ablegen, um Übersetzungen zu überschreiben. Beispiel: englische Nachrichten des Pakets skyrim/hearthfire anpassen.
lang/
└── vendor/
    └── hearthfire/
        └── en/
            └── messages.php
// lang/vendor/hearthfire/en/messages.php
return [
    'welcome' => 'Angepasste Nachricht',
    // Nur die Schlüssel definieren, die überschrieben werden. Alle übrigen kommen aus der Originaldatei.
];

Praxisbeispiel: Locale-Umschaltung per Middleware

Beispiel einer Middleware, die die Locale anhand von URL, Session oder Nutzerpräferenz umschaltet.
1

Middleware erzeugen

php artisan make:middleware SetLocale
2

Middleware implementieren

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    public function handle(Request $request, Closure $next): Response
    {
        // Unterstützte Sprachen
        $supportedLocales = ['de', 'en'];

        // Locale aus der Session verwenden, falls vorhanden
        $locale = $request->session()->get('locale');

        // Sonst Accept-Language des Browsers heranziehen
        if (! $locale) {
            $browserLocale = substr($request->getPreferredLanguage($supportedLocales) ?? 'de', 0, 2);
            $locale = in_array($browserLocale, $supportedLocales) ? $browserLocale : 'de';
        }

        App::setLocale($locale);

        return $next($request);
    }
}
3

Middleware registrieren

Registrieren Sie die Middleware in bootstrap/app.php.
use App\Http\Middleware\SetLocale;

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(SetLocale::class);
})
4

Route zum Umschalten der Locale

// routes/web.php
Route::post('/locale/{locale}', function (string $locale) {
    if (! in_array($locale, ['de', 'en'])) {
        abort(400);
    }

    session(['locale' => $locale]);

    return back();
})->name('locale.switch');
5

Buttons im Blade-Template

<div>
    <form method="POST" action="{{ route('locale.switch', 'de') }}">
        @csrf
        <button type="submit">Deutsch</button>
    </form>

    <form method="POST" action="{{ route('locale.switch', 'en') }}">
        @csrf
        <button type="submit">English</button>
    </form>
</div>

Beispielhafter Aufbau der Sprachdateien

lang/
├── de.json          # JSON (UI-Texte)
├── en.json
├── de/
│   └── validation.php   # PHP-Datei (Validierung)
└── en/
    └── validation.php
// lang/de.json
{
    "Dashboard": "Dashboard",
    "Login": "Anmelden",
    "Logout": "Abmelden",
    "Welcome, :name!": "Willkommen, :name!",
    "Save": "Speichern",
    "Cancel": "Abbrechen",
    "Are you sure?": "Sind Sie sicher?"
}
{{-- resources/views/layouts/app.blade.php --}}
<nav>
    <a href="{{ route('dashboard') }}">{{ __('Dashboard') }}</a>
    <span>{{ __('Welcome, :name!', ['name' => auth()->user()->name]) }}</span>

    <form method="POST" action="{{ route('logout') }}">
        @csrf
        <button type="submit">{{ __('Logout') }}</button>
    </form>
</nav>

Zusammenfassung

FormatDateipfadBeispielschlüsselAbruf
PHP-Dateilang/de/messages.php'welcome' => '...'__('messages.welcome')
JSONlang/de.json"Welcome": "..."__('Welcome')
Funktion/MethodeZweck
__('key')Übersetzung abrufen (Helfer)
trans('key')Alternativhelfer zu __()
trans_choice('key', $count)Übersetzung mit Pluralformen
App::setLocale('de')Locale pro Request setzen
App::currentLocale()Aktuelle Locale abfragen
App::isLocale('de')Aktuelle Locale prüfen
{{-- Basis --}}
{{ __('messages.welcome') }}

{{-- Mit Platzhalter --}}
{{ __('messages.welcome', ['name' => $user->name]) }}

{{-- Pluralformen --}}
{{ trans_choice('messages.apples', $count) }}
Zuletzt geändert am 13. Juli 2026