laravel-l10n

La ricerca non è ancora disponibile.

Nessun risultato per “”.

↑ ↓ per spostarti · ↵ per aprire Ricerca di Algolia

// routing

Route localizzate

Definisci i locale supportati da una route, scegli come applicare i prefissi di lingua e traduci URI e domini delle route.

Come funziona

Ogni route che marchi con lang() diventa la route canonica: mantiene il suo URI e il suo nome, e serve il fallback locale. Per ogni locale aggiuntivo, il package registra una route tradotta, una copia della route canonica con:

  • un URI con il prefisso del locale e, quando disponibile, tradotto tramite i tuoi file di lingua;
  • un nome composto dal nome canonico più il locale, come example.es;
  • il locale dell'applicazione impostato sulla sua lingua per ogni richiesta che serve.

Le route tradotte vengono generate dopo il boot di tutti i service provider, quindi definisci le tue route come sempre nei file di route e vengono rilevate automaticamente. Funzionano anche con la cache delle route.

Definire le route localizzate

Usa il metodo lang() per indicare quali locale deve supportare una route:

routes/web.php php
Route::get('/example', Controller::class)
    ->lang(['es', 'fr', 'it'])
    ->name('example');

Supponendo che il fallback locale sia en e che in lang/es/routes.php esista una traduzione spagnola per example, vengono registrate quattro route:

URI Nome Locale
/example example en
/es/ejemplo example.es es
/fr/example example.fr fr
/it/example example.it it

Le route francese e italiana non hanno una traduzione, quindi mantengono l'URI originale dopo il prefisso del locale. Vedi Tradurre gli URI delle route per aggiungerne una.

Il fallback locale

La route canonica serve il fallback_locale di Laravel (APP_FALLBACK_LOCALE nel .env). Deve corrispondere alla lingua in cui sono davvero scritti le tue route e i tuoi contenuti: se i tuoi URI sono in inglese, il fallback locale deve essere en.

Elencare il fallback locale in lang() non crea problemi: la route canonica lo serve già, quindi non viene registrata nessuna route in più.

routes/web.php php
// Same result as ->lang(['es']) when the fallback locale is 'en'
Route::get('/example', Controller::class)
    ->lang(['en', 'es']);

Gruppi di route

Per non ripetere le stesse lingue su ogni route, usa Route::lang()->group():

routes/web.php php
Route::lang(['es', 'it'])->group(function () {
    Route::get('/example', fn () => 'Hello, World!');
    Route::get('/another', fn () => 'Another route');
});

Tutte le route del gruppo ne ereditano i locale. Chiama lang() su una singola route per aggiungere altre lingue a quelle del gruppo:

routes/web.php php
Route::lang(['es', 'it'])->group(function () {
    Route::get('/example', fn () => 'Hello, World!'); // es, it
    Route::get('/another', fn () => 'Another route')
        ->lang(['fr']); // es, it, fr
});

lang() si combina con gli altri attributi dei gruppi, come middleware, prefissi e domini:

routes/web.php php
Route::middleware('auth')->lang(['es', 'it'])->group(function () {
    Route::get('/dashboard', DashboardController::class)->name('dashboard');
});

Il locale dell'applicazione

Ogni route localizzata imposta il locale dell'applicazione sulla propria lingua prima che venga eseguito il tuo codice:

  • una route tradotta usa il suo locale, quindi /es/ejemplo viene eseguita con app()->getLocale() uguale a es;
  • la route canonica usa il fallback locale, quindi /example viene eseguita con en;
  • le route senza lang() lasciano invariato il locale dell'applicazione, che per impostazione predefinita è APP_LOCALE.

Questo significa che __(), i messaggi di validazione, le date e tutto ciò che dipende dal locale seguono automaticamente l'URL. Con una traduzione spagnola in lang/es.json:

routes/web.php php
Route::get('/welcome', fn () => __('Welcome!'))
    ->lang(['es']);

