Se usi Laravel per progetti un po’ più complessi del classico “todo list”, prima o poi ti scontri con il sistema di traduzioni. Funziona bene, è flessibile, ma ha le sue particolarità — e se non sai dove mettere le mani rischi di impazzire davanti a un “These credentials do not match our records” che continua a spuntare in inglese anche se hai già scritto la tua bella frase in italiano.
Vediamo come funziona davvero, senza fumo negli occhi.
Due strade: JSON e file PHP
Laravel supporta due approcci per le traduzioni:
1. File JSON (resources/lang/it.json)
- È un file unico per lingua.
- La chiave è la stringa letterale in inglese, il valore è la traduzione.
- Esempio:
{ "Log in": "Accedi", "Remember me": "Ricordami" } - Usato soprattutto dalle viste generate da Breeze, Jetstream e compagnia bella, che scrivono direttamente
__('Log in')o__('Remember me').
È semplice e veloce: traduci stringa per stringa senza namespace.
2. File PHP (resources/lang/it/auth.php, validation.php, ecc.)
- Qui le chiavi sono logiche, non testuali.
- Esempio per l’autenticazione:
<?php return [ 'failed' => 'Le credenziali non corrispondono ai nostri dati.', 'password' => 'La password fornita non è corretta.', ]; - In questo caso il codice chiama
__('auth.failed')invece della stringa intera.
È il sistema usato da Laravel “interno”: errori di validazione, messaggi di login, reset password, ecc.
Locale e fallback
Le traduzioni vengono lette in base al locale impostato.
- In
config/app.php:'locale' => 'it', 'fallback_locale' => 'en', - Oppure nel
.env:APP_LOCALE=it
Attenzione: se hai fatto php artisan config:cache, il .env non viene più letto direttamente, quindi ti conviene hardcodare locale in config/app.php o ripulire la cache.
La cache, maledetta cache
Se traduzioni e locale non cambiano, il 90% delle volte è colpa della cache.
Ripulire è la prima cosa da fare:
php artisan optimize:clear
php artisan config:clear
php artisan cache:clear
php artisan view:clear
Dopo, ricarica la pagina con un hard refresh del browser.
Se vuoi essere ancora più sicuro, testa in Tinker:
php artisan tinker
>>> app()->getLocale()
"it"
>>> __('auth.failed')
"Le credenziali non corrispondono ai nostri dati."
Se qui funziona, funziona anche nel browser.
JSON o PHP? Quando usare cosa
- JSON → per le label e i testi “visibili” nelle view (
Log in,Forgot your password?). - PHP → per i messaggi di sistema (
auth.failed, errori di validazione, reset password).
Puoi usarli anche insieme senza problemi: Laravel li fonde.
Personalizzare i messaggi di sistema
Vuoi cambiare il testo dell’errore di login? Vai in resources/lang/it/auth.php:
'failed' => 'Utente o password non validi.',
Vuoi tradurre la frase lunga del “Forgot your password?”?
Mettila nel JSON:
{
"Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Hai dimenticato la password? Nessun problema: inserisci la tua email e ti invieremo un link per reimpostarla."
}
Debugging: checklist rapida
- Locale impostato in
config/app.php - Cache ripulita (
optimize:clear,config:clear, ecc.) - Stringa giusta nel file giusto (
auth.failednei PHP, testi letterali nel JSON) - Test con Tinker:
__('auth.failed')deve restituire italiano
Conclusione
Il sistema di traduzione di Laravel è flessibile, ma non sempre intuitivo se non sai la differenza tra file JSON e file PHP namespaced.
La regola è semplice: UI nel JSON, messaggi di sistema nei PHP. E quando non funziona… la colpa è quasi sempre della cache.


