> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Paketübersetzungen überschreiben und aktualisieren

> Anhand des Übersetzungsladers von Laravel 13 erläutert: teilweises Überschreiben von PHP-Übersetzungen, gemeinsam genutzte Schlüssel bei JSON-Übersetzungen und Aktualisierungen, die veröffentlichte Übersetzungen nicht beschädigen.

## Ziel dieser Seite

Sie liefern die Meldungen Ihres Pakets in mehreren Sprachen aus und ermöglichen es der nutzenden Anwendung, nur die benötigten Texte zu ändern. Dabei behandeln Sie Übersetzungsschlüssel und Platzhalter als öffentliche API und klären, wie Anpassungen bei Paket-Updates erhalten bleiben.

Die [Lokalisierung](/de/localization) behandelt die grundlegende Verwendung in der Anwendung, die [Laravel-Paketentwicklung](/de/advanced/package-development) die Grundlagen von Registrierung und Veröffentlichung. Diese Seite geht auf die Implementierung von `ServiceProvider`, `FileLoader` und `Translator` in Laravel 13 ein.

<Info>
  `loadTranslationsFrom()` registriert den Ladeort, `publishes()` das Ziel einer Dateikopie. Damit Übersetzungen verwendet werden können, müssen Nutzer nicht zwingend `vendor:publish` ausführen.
</Info>

## PHP-Übersetzungen mit Namensraum ausliefern

Wenn Ihr Paket eigene Schlüssel haben soll, verwenden Sie das PHP-Array-Format zusammen mit einem Namensraum. Das folgende Beispiel zeigt ein Paket namens `Acme\Courier`.

```text theme={null}
courier/
├── src/
│   └── CourierServiceProvider.php
└── lang/
    ├── en/
    │   └── messages.php
    └── ja/
        └── messages.php
```

In `lang/ja/messages.php` legen Sie die japanischen Standardwerte ab.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => ':nameさんへの配送を受け付けました。',
        'failed' => '配送できませんでした。',
    ],
];
```

In `lang/en/messages.php` stellen Sie zusätzlich Englisch als Fallback bereit.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => 'Delivery to :name has been queued.',
        'failed' => 'Delivery failed.',
    ],
];
```

Registrieren Sie im `boot()` des Service Providers das Laden und optional die Veröffentlichung.

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');

        $this->publishes([
            __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
        ], 'courier-translations');
    }
}
```

Bei der Verwendung geben Sie Namensraum, Dateiname und Array-Schlüssel an. Als Sprachcode wird entsprechend der Laravel-Konfiguration `ja` verwendet. Das ist etwas anderes als das `jp` in den URLs dieser Dokumentationsseite.

```php theme={null}
echo __('courier::messages.delivery.queued', ['name' => '山田'], 'ja');
```

Der Namensraum `courier` ist das zweite Argument von `loadTranslationsFrom()`. Er wird nicht automatisch aus dem Composer-Paketnamen abgeleitet.

## PHP-Übersetzungen ersetzen nicht die ganze Datei

In der nutzenden Anwendung können Sie – beim Standard-Sprachverzeichnis – in `lang/vendor/courier/ja/messages.php` nur die zu ändernden Schlüssel eintragen. Auch wenn das Sprachverzeichnis geändert wurde, verwenden Sie den Pfad unterhalb von `$this->app->langPath('vendor/courier')`.

```php theme={null}
<?php

return [
    'delivery' => [
        'queued' => ':name様への配送予約が完了しました。',
    ],
];
```

In diesem Beispiel ändert sich nur `queued`; für `failed` wird weiterhin die japanische Übersetzung des Pakets verwendet.

### Ladereihenfolge des FileLoader

`ServiceProvider::loadTranslationsFrom()` registriert den Namensraum, nachdem der Translator aufgelöst wurde. Die Dateien selbst werden erst gelesen, wenn eine Übersetzung angefordert wird.

`FileLoader::loadNamespaced()` liest die Sprachdatei des registrierten Pakets und übergibt das Array an `loadNamespaceOverrides()`. Dort wird in jedem Sprachpfad des Loaders `vendor/{namespace}/{locale}/{group}.php` gelesen und per `array_replace_recursive()` ersetzt.

```mermaid theme={null}
flowchart TD
    A["courier::messages.delivery.queued<br>locale: ja"] --> B["lang/ja/messages.php<br>des Pakets"]
    B --> C["lang/vendor/courier/ja/messages.php<br>der Anwendung"]
    C --> D["Angegebene Schlüssel per<br>array_replace_recursive ersetzen"]
    D --> E["Übersetzungstext abrufen und<br>Platzhalter ersetzen"]