// GET /welcome    → "Welcome!"
// GET /es/welcome → "¡Bienvenido!"

Il locale è già impostato quando viene eseguito il route model binding, quindi i tuoi binding possono risolvere slug tradotti o altri valori che dipendono dal locale.

Per leggere il locale della route corrente, usa $request->route()->locale(). Vedi Helper delle route.

Nomi delle route

Le route tradotte prendono il nome della route canonica, seguito da un punto e dal locale:

Route::get('/example', Controller::class)
    ->lang(['es', 'it'])
    ->name('example');

// Registered names: example, example.es, example.it

Raramente ti servono questi nomi direttamente. Chiama route('example') e il package sceglie la route per il locale corrente, oppure passa lang per sceglierne un'altra. Vedi Generazione degli URL.

Per controllare la route corrente, usa L10n::is('example') invece di Route::is('example'): corrisponde alla route canonica e a tutte le sue traduzioni. Vedi Corrispondenza delle route.

Anche le route senza nome vengono localizzate: il package assegna a loro, e alle loro traduzioni, un nome interno che inizia con generated::.

Strategia di routing

L'opzione route_strategy in config/l10n.php controlla come vengono applicati i prefissi di lingua. Le strategie sono tre:

  • prefix_except_default (predefinita) lascia senza prefisso il fallback locale e aggiunge il prefisso a tutti gli altri locale.
  • prefix aggiunge il prefisso a ogni locale, compreso il fallback, e non registra nessuna route senza prefisso.
  • no_prefix usa gli URI tradotti senza alcun prefisso di lingua.

Ecco come si confrontano per Route::get('/example')->lang(['es', 'it']), con una traduzione spagnola per example e nessuna italiana:

Locale prefix_except_default prefix no_prefix
en (fallback) /example /en/example /example
es /es/ejemplo /es/ejemplo /ejemplo
it /it/example /it/example non registrata

Con prefix, una richiesta a /example restituisce 404: il fallback locale si trova su /en/example come qualsiasi altra lingua. Con no_prefix, la route italiana avrebbe lo stesso URI di quella canonica, quindi viene saltata (vedi Collisioni con no_prefix in Tradurre gli URI delle route).

Per cambiare strategia, pubblica la configurazione del package:

php artisan vendor:publish --tag=l10n-config

Poi imposta l'opzione nel file pubblicato:

config/l10n.php php
return [
    'route_strategy' => 'prefix',
];

La strategia vale per tutte le route localizzate dell'applicazione.

Tradurre gli URI delle route

Gestisci le traduzioni delle route in un file routes.php per ogni lingua, dentro la cartella lang:

/lang
├── /es
│   └── routes.php
├── /fr
│   └── routes.php
└── /it
    └── routes.php

In ogni file, associa l'URI originale della route alla sua traduzione:

lang/es/routes.php php
return [
    'example' => 'ejemplo',
    'products/{product}' => 'productos/{product}',
];

Se per un locale non c'è una traduzione, l'URI originale viene usato così com'è.

Mantieni nell'URI tradotto i parametri della route con gli stessi nomi, così la route tradotta riceve gli stessi parametri di quella canonica. Vanno tradotti solo i segmenti statici.

Chiavi di binding personalizzate

Per le route con una chiave di binding personalizzata, ometti la chiave (:slug) sia dalla chiave di traduzione sia dall'URI tradotto:

Route::get('/article/{post:slug}', [PostController::class, 'show'])
    ->lang(['it']);
return [
    'article/{post}' => 'articolo/{post}',
];

La route localizzata continua a risolvere post tramite il suo slug.

Chiavi di route tradotte

Se è la chiave della route a essere tradotta, per esempio uno slug salvato per ogni locale, implementa il contratto HasLocalizedRouteKey sul model. Quando genera l'URL di una route localizzata, il package chiama getLocalizedRouteKey() passando il locale della route e il campo di binding. Questo esempio usa spatie/laravel-translatable:

