Skip to main content

Obiettivo di questa pagina

Distribuire i messaggi di un pacchetto in più lingue, permettendo all’applicazione che lo utilizza di modificare solo i testi necessari. Vedremo anche come trattare chiavi di traduzione e placeholder come API pubblica e come preservare le personalizzazioni quando il pacchetto viene aggiornato. Localizzazione tratta le operazioni di base nell’applicazione, mentre Sviluppo di pacchetti Laravel tratta le basi della registrazione e della pubblicazione. Questa pagina entra nell’implementazione di ServiceProvider, FileLoader e Translator di Laravel 13.
loadTranslationsFrom() registra il percorso da cui caricare le traduzioni, mentre publishes() registra la destinazione in cui copiare i file. Per usare le traduzioni, l’utente non deve necessariamente eseguire vendor:publish.

Distribuire traduzioni PHP con un namespace

Se vuoi chiavi dedicate al pacchetto, usa il formato ad array PHP con un namespace. Di seguito l’esempio di un pacchetto chiamato Acme\Courier.
Prepara i valori predefiniti in giapponese in lang/ja/messages.php.
Prepara anche l’inglese di fallback in lang/en/messages.php.
Registra il caricamento e la pubblicazione facoltativa nel metodo boot() del service provider.
Chi utilizza il pacchetto specifica namespace, nome del file e chiave dell’array. Il codice della lingua segue la configurazione di Laravel e usa ja, che è diverso da jp usato negli URL di questo sito di documentazione.
Il namespace courier è il secondo argomento di loadTranslationsFrom(). Non viene determinato automaticamente dal nome del pacchetto Composer.

Le traduzioni PHP non sostituiscono l’intero file

Nell’applicazione che utilizza il pacchetto, con la directory delle lingue standard, puoi scrivere in lang/vendor/courier/ja/messages.php solo le chiavi da modificare. Anche se hai cambiato la directory delle lingue, usa il percorso sotto $this->app->langPath('vendor/courier').
In questo esempio cambia solo queued, mentre failed usa la traduzione giapponese del pacchetto.

Ordine di caricamento di FileLoader

ServiceProvider::loadTranslationsFrom() registra il namespace dopo la risoluzione del Translator. Il recupero effettivo dei file avviene quando viene richiesta una traduzione. FileLoader::loadNamespaced() legge i file di lingua del pacchetto registrato e passa l’array a loadNamespaceOverrides(). Qui vengono letti i file vendor/{namespace}/{locale}/{group}.php presenti in ciascun percorso delle lingue del loader e i valori vengono sostituiti con array_replace_recursive(). Il TranslationServiceProvider standard passa al loader il percorso delle lingue del framework e quello dell’applicazione, in quest’ordine. Anche se un’estensione registra percorsi aggiuntivi, per la stessa chiave prevale l’array di sovrascrittura caricato per ultimo.
Se il namespace non è registrato, FileLoader::loadNamespaced() restituisce un array vuoto. Mettere semplicemente i file in lang/vendor/courier non compensa la mancata registrazione nel service provider. Inoltre, se un altro pacchetto registra lo stesso namespace, la destinazione registrata viene sostituita: scegli quindi un nome che non generi conflitti.

Le traduzioni JSON non hanno un namespace dedicato al pacchetto

Per le traduzioni JSON, che usano il testo come chiave, registra la directory come segue. Si tratta di un’alternativa rispetto alle traduzioni PHP viste sopra.
Esempio di lang/ja.json del pacchetto.
loadJsonTranslationsFrom() non ha un argomento per il namespace. Le traduzioni JSON registrate condividono lo stesso spazio delle chiavi con gli altri pacchetti e con l’applicazione.

La destinazione della sovrascrittura JSON è il ja.json dell’applicazione

FileLoader::loadJsonPaths() legge prima i percorsi JSON registrati, poi i normali percorsi delle lingue, e li unisce con array_merge(). Nella configurazione standard, la stessa chiave stringa nel file lang/ja.json dell’applicazione sovrascrive il valore del pacchetto.
  • Se più pacchetti usano la stessa chiave stringa, prevale il valore del JSON caricato per ultimo. Evita progettazioni che dipendono dall’ordine dei provider.
  • lang/vendor/courier/ja.json non è una destinazione di sovrascrittura del loader JSON standard. Anche riutilizzando per il JSON la configurazione di pubblicazione pensata per il PHP, questo percorso non viene letto automaticamente.
  • Pubblicare con publishes() il JSON del pacchetto nel lang/ja.json dell’applicazione non unisce il contenuto dei file. Per non rompere le traduzioni esistenti, indica una procedura in cui l’utente aggiunge solo le chiavi necessarie.