```

Der Standard-`TranslationServiceProvider` übergibt dem Loader den Sprachpfad des Frameworks und den der Anwendung in dieser Reihenfolge. Auch wenn eine Erweiterung zusätzliche Pfade registriert, hat bei gleichen Schlüsseln das später geladene Überschreibungs-Array Vorrang.

| Zustand | Ergebnis |
| - | - |
| Der Schlüssel ist in der Anwendung vorhanden | Dieser Wert überschreibt den Wert des Pakets |
| Die Datei ist vorhanden, aber der Schlüssel fehlt | Der Wert des Pakets für dieselbe Sprache bleibt erhalten |
| Der Schlüssel fehlt in der angeforderten Sprache | Normalerweise wird in der PHP-Übersetzung der `fallback_locale` gesucht |
| Der Schlüssel fehlt auch im Fallback | Standardmäßig wird der angeforderte Schlüssel zurückgegeben |

<Warning>
  Ist der Namensraum nicht registriert, gibt `FileLoader::loadNamespaced()` ein leeres Array zurück. Allein das Ablegen von Dateien in `lang/vendor/courier` gleicht eine fehlende Registrierung im Service Provider nicht aus. Registriert außerdem ein anderes Paket denselben Namensraum, wird der Ladeort ersetzt – wählen Sie daher einen kollisionsfreien Namen.
</Warning>

## JSON-Übersetzungen haben keinen paketeigenen Namensraum

Für JSON-Übersetzungen, bei denen Sätze als Schlüssel dienen, registrieren Sie das Verzeichnis wie folgt. Dies ist eine Alternative zu den oben gezeigten PHP-Übersetzungen.

```php theme={null}
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}
```

Ein Beispiel für `lang/ja.json` im Paket:

```json theme={null}
{
  "Courier delivery queued": "配送を受け付けました。"
}
```

```php theme={null}
echo __('Courier delivery queued', [], 'ja');
```

`loadJsonTranslationsFrom()` hat kein Argument für einen Namensraum. Registrierte JSON-Übersetzungen teilen sich denselben Schlüsselraum mit anderen Paketen und der Anwendung.

### Ziel für JSON-Überschreibungen ist die ja.json der Anwendung

`FileLoader::loadJsonPaths()` liest zuerst die registrierten JSON-Pfade, danach die regulären Sprachpfade, und führt sie per `array_merge()` zusammen. In der Standardkonfiguration überschreibt derselbe Textschlüssel in der `lang/ja.json` der Anwendung den Wert des Pakets.

```json theme={null}
{
  "Courier delivery queued": "配送予約が完了しました。"
}
```

* Verwenden mehrere Pakete denselben Textschlüssel, hat der Wert aus der später geladenen JSON-Datei Vorrang. Vermeiden Sie ein Design, das sich auf die Reihenfolge der Provider verlässt.
* `lang/vendor/courier/ja.json` ist kein Überschreibungsziel des Standard-JSON-Loaders. Wenn Sie die Veröffentlichungseinstellung für PHP unverändert für JSON übernehmen, wird dieser Ort nicht automatisch gelesen.
* Wenn Sie die JSON-Datei des Pakets per `publishes()` in die `lang/ja.json` der Anwendung kopieren, werden die Dateiinhalte nicht zusammengeführt. Damit bestehende Übersetzungen nicht beschädigt werden, beschreiben Sie ein Vorgehen, bei dem Nutzer nur die benötigten Schlüssel ergänzen.

<Warning>
  `Translator::get()` prüft zuerst die JSON-Datei der angeforderten Sprache und sucht, falls dort nichts gefunden wird, nach einem Schlüssel im PHP-Format. Anders als bei PHP-Übersetzungen wird nicht der Reihe nach bis zur JSON-Datei der Fallback-Sprache gesucht. Wenn Sie englische Sätze als JSON-Schlüssel verwenden, unterscheiden Sie dies vom Standardverhalten, bei dem ohne Übersetzung der ursprüngliche Schlüssel angezeigt wird.
</Warning>

Der Namensraum von PHP-Übersetzungen trennt PHP-Schlüssel von denen anderer Pakete. Da `Translator::get()` jedoch zuerst exakt übereinstimmende JSON-Schlüssel prüft, hat ein in JSON definierter Schlüssel wie `courier::messages.delivery.queued` Vorrang vor der PHP-Seite. In der Regel sollten Sie Satzschlüssel und Schlüssel im PHP-Format nicht vermischen.

## Veröffentlichte Übersetzungen aktualisieren, ohne sie zu beschädigen

Nutzern, die die PHP-Übersetzungen vollständig veröffentlichen möchten, können Sie einen auf das Ziel eingeschränkten Befehl empfehlen.

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-translations
```

Werden jedoch alle Standardwerte kopiert, gilt auch diese Kopie fortan als Überschreibung. Korrigieren Sie im Paket einen Tippfehler, bleibt der neue Wert unsichtbar, solange derselbe Schlüssel in der veröffentlichten Datei steht. Neue Schlüssel, die in der Kopie fehlen, werden hingegen vom Paket ergänzt.

<Tip>
  Wenn nur wenige Texte geändert werden sollen, lassen sich Updates leichter übernehmen, wenn Sie nicht alle Dateien veröffentlichen, sondern nur die benötigten Schlüssel in die Überschreibungsdatei aufnehmen. Dieses Vorgehen nutzt das teilweise Überschreiben von PHP-Übersetzungen.
</Tip>

Für die langfristige Wartung planen Sie Updates in folgender Reihenfolge:

1. **Schlüssel und Namensraum beibehalten** — Das Löschen oder Verschieben von Schlüsseln wirkt sich auf die `__()`-Aufrufe der Nutzer und auf die Überschreibungsziele aus. Erwägen Sie eine Übergangsphase, in der neue Schlüssel hinzugefügt und alte beibehalten werden.
2. **Platzhalter beibehalten** — Wird `:name` in `:recipient` geändert, muss auch das Ersetzungs-Array auf der aufrufenden Seite angepasst werden. Betrachten Sie dies nicht als reine Änderung der Übersetzungsdatei.
3. **Veröffentlichte Dateien per Diff prüfen** — Vergleichen Sie die Überschreibungen der Nutzer mit den neuen Standardwerten. Durch das Entfernen nicht mehr benötigter Überschreibungsschlüssel kehren Sie zum Wert des Pakets zurück.
4. **Bedingungsloses erneutes Veröffentlichen vermeiden** — Erneutes Veröffentlichen mit `--force` überschreibt die Anpassungen der Nutzer. Bei einem Design, das JSON in die Datei der Anwendung kopiert, können sogar andere Übersetzungen verloren gehen.
5. **In langlebigen Prozessen prüfen** — `Translator::load()` hält die Arrays pro Namensraum, Gruppe und Sprache in der Instanz. In Prozessen, in denen ein bereits geladener Translator weiterbesteht, wird nach einer Dateiänderung nicht zwangsläufig neu geladen. Starten Sie Worker usw. je nach Betrieb neu.

Die Auswahl des Ziels und die Optionen zum Überschreiben beim Veröffentlichen werden unter [Öffentliche Paket-Assets veröffentlichen und aktualisieren](/de/advanced/package-assets) ergänzt, die Beurteilung der Kompatibilität bei Versionsupdates unter [Versionskompatibilität von Paketen verwalten](/de/advanced/package-versioning).

## Prüfpunkte in der nutzenden Anwendung

Prüfen Sie in einer Testanwendung, in der der Service Provider registriert ist, die folgenden Kombinationen. Zum Aufbau einer Testumgebung innerhalb des Pakets siehe [Laravel-Pakete mit Orchestra Testbench testen](/de/advanced/package-testing).

| Fall | Zu prüfen |
| - | - |
| PHP-Übersetzungen nicht veröffentlicht | Japanisch und Englisch des Pakets werden abgerufen |
| Nur das japanische `queued` überschrieben | `queued` ändert sich, `failed` bleibt beim Standardwert |
| Schlüssel durch Paket-Update hinzugefügt | Auch Schlüssel, die in der bestehenden Überschreibungsdatei fehlen, werden abgerufen |
| Schlüssel fehlt in der angeforderten Sprache | PHP-Übersetzungen werden aus der konfigurierten Fallback-Sprache abgerufen |
| Gleicher Schlüssel in JSON definiert | In der Standardkonfiguration hat die JSON-Datei der Anwendung Vorrang |
| JSON nur in `lang/vendor/courier` abgelegt | In der Standardkonfiguration wirkt dies nicht als JSON-Überschreibung |
| Übersetzung mit `:name` | Stimmt mit dem Ersetzungs-Array des Aufrufers überein, keine unersetzten Zeichenketten bleiben übrig |

In Tests, die eine Überschreibungsdatei erst nach dem Laden anlegen, stellen Sie sicher, dass bereits geladene Ergebnisse des Translators keinen Einfluss haben. Legen Sie die Datei vor dem Abruf an oder verwenden Sie für jeden Fall eine neue Anwendungsinstanz.

## Herangezogene Primärquellen

Geprüft wurden die offizielle Dokumentation im aktuellen Standard-Branch `13.x` und die interne Implementierung im zum Zeitpunkt der Prüfung neuesten Release `v13.35.0`.

* [Offizielle Laravel-Dokumentation: Sprachdateien in Paketen](https://github.com/laravel/docs/blob/13.x/packages.md#language-files)
* [Offizielle Laravel-Dokumentation: Paketübersetzungen überschreiben](https://github.com/laravel/docs/blob/13.x/localization.md#overriding-package-language-files)
* [ServiceProvider: Registrierung von Übersetzungen](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php)
* [TranslationServiceProvider: Standard-Sprachpfade](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/TranslationServiceProvider.php)
* [FileLoader: rekursives Ersetzen bei PHP und Ladereihenfolge bei JSON](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/FileLoader.php)
* [Translator: JSON-vorrangiger Abruf und geladene Arrays](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Translation/Translator.php)
* [Offizielle Tests: Übersetzungslader](https://github.com/laravel/framework/blob/v13.35.0/tests/Translation/TranslationFileLoaderTest.php)


## Related topics

- [Laravel-Paketentwicklung](/de/advanced/package-development.md)
- [Weiterführende Themen](/de/advanced/index.md)
- [Paket-Views überschreiben und aktualisieren](/de/advanced/package-views.md)
- [Öffentliche Paket-Assets veröffentlichen und aktualisieren](/de/advanced/package-assets.md)
- [Konfiguration](/de/configuration.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.