Vai al contenuto principale
Tutta la documentazione

Lingue e localizzazione

OnlyTons parla inglese e italiano. L'interfaccia, le etichette di stato, i suggerimenti e il testo delle notifiche cambiano tutti insieme.

Cambiare lingua (per gli utenti)

  • Nelle pagine pubbliche — la home, /explore, le pagine dei terreni e la documentazione — usa i link 🇬🇧 EN / 🇮🇹 IT nell'intestazione. Cambiano l'indirizzo (?lang=it), quindi la pagina che stai leggendo in italiano è un link che puoi inviare a qualcun altro.
  • Nella pagina di accesso, usa il selettore di lingua sotto il modulo.
  • Una volta effettuato l'accesso, usa il selettore in fondo alla barra laterale.

La tua scelta viene ricordata: viene salvata nel tuo account (così ti segue tra i diversi dispositivi) e memorizzata nella cache del browser. La pagina viene ridisegnata immediatamente nella lingua scelta.

La bandiera accanto a ogni abbreviazione è solo decorativa: una bandiera indica un paese, non una lingua. Gli screen reader annunciano il nome completo della lingua ("IT — Italiano") e l'etichetta effettiva del link è l'abbreviazione di due lettere.

Cosa viene tradotto

  • Pulsanti, etichette dei moduli, stati vuoti/di errore, toast e suggerimenti.
  • Etichette di stato ed enum — fasi delle trattative, stati di offerta/richiesta, schemi di certificazione, stati di verifica, unità, ruoli e così via.
  • Testo delle notifiche — assemblato da modelli, così arriva nella tua lingua.

I dati di prodotto che inserisci — nomi delle organizzazioni, nomi dei prodotti, note in testo libero — vengono archiviati come li hai scritti e mostrati così come sono; non vengono tradotti automaticamente.

Come funziona (per chi mantiene il codice)

OnlyTons usa una localizzazione basata sulle preferenze, non un routing basato sull'URL. Non c'è deliberatamente nessun segmento /[lang]/… — ogni route mantiene il suo percorso e il locale attivo viene risolto da un cookie (inizializzato dal valore users.locale salvato dall'utente). Questo si adatta a un'app B2B autenticata dove ogni utente ha una preferenza archiviata, ed evita di ristrutturare l'intero albero delle route.

?lang= sulle pagine pubbliche

Il livello pubblico ha richiesto proprio l'intervento additivo previsto nel paragrafo precedente, limitato alle sole route pubbliche. Un crawler non invia cookie, quindi senza un override l'unica versione indicizzabile di / e /explore sarebbe stata quella inglese — su un prodotto il cui mercato principale è l'Italia.

  • ?lang=it è un override indicizzabile e condivisibile. Ha la precedenza sul cookie: la query string è l'espressione di intento più specifica, e un alternate hreflang che mostrasse in silenzio la lingua del cookie sarebbe una bugia detta al crawler.
  • Accept-Language è il fallback quando non ci sono né ?lang né cookie: il caso della prima visita (negotiate.ts, puro e testato).
  • Il proxy risolve tutto questo e lo passa a valle come HEADER DI RICHIESTA (x-onlytons-locale), mai come Set-Cookie. Un Set-Cookie su ogni risposta pubblica la rende non memorizzabile in nessuna cache condivisa, e il livello pubblico è costruito attorno alla cache. È anche l'unico meccanismo che arriva al layout radice, dove viene scritto <html lang>: nell'App Router i layout non possono leggere searchParams.
  • Il proxy rimuove l'header su ogni percorso non pubblico, così non può essere falsificato per sovrascrivere la preferenza salvata di un utente registrato.
  • Il selettore di lingua pubblico è un insieme di link, non un select, così gli URL alternativi sono nel markup e funziona anche senza JavaScript.

L'albero dell'app non cambia: dentro (app) il cookie resta l'unica fonte.

Gli elementi, tutti sotto apps/web/src/lib/i18n/:

FileRuolo
config.tsLocale supportati, default, nome del cookie, helper
messages/en.tsIl catalogo canonico dei messaggi (l'insieme delle chiavi)
messages/it.tsCatalogo italiano — tipizzato rispetto a en, così una chiave mancante non compila
messages/index.tsLookup nel dizionario + interpolazione dei {placeholder}
enum-labels.tsOverride in italiano dei *_LABELS colocati nello schema; l'inglese è il fallback
client.tsxI18nProvider + hook: useTranslate(), useLabels(), useLocale()
server.tsgetLocale(), getServerT(), getServerLabels() per i server component
actions.tssetLocaleAction — la server action che il selettore chiama (imposta il cookie + persiste users.locale)
negotiate.tsnegotiateLocale(Accept-Language) + resolvePublicLocale({lang, cookie, acceptLanguage}) — puro; il proxy lo usa per i percorsi pubblici

Regole pratiche quando aggiungi UI:

  • Client component → const { t } = useTranslate() e/o const labels = useLabels().
  • Server component → const t = await getServerT() / const labels = await getServerLabels().
  • Non scrivere mai una stringa rivolta all'utente fissa nel codice della logica. Aggiungi una chiave a messages/en.ts (e il suo valore italiano in messages/it.ts) e usa t("your.key"). I router e le librerie restituiscono codici leggibili dalla macchina; l'interfaccia li mappa in testo.
  • I nomi visualizzati degli enum restano colocati nel loro file di schema (inglese) e ricevono un override italiano in enum-labels.ts.

Aggiungere una lingua

  1. Aggiungi il codice a LOCALES in config.ts e un nome nativo a LOCALE_LABELS.
  2. Aggiungi un messages/<locale>.ts tipizzato : Messages (il compilatore elenca ogni chiave che ancora manca).
  3. Aggiungi un blocco di override in enum-labels.ts (oppure lascia che l'inglese faccia da fallback).

Tutto qui — il selettore, il cookie e il provider la riconoscono automaticamente.


Avanti: Glossario · Torna all'indice