Translator::get() controlla prima il JSON della lingua richiesta e, se non trova nulla, cerca la chiave come chiave in formato PHP. Non esiste un processo che, come per le traduzioni PHP, cerchi in sequenza fino al JSON della lingua di fallback. Se usi frasi in inglese come chiavi JSON, distingui questo caso dal comportamento standard per cui, in assenza di traduzione, viene mostrata la chiave originale.
Il namespace delle traduzioni PHP isola le chiavi PHP dagli altri pacchetti. Tuttavia, poiché Translator::get() cerca prima una corrispondenza esatta nel JSON, se nel JSON definisci una chiave come courier::messages.delivery.queued, questa avrà la precedenza sul lato PHP. Di norma conviene non mescolare chiavi testuali e chiavi in formato PHP.

Aggiornare senza rompere le traduzioni pubblicate

Agli utenti che vogliono pubblicare in blocco le traduzioni PHP puoi indicare un comando con un ambito ristretto.
Tuttavia, se copi tutti i valori predefiniti, da quel momento anche la copia diventa un insieme di valori di sovrascrittura. Anche se correggi un refuso nel pacchetto, il nuovo valore non sarà visibile finché la stessa chiave resta nel file pubblicato. Le nuove chiavi assenti dalla copia, invece, vengono integrate dal pacchetto.
Se devi modificare solo pochi testi, è più facile recepire gli aggiornamenti mettendo nel file di sovrascrittura solo le chiavi necessarie, invece di pubblicare tutti i file. È un approccio che sfrutta la sovrascrittura parziale delle traduzioni PHP.
Per la manutenzione a lungo termine, progetta gli aggiornamenti nel seguente ordine.
  1. Mantieni chiavi e namespace — Eliminare o spostare una chiave influisce sulle chiamate __() degli utenti e sulle destinazioni di sovrascrittura. Valuta di aggiungere nuove chiavi mantenendo le vecchie per un periodo di transizione.
  2. Mantieni i placeholder — Se cambi :name in :recipient, deve cambiare anche l’array di sostituzione del chiamante. Non considerarla una modifica che riguarda solo i file di traduzione.
  3. Confronta le differenze con i file pubblicati — Confronta le sovrascritture dell’utente con i nuovi valori predefiniti. Eliminando le chiavi di sovrascrittura non più necessarie si torna ai valori del pacchetto.
  4. Evita le ripubblicazioni incondizionate — La ripubblicazione con --force sovrascrive le personalizzazioni dell’utente. Con una progettazione che copia il JSON nel file dell’applicazione, potresti perdere anche altre traduzioni.
  5. Verifica nei processi persistenti — Translator::load() mantiene nell’istanza gli array per namespace, gruppo e lingua. Nei processi in cui resta un Translator che ha già caricato le traduzioni, la sola modifica dei file non garantisce che vengano ricaricate. Riavvia i worker o processi simili in base al tuo ambiente.
La scelta dell’ambito di pubblicazione e le opzioni di sovrascrittura sono approfondite in Asset pubblici e aggiornamento di un pacchetto, mentre la valutazione della compatibilità durante gli aggiornamenti di versione è trattata in Gestire la compatibilità tra versioni dei pacchetti.

Cosa verificare nell’applicazione che utilizza il pacchetto

In un’applicazione di verifica in cui è registrato il service provider, controlla le seguenti combinazioni. Per configurare l’ambiente di test all’interno del pacchetto, consulta Testare pacchetti Laravel con Orchestra Testbench. Nei test che creano file di sovrascrittura dopo il caricamento, fai in modo che i risultati già caricati dal Translator non influiscano. Prepara prima i file e poi recupera le traduzioni, oppure usa una nuova istanza dell’applicazione per ogni caso.

Fonti primarie consultate

Per la documentazione ufficiale è stato verificato l’ultimo branch predefinito 13.x, mentre per l’implementazione interna l’ultima release disponibile al momento della consultazione, v13.35.0.
Ultima modifica il 8 ottobre 2026