Un prodotto, molti clienti: traduzioni per cliente con i tenant, un esempio pratico
Le traduzioni per cliente (dette anche override dei tenant) permettono a un prodotto di parlare la lingua di ogni cliente, in senso letterale e commerciale: la stessa app dice "paziente" per uno studio e "cliente" per un altro, indica qui una politica di cancellazione di 24 ore e lì una di 48, e mostra il nome del cliente invece del vostro, mentre tutto il resto resta un unico insieme condiviso di traduzioni. Questo articolo confronta i modi in cui i team lo costruiscono, poi ripercorre un’esecuzione reale: un progetto base, tre tenant cliente, i loro override, cosa è successo quando il testo base è cambiato, e come l’app carica il cliente giusto.
- Salvate la differenza, non una copia: un tenant eredita ogni chiave e traduzione della base e conserva solo i propri override. Le nuove chiavi della base e le modifiche alla base raggiungono ogni tenant che non le ha sovrascritte.
- Gli override non seguono la base: il testo di un cliente resta suo finché non viene eliminato nel tenant. "check tenants" nell’editor mostra chi sovrascrive una chiave, con il valore.
- Un ID di progetto per cliente: l’app carica il tenant che serve; i file sulla CDN uniscono già base e override, e i file di un tenant vengono ripubblicati quando la base cambia (con la pubblicazione automatica; altrimenti quando pubblicate la base).
- Solo gli override costano parole: il testo ereditato non viene contato due volte. I tenant partono dal piano Growth (5 inclusi).
Cinque modi in cui i team gestiscono le formulazioni per cliente
| Approccio | Come funziona | Funziona bene quando | Diventa difficile quando |
|---|---|---|---|
| Una copia per cliente | Duplicare i file di lingua o il progetto TMS per ogni cliente | uno o due clienti, un prodotto che cambia di rado | ogni modifica alla base va ricopiata in ogni copia, e le copie divergono |
| Codici locale personalizzati | Un codice come de-x-physio contiene solo le chiavi modificate; i18next ricade su de per il resto | una manciata di clienti, i file sono gestiti dagli sviluppatori | clienti per lingue moltiplicano i file; i traduttori vedono decine di pseudo-lingue |
| Un namespace per cliente | Un namespace physio-north caricato prima di quello condiviso | differiscono poche chiavi | l’ordine di ricerca vive nella configurazione i18next di ogni app (fallbackNS), e i namespace si moltiplicano per cliente |
| Interpolazione | {{brand}} o {{hours}} dentro le stringhe | differiscono solo dei valori (un nome di brand, un numero di ore) | terminologia o tono differiscono oltre le poche varianti che il context di i18next può coprire |
| Progetti tenant | Un progetto per cliente che eredita da un progetto base e salva gli override | molti clienti, ognuno con le proprie formulazioni, i propri utenti e il proprio accesso | gli override vanno controllati quando la base cambia; serve il piano Growth o superiore, e dei pacchetti oltre i tenant inclusi; e per clienti i cui prodotti differiscono davvero, progetti separati sono più semplici |
I primi quattro non richiedono strumenti particolari, e il secondo è una configurazione i18next perfettamente valida per pochi clienti. Il resto dell’articolo riguarda il quinto, in cui un cliente in più è un tenant in più, non una copia in più.
L’esempio
ClinicDesk è un’app per gli appuntamenti degli studi, venduta in white-label. I suoi tre clienti sono inventati per questo esempio:
| Cliente | Cosa vuole di diverso |
|---|---|
| Physio North | "Cliente" invece di "paziente", il proprio nome, la propria frase di supporto |
| Praxis am See | Un periodo di cancellazione di 48 ore invece di 24, il proprio nome, la propria frase di supporto |
| Smile Dental | Solo il proprio nome |
Il progetto base ha 15 chiavi in inglese, tedesco e francese (il francese aggiunge una forma plurale).
Passo 1: il progetto base
La base contiene le formulazioni del prodotto stesso: navigazione, pulsanti, il flusso di prenotazione, un SMS di promemoria, la politica di cancellazione. Abbiamo segnalato le 15 chiavi inglesi con una frase di contesto ciascuna, e la traduzione automatica ha compilato tedesco e francese. Per esempio, la politica è diventata "Sie können bis zu 24 Stunden vor Ihrem Termin kostenfrei stornieren." e "Vous pouvez annuler sans frais jusqu'à 24 heures avant votre rendez-vous."
Passo 2: un tenant per cliente
Nella pagina multi-tenant del progetto, ogni cliente riceve un tenant: un progetto suo, creato dalla base. Con can’t deviate from parent attivo (l’impostazione predefinita), un tenant ha sempre le lingue e i namespace della base, quindi una nuova lingua nella base compare in ogni tenant.
Ogni tenant ha il proprio ID di progetto, i propri utenti e le proprie chiavi API. Le persone di un cliente possono essere invitate solo al loro tenant e non vedono gli altri clienti; il vostro team, in quanto membri della vostra organizzazione, li raggiunge tutti.
Passo 3: le formulazioni di ogni cliente
Gli override sono normali modifiche dentro il tenant: nell’editor, tramite l’API oppure, come qui, tramite il server MCP. Abbiamo scritto gli override inglesi per ogni cliente: sei per Physio North, tre per Praxis am See, uno per Smile Dental:
| Chiave | Base (inglese) | Physio North | Praxis am See | Smile Dental |
|---|---|---|---|---|
app.title | ClinicDesk | Physio North | Praxis am See | Smile Dental |
nav.patients | Patients | Clients | (base) | (base) |
patients.add | Add patient | Add client | (base) | (base) |
patients.label | Patient | Client | (base) | (base) |
patients.search | Search patients | Search clients | (base) | (base) |
appointments.cancelPolicy | ... up to 24 hours before ... | (base) | ... up to 48 hours before ... | (base) |
footer.support | Questions? Contact the ClinicDesk support team. | Questions? Contact the Physio North front desk. | Questions? Call the practice team. | (base) |
Una cosa che non avevamo previsto: appena salvati gli override inglesi di Physio North, la traduzione automatica del tenant ne ha ricavato bozze in tedesco e francese, ognuna con un punteggio di confidenza e contrassegnata per la revisione. Abbiamo riscritto la frase di supporto in entrambe le lingue e lasciato le altre cinque bozze alla revisione del cliente. La politica di 48 ore di Praxis am See è stata tradotta in bozza allo stesso modo ("48 heures" in francese); abbiamo tenuto la bozza francese e sostituito quella tedesca. Succede quando il tenant ha la traduzione automatica attiva (al momento della creazione prende l’impostazione dalla base) e l’override arriva tramite l’API, la CLI o MCP come una chiave che il tenant non aveva ancora; un override digitato nell’editor, o una seconda modifica a un override esistente, non viene tradotto in bozza a meno che non richiediate una traduzione.
Nell’editor del tenant, il filtro overridden elenca ogni override, bozze automatiche comprese:
Passo 4: la base cambia
Poi abbiamo cambiato un testo base: la frase di supporto inglese è diventata "Questions? Our support team replies within one business day.", inviata richiedendo la traduzione automatica, quindi tedesco e francese sono stati tradotti di nuovo. (Senza quella richiesta, un testo sorgente modificato mantiene le sue traduzioni e le contrassegna per la revisione.) Due tenant sovrascrivono quella chiave, uno no:
- Smile Dental (nessun override) ha mostrato subito la nuova frase, in tedesco "Haben Sie Fragen? Unser Support-Team antwortet Ihnen innerhalb eines Werktages.", e i suoi file sulla CDN la contenevano senza che nessuno pubblicasse il tenant (la versione pubblica automaticamente; altrimenti il tenant viene ripubblicato quando pubblicate la base).
- Physio North e Praxis am See hanno mantenuto le proprie frasi. Una lettura raw del tenant (da parte di chi ha accesso alla base) mostra accanto a ogni override quale valore base sostituisce, così un agente o uno script può confrontarli.
È questa la regola da ricordare: le chiavi che un cliente non ha toccato seguono la base; le chiavi che un cliente ha cambiato restano sue finché l’override non viene eliminato, dopodiché il tenant eredita di nuovo la base. Gli override che si perdono un miglioramento della base sono il rischio principale di questo schema: quando il testo sorgente della base cambia, le traduzioni sovrascritte di un tenant vengono contrassegnate come da rivedere (a meno che la modifica non sia stata ritradotta, come in questa esecuzione), ma un override nella lingua sorgente non riceve alcun segnale. L’editor del progetto base ha una risposta diretta a "chi è coinvolto": selezionate una chiave e una lingua, e check tenants elenca, tra i tenant che potete aprire, quelli che la sovrascrivono, con i loro valori.
Passo 5: caricare il cliente giusto
I file pubblicati di ogni tenant sulla CDN uniscono già la base con gli override del cliente: il file inglese di Physio North dice "Clients" e "Physio North", quello di Smile Dental dice "Patients" e "Smile Dental". L’app deve solo sapere quale cliente serve, dal sottodominio, dal login o da un valore di configurazione, e passare al backend l’ID di progetto di quel tenant:
import i18next from 'i18next'
import LocizeBackend from 'i18next-locize-backend'
// one tenant project ID per customer; customers without own wording load the base
const TENANT_PROJECT_IDS = {
'physio-north': '<physio north tenant project id>',
'praxis-am-see': '<praxis am see tenant project id>',
'smile-dental': '<smile dental tenant project id>'
}
const BASE_PROJECT_ID = '<base project id>'
i18next.use(LocizeBackend).init({
fallbackLng: 'en',
backend: {
projectId: TENANT_PROJECT_IDS[customer] ?? BASE_PROJECT_ID,
version: 'latest'
}
})Poiché i file vengono caricati a runtime, la modifica di un cliente va online senza un rilascio della vostra app; quanto velocemente la vedono gli utenti dipende dalla cache, di cui parla aggiornare le traduzioni senza un nuovo deploy. Se invece includete le traduzioni nel bundle, scaricate allo stesso modo i file di ogni tenant nella vostra build.
Costi e accesso
- Piani: i tenant vengono fatturati con il loro progetto base. Growth ne include 5, Professional 10, Professional Plus 20, Enterprise 50; altri si aggiungono a pacchetti (prezzi).
- Parole: contano solo i valori sovrascritti, quindi le 14 chiavi inglesi che Smile Dental eredita non vengono addebitate di nuovo.
- Ripartizione per tenant: il pannello dei tenant mostra agli admin una stima di quanto vale l’uso di ogni tenant alle vostre tariffe, per rifatturare i costi ai clienti.
- Accesso: i clienti possono lavorare nel proprio tenant senza vedersi a vicenda; i membri della vostra organizzazione raggiungono ogni tenant.
A cosa fare attenzione
- Gli override congelano una chiave per quel cliente. Quando migliorate un testo base, controllate i tenant che lo sovrascrivono; eliminare un override restituisce la chiave alla base.
- Sovrascrivete ogni lingua che un cliente usa. Un override solo in inglese lascia le altre lingue del tenant sul testo base, quindi un cliente potrebbe leggere 48 ore in inglese e 24 in tedesco. Anche le bozze prodotte da un override sono override: contano come parole e non seguono più la base.
- Decidete chi può sovrascrivere cosa. Un cliente che modifica il proprio tenant può cambiare qualsiasi chiave, testi legali compresi. Tenete le formulazioni di compliance nella base e concordate con i clienti quali chiavi sono loro.
- Lingue per cliente. Con "can’t deviate from parent" disattivato, un tenant può avere lingue che la base non ha, e le lingue aggiunte alla base allora non gli vengono aggiunte automaticamente. Scegliete tenant per tenant.
- Prodotti diversi non sono tenant. Se le app di due clienti condividono poco più di una schermata di login, progetti separati sono più semplici.
Provatelo
La documentazione multi-tenant copre impostazioni e opzioni. Ogni account parte con una prova di 14 giorni con tutte le funzionalità e senza carta di credito, abbastanza per creare un progetto base e due tenant, sovrascrivere qualche chiave e caricare nella vostra app i file di ogni cliente.
Domande frequenti
Tenete un unico insieme base di traduzioni e salvate solo ciò che un cliente cambia sopra di esso. In Locize questo è un progetto tenant per cliente: eredita ogni chiave e traduzione del progetto base e conserva i propri override, i propri utenti e il proprio ID di progetto. L’app carica il tenant del cliente che sta servendo; i file che riceve uniscono la base con gli override di quel cliente.
L’override mantiene il suo valore finché qualcuno non lo elimina nel tenant; a quel punto il tenant eredita di nuovo il valore base. Le chiavi che il cliente non ha sovrascritto seguono le modifiche alla base. Quando il testo sorgente della base cambia, le traduzioni sovrascritte del tenant vengono contrassegnate come da rivedere (a meno che quella modifica non sia stata ritradotta), ma un override nella lingua sorgente stessa non riceve alcun segnale, quindi controllate gli override quando cambiate un testo base: nell’editor di Locize, "check tenants" elenca, tra i tenant che potete aprire, quelli che sovrascrivono la chiave selezionata, con i loro valori.
Ogni tenant ha il proprio ID di progetto. L’app decide quale cliente serve (dal sottodominio, dal login o da un valore di configurazione) e passa al backend di i18next l’ID di progetto del tenant di quel cliente; i clienti senza formulazioni proprie caricano il progetto base. I file sulla CDN uniscono già la base con gli override, quindi l’app non deve unire nulla.
Sì, per pochi clienti: date a ogni cliente un codice lingua personalizzato come de-x-physio che contiene solo le chiavi modificate, e lasciate che i18next ricada su de per tutto il resto. Funziona bene finché sono gli sviluppatori a gestire i file; diventa pesante quando cresce il numero di clienti moltiplicato per le lingue, perché ogni combinazione è un altro file e i traduttori vedono decine di pseudo-lingue.
I tenant vengono fatturati con il loro progetto base. Il piano Growth include 5 tenant, Professional 10, Professional Plus 20 ed Enterprise 50; altri si aggiungono a pacchetti. Le parole contano solo per i valori sovrascritti, quindi il testo che un tenant eredita non viene addebitato due volte, e il pannello dei tenant mostra una ripartizione dei costi per tenant.
Stanco di gestire le traduzioni a mano?
Locize è il backend di gestione delle traduzioni creato dal team di i18next: distribuzione via CDN, traduzione con AI, editing in-context, senza nuovi deploy.
Inizia la prova gratuita di 14 giorni