app/Models/Post.php php
use Goodcat\L10n\Contracts\HasLocalizedRouteKey;
use Spatie\Translatable\HasTranslations;

class Post extends Model implements HasLocalizedRouteKey
{
    use HasTranslations;

    public array $translatable = ['slug'];

    public function getLocalizedRouteKey(string $locale, ?string $field = null): ?string
    {
        return $this->getTranslation($field ?? $this->getRouteKeyName(), $locale, false) ?: null;
    }
}
route('posts.show', ['post' => $post, 'lang' => 'it']); // "https://example.com/it/articolo/ciao-mondo"

Restituisci null quando il model non ha una traduzione per un locale. Il selettore di lingua, i link hreflang e il redirect al locale preferito saltano quel locale. Per route() e action(), vedi Chiavi di route localizzate mancanti.

Le richieste in ingresso vengono risolte dal binding del model. Per rispondere con un 404 quando il post non ha una traduzione, o quando il suo slug appartiene a un altro locale, cerca lo slug nel locale della route:

app/Models/Post.php php
public function resolveRouteBinding($value, $field = null): ?self
{
    $field ??= $this->getRouteKeyName();

    return $this->where("$field->".app()->getLocale(), $value)->first();
}

Per fare invece un redirect, lascia che il binding trovi lo slug in qualsiasi locale e manda il visitatore all'URL corretto:

app/Http/Controllers/PostController.php php
public function show(Request $request, Post $post)
{
    if ($request->route()->originalParameter('post') !== $post->getLocalizedRouteKey(app()->getLocale())) {
        return redirect()->route('posts.show', $post, 301);
    }

    // ...
}

Collisioni con no_prefix

Senza un prefisso di lingua, due route possono finire con lo stesso URI. Con la strategia no_prefix, una traduzione che condivide dominio e URI con la route canonica o con una traduzione precedente viene saltata:

routes/web.php php
// lang/es/routes.php has no translation for 'dashboard'
Route::get('/dashboard', DashboardController::class)
    ->lang(['es'])
    ->name('dashboard');

Qui /dashboard è servita solo dalla route canonica, con il fallback locale. Anche route('dashboard', ['lang' => 'es']) restituisce l'URL canonico. Per servire i visitatori spagnoli su un URL dedicato, aggiungi una traduzione per dashboard in lang/es/routes.php.

Traduzione dei domini

Se la tua applicazione usa il routing basato sui domini, puoi tradurre i domini negli stessi file di lingua routes.php. La chiave è il dominio originale:

lang/es/routes.php php
return [
    'example' => 'ejemplo',
    'example.com' => 'es.example.com',
];

Quando un locale ha un dominio tradotto, le sue route non hanno prefisso: è già il dominio a identificare la lingua. I locale senza un dominio tradotto mantengono il prefisso nel percorso sul dominio originale:

routes/web.php php
Route::domain('example.com')->lang(['es', 'it'])->group(function () {
    Route::get('/example', Controller::class);
});
Locale prefix_except_default prefix
en (fallback) example.com/example example.com/en/example
es (dominio tradotto) es.example.com/ejemplo es.example.com/ejemplo
it example.com/it/example example.com/it/example

Con la strategia prefix, il fallback locale mantiene il prefisso nel percorso sul dominio originale, perché non ha un dominio tradotto.

Cosa ereditano le route tradotte

Una route tradotta è una copia della sua route canonica, quindi mantiene tutto quello che hai definito su di essa:

  • il controller o la closure;
  • i middleware, compresi quelli ereditati dai gruppi;
  • i vincoli sui parametri definiti con where() e i valori predefiniti definiti con defaults();
  • le opzioni del route model binding, come le chiavi personalizzate e withTrashed();
  • le route Route::fallback(), le cui traduzioni sono anch'esse route di fallback.

Definisci la route una volta sola e ogni lingua si comporta allo stesso modo, cambiano solo URL e locale.

Questa pagina ti è stata utile?
Grazie per il feedback!
successivo Generazione degli URL