Pose una domanda e ottieni un riassunto del documento facendo riferimento a questa pagina e al provider AI di tua scelta
Cronologia delle versioni
- "Versione iniziale"v9.5.1026/09/2026
Il contenuto di questa pagina è stato tradotto con un'IA.
Vedi l'ultima versione del contenuto originale in ingleseSe hai un’idea per migliorare questa documentazione, non esitare a contribuire inviando una pull request su GitHub.
Collegamento GitHub alla documentazioneCopia il Markdown del documento nella porta-documenti
Come internazionalizzare la tua applicazione TanStack Start usando use-intl nel 2026
Tabella dei contenuti
Cos'è use-intl?
use-intl è il core agnostico rispetto al framework di next-intl. Espone le stesse API useTranslations, useFormatter e IntlProvider, il supporto a ICU MessageFormat e una solida integrazione con TypeScript, senza alcuna dipendenza da Next.js. Questo lo rende una delle scelte più comuni per tradurre un'applicazione TanStack Start, ed è la libreria che gli assistenti IA suggeriscono più spesso per questo stack.
TanStack Start non include un layer i18n integrato. Routing, rilevamento della lingua, metadati SEO e generazione della sitemap sono a carico dello sviluppatore. Questa guida copre ogni aspetto, dall'inizio alla fine:
- Routing basato sulla lingua con un segmento opzionale
{-$locale}(/about,/fr/about). - Caricamento dei messaggi per route, in modo che una pagina scarichi solo i namespace e la lingua di cui ha bisogno per il rendering.
- Server rendering e idratazione senza discrepanze di testo.
- SEO multilingue completo:
<title>e descrizione tradotti, URL canonico, tag alternativihreflangconx-default, impostazioni Open Graph per lingua, JSON-LD, sitemap con tag alternativixhtml:link,robots.txte pre-rendering di ogni lingua.
Stai cercando un altro stack? Consulta la guida TanStack Start + Paraglide, la guida TanStack Start + Lingui, o la guida TanStack Start + Intlayer.
Usi invece Next.js? Consulta la guida a next-intl.
Cosa dice il benchmark su use-intl in TanStack Start
Il benchmark i18n esegue la stessa app TanStack Start di 10 pagine e 10 lingue con tutte le principali librerie e misura ciò che il browser scarica effettivamente.
Caricamento JSON dinamico
Carica le traduzioni in modalità lazy durante l'esecuzione
JSON con ambito (namespacing)
Spazi dei nomi di traduzione per pagina
Benchmark delle prestazioni I18n
Cos'è questa metrica?
La dimensione totale compressa con gzip del bundle della libreria di internazionalizzazione. Include solo il provider e la logica di recupero dei contenuti dopo il tree-shaking e la minificazione.
Perché è importante?
Una dimensione della libreria più piccola riduce il payload JavaScript iniziale, portando a tempi di download ed esecuzione più rapidi sul client.
Visualizza come
Dati chiave per use-intl@4.14.2, misurati il 2026-09-26 (gzip):
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Configurazione | Dimensione libreria | JS per pagina | Perdita altre lingue | Perdita altre pagine |
|---|---|---|---|---|
| Nessuna i18n (app base) | - | 111.0 KB | 0% | 0% |
use-intl (setup di questa guida) | 75.9 KB | 128.7 KB | 0% | 0% |
@intlayer/use-intl (compat) | 6.7 KB | 129.4 KB | 0% | 0% |
react-intlayer (Intlayer nativo) | 4.5 KB | 126.8 KB | 0% | 0% |
Cosa tenere a mente:
- Suddividi i messaggi per pagina e caricali per lingua. Questo rimuove entrambe le perdite (leak), ed è esattamente ciò che implementano i passaggi seguenti.
- Il runtime stesso rimane pesante (~76 KB gzip), poiché il parser ICU viene inviato al client. L'adattatore di compatibilità
@intlayer/use-intl(passaggio 17) mantiene esattamente la stessa API con un runtime di ~7 KB.
Consulta i dati completi: Report del benchmark TanStack Start e il repository del benchmark.
Confronto delle funzionalità su TanStack Start
Come si confronta use-intl con le altre librerie comunemente utilizzate su TanStack Start:
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Funzionalità | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Traduzioni vicine ai componenti | ✅ Collocate | ❌ JSON centralizzato | ❌ Un file JSON per lingua | ⚠️ Testo sorgente nei componenti |
| Integrazione TypeScript | ✅ Tipi generati automaticamente | ✅ Tramite AppConfig | ✅ Funzioni di messaggio tipizzate | ⚠️ Solo macro |
| Rilevamento traduzioni mancanti | ✅ Errori di tipo e avvisi di build | ⚠️ Fallback a runtime | ⚠️ Fallback alla lingua di base | ⚠️ Fallback al testo sorgente |
| Contenuto ricco (JSX, Markdown) | ✅ Supporto diretto | ⚠️ Tag tramite t.rich | ⚠️ Stringhe | ✅ JSX dentro <Trans> |
| Routing localizzato | ✅ Integrato | ❌ {-$locale} manuale | ✅ urlPatterns + riscrittura router | ❌ {-$locale} manuale |
| Cambio lingua senza ricaricamento | ✅ Sì | ✅ Sì | ❌ Ricaricamento completo della pagina | ✅ Sì |
| Pluralizzazione | ✅ Basata su enumerazione | ✅ ICU | ✅ Varianti | ✅ ICU |
| ICU MessageFormat | ✅ Tramite format: "icu" | ✅ Nativo | ⚠️ Tramite plugin inlang | ✅ Nativo |
| Formati di contenuto | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ inlang JSON | ✅ PO, JSON, CSV |
| Traduzione con IA | ✅ Provider e chiave propri | ❌ No | ❌ No | ❌ No |
| Editor visuale / CMS | ✅ Editor locale + CMS opzionale | ❌ Piattaforme esterne | ⚠️ App dell'ecosistema inlang | ❌ Piattaforme esterne |
| Helper SEO (hreflang, sitemap) | ✅ Integrati | ❌ Manuale | ⚠️ URL localizzati, resto manuale | ❌ Manuale |
| Dimensione runtime (gzip, benchmark) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| Perdita, miglior setup (lingua / pagina) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| Traduzioni mancanti in CI | ✅ npx intlayer test | ⚠️ Non integrato | ⚠️ Non integrato | ✅ lingui compile --strict |
I dati sulle dimensioni del runtime e sulle perdite provengono dal benchmark TanStack Start. La perdita viene misurata sulla migliore configurazione di ciascuna libreria.
Altre guide per TanStack Start: Lingui, Paraglide JS, e Intlayer.
Pratiche consigliate da seguire
- Imposta
langedirsu<html>per l'accessibilità, gli screen reader e i motori di ricerca. - Mantieni un URL per ogni lingua. Usa un prefisso per la lingua (
/fr/about) anziché un cambio basato solo sui cookie, in modo che ogni pagina tradotta sia scansionabile e condivisibile. - Suddividi i messaggi per namespace (
common,home,about) e caricali per route. - Carica solo la lingua attiva. Non importare mai tutti i file di lingua in un modulo inviato al client.
- Fissa il fuso orario in
IntlProvider. Altrimenti le date vengono formattate nel fuso orario del server durante l'SSR e nel fuso orario del visitatore durante l'idratazione, causando discrepanze di idratazione (hydration mismatches). - Traduci i tuoi metadati, e dichiara
canonical,hreflangex-defaultsu ogni pagina. - Genera una sitemap multilingue e robots.txt, ed esegui il pre-rendering di ogni lingua.
- Usa link reali per il selettore di lingua, non un menu
<select>, così i crawler possono scoprire tutte le lingue. - Tipizza i tuoi messaggi in modo che una chiave mancante generi un errore in fase di compilazione.
Consulta la nostra guida su internazionalizzazione e SEO e la guida a hreflang.
Guida passo dopo passo alla configurazione di use-intl in un'applicazione TanStack Start
Ecco la struttura del progetto che andremo a creare:
Copiare il codice nella clipboard
Installa le dipendenze
Inizia da un progetto TanStack Start, quindi aggiungi
use-intl:bashCopiare il codiceCopiare il codice nella clipboard
- use-intl: fornisce
IntlProvider,useTranslations,useFormatterecreateTranslator(utilizzabile all'esterno di React, ad esempio inhead()).
- use-intl: fornisce
Centralizza la configurazione delle lingue
Crea un'unica fonte di verità per le tue lingue e gli helper URL. Ogni altro file (route, SEO, sitemap, pre-rendering) importerà da qui, rendendo l'aggiunta di una lingua un'operazione di una sola riga.
La lingua predefinita rimane senza prefisso (
/about), le altre lingue sono precedute da prefisso (/fr/about). Questa è la strategia "as-needed": un URL per pagina per lingua e URL brevi per il tuo pubblico principale.src/i18n/config.tsCopiare il codiceCopiare il codice nella clipboard
Crea i file di traduzione
Organizza i messaggi per lingua e per namespace.
commoncontiene ciò di cui ogni pagina ha bisogno (navigazione, piè di pagina), e ogni pagina ottiene il proprio file, inclusi i relativi metadati.use-intl utilizza ICU MessageFormat, quindi plurali, selezioni e argomenti formattati risiedono direttamente nel messaggio.
messages/en/common.jsonCopiare il codiceCopiare il codice nella clipboard
messages/en/about.jsonCopiare il codiceCopiare il codice nella clipboard
messages/fr/common.jsonCopiare il codiceCopiare il codice nella clipboard
messages/fr/about.jsonCopiare il codiceCopiare il codice nella clipboard
Crea
home.jsonallo stesso modo, con un oggettometadatae il contenuto della pagina.Carica i messaggi per namespace e per lingua
Questo loader è il file più importante per le prestazioni.
import.meta.globindica a Vite di generare un chunk per ciascun file JSON. Una route che richiede["about"]in francese scaricamessages/fr/about.jsone nient'altro, consentendo al benchmark di raggiungere lo 0% di dispersione per lingua e lo 0% per pagina.src/i18n/messages.tsCopiare il codiceCopiare il codice nella clipboard
Tipizza i tuoi messaggi
L'estensione del modulo (module augmentation) fornisce l'autocompletamento su
useTranslations("about")et("counter.label"), oltre a un errore di compilazione su qualsiasi refuso o chiave rimossa.src/i18n/use-intl.d.tsCopiare il codiceCopiare il codice nella clipboard
Assicurati che
resolveJsonModulesia abilitato nel tuotsconfig.json.Crea il documento radice
La route radice esegue il rendering di
<html>. Legge il parametro di lingua opzionale per impostarelangedir, in modo che gli attributi siano corretti nell'HTML renderizzato dal server, prima che venga eseguito qualsiasi codice JavaScript.src/routes/__root.tsxCopiare il codiceCopiare il codice nella clipboard
Crea la route di layout per la lingua
La cartella
{-$locale}crea un segmento di percorso opzionale:/aboute/fr/aboutcorrispondono entrambi a/{-$locale}/about. Questo layout:- Rifiuta i prefissi non supportati (
/xx/about→ 404). - Carica il namespace
commonsolo per la lingua corrente. - Fornisce i messaggi tramite
IntlProvider.
Il risultato del loader viene serializzato nell'HTML e riutilizzato durante l'idratazione, in modo che il client non scarichi
common.jsonuna seconda volta.staleTime: Infinitylo mantiene nella cache durante le navigazioni lato client.src/routes/{-$locale}/route.tsxCopiare il codiceCopiare il codice nella clipboard
IntlProvidernon unisce i messaggi di un provider genitore. Il passaggio successivo aggiunge un piccolo componente che lo fa, in modo che ogni pagina possa aggiungere il proprio namespace sopracommon.- Rifiuta i prefissi non supportati (
Isola l'ambito dei messaggi di pagina
Ogni pagina carica il proprio namespace nel rispettivo loader, quindi avvolge il suo contenuto con
ScopedMessages, che unisce il namespace di pagina con i messaggi del genitore.src/components/ScopedMessages.tsxCopiare il codiceCopiare il codice nella clipboard
Utilizza le traduzioni nelle tue pagine
Il loader di pagina recupera il namespace
aboutper la lingua corrente,head()crea da esso metadati tradotti e completi per la SEO (vedi passaggio 13), e il componente esegue il rendering del contenuto.src/routes/{-$locale}/about.tsxCopiare il codiceCopiare il codice nella clipboard
Usa traduzioni e formattatori nei componenti
Qualsiasi componente all'interno dei provider può chiamare
useTranslationseuseFormatter. I plurali vengono risolti tramite ICU e i numeri vengono formattati in base alla lingua attiva.src/components/Counter.tsxCopiare il codiceCopiare il codice nella clipboard
Crea un componente di link localizzato
OpzionaleOgni route risiede sotto
{-$locale}, quindi un link deve trasmettere il parametro della lingua corrente. Questo wrapper mantiene iltotipizzato di TanStack Router e inietta la lingua automaticamente.src/components/LocalizedLink.tsxCopiare il codiceCopiare il codice nella clipboard
src/components/Header.tsxCopiare il codiceCopiare il codice nella clipboard
Cambia la lingua dei tuoi contenuti
OpzionaleEsegui il rendering del selettore come link, non come un menu
<select>. I link sono scansionabili, consentendo ai motori di ricerca di trovare ogni versione linguistica, e funzionano senza JavaScript.to="."mantiene la pagina corrente e sostituisce solo il parametro della lingua. Il cookie memorizza la scelta esplicita per il middleware di reindirizzamento del passaggio 16.src/components/LocaleSwitcher.tsxCopiare il codiceCopiare il codice nella clipboard
Internazionalizza i tuoi metadati
OpzionaleÈ qui che l'i18n ripaga gli sforzi: ogni versione linguistica può posizionarsi autonomamente sui motori di ricerca. Ogni pagina deve esporre:
- un
<title>e unadescriptiontradotti; - un URL canonical che punta a se stesso (non alla lingua predefinita);
- un
hreflangalternativo per lingua, piùx-defaultper le lingue senza corrispondenza; - tag Open Graph
og:locale,og:locale:alternateeog:url, utilizzati dalle anteprime social; - JSON-LD con
inLanguage, che aiuta i motori di ricerca e gli assistenti IA ad attribuire la lingua corretta alla pagina.
Un singolo helper genera tutto questo, mantenendo snelle le pagine:
src/i18n/seo.tsCopiare il codiceCopiare il codice nella clipboard
Usalo nell'
head()di ciascuna pagina, come mostrato al passaggio 9. Per la home page, passapath: "/".- un
Internazionalizza la tua sitemap
OpzionaleUna sitemap multilingue elenca ogni URL di ogni lingua, e ogni voce dichiara tutti i suoi alternativi con
xhtml:link. Google usa queste annotazioni esattamente come i taghreflangdella pagina, rendendole un valido backup quando una pagina viene scansionata raramente.Le server route di TanStack Start ti consentono di servirla direttamente da un file route:
src/routes/sitemap[.]xml.tsCopiare il codiceCopiare il codice nella clipboard
Internazionalizza il tuo file robots.txt
OpzionaleLe route private esistono in ogni lingua, quindi le regole
Disallowdevono coprire tutti i prefissi. Rimuovipublic/robots.txtse il template iniziale ne ha creato uno, quindi servilo da una route:src/routes/robots[.]txt.tsCopiare il codiceCopiare il codice nella clipboard
Reindirizza i nuovi visitatori alla loro lingua
OpzionaleUn middleware di richiesta invia un visitatore che atterra su
/alla sua lingua preferita, basandosi prima sul cookie della lingua e poi sull'headerAccept-Language. Solo/viene reindirizzato: i deep link non vengono mai toccati, garantendo che gli URL condivisi e i crawler ricevano sempre la pagina richiesta.src/i18n/negotiateLocale.tsCopiare il codiceCopiare il codice nella clipboard
src/start.tsCopiare il codiceCopiare il codice nella clipboard
Un visitatore che seleziona esplicitamente l'inglese nel selettore riceve
locale=ennel cookie, evitando qualsiasi reindirizzamento futuro. In una distribuzione completamente statica (passaggio 18),/viene servito come file e questo middleware non viene eseguito, il che è normale: la pagina rimane accessibile e il selettore si occupa del resto.Mantieni l'API di use-intl e riduci il runtime con Intlayer
OpzionaleIl benchmark evidenzia che la parte più pesante di un setup use-intl è il runtime stesso (~76 KB gzip). L'adattatore di compatibilità
@intlayer/use-intlespone la stessa API (useTranslations,useFormatter,IntlProvider,createTranslator, plurali ICU,t.rich), ma la serve da dizionari Intlayer compilati: ~6.7 KB anziché ~75.9 KB, 0% di perdita per lingua e 0% per pagina, senza alcuna modifica ai componenti.bashCopiare il codiceCopiare il codice nella clipboard
Il plugin Vite crea un alias da
use-intlall'adattatore, mantenendo funzionanti tutti gli import esistenti:vite.config.tsCopiare il codiceCopiare il codice nella clipboard
I tuoi file JSON rimangono la fonte di verità grazie al plugin di sincronizzazione JSON:
intlayer.config.tsCopiare il codiceCopiare il codice nella clipboard
L'adattatore rappresenta anche un percorso di migrazione graduale: una volta configurato, puoi convertire i componenti uno per uno all'API nativa
useIntlayer. Consulta la guida a Intlayer con TanStack Start.Esegui il pre-rendering di ogni lingua
OpzionaleL'HTML statico garantisce la pagina più veloce da servire e la più semplice da indicizzare. Elenca ogni percorso localizzato in modo che TanStack Start esegua il pre-rendering di tutte le versioni linguistiche in fase di build, oltre ai file della sitemap e di robots:
vite.config.tsCopiare il codiceCopiare il codice nella clipboard
Poiché il selettore di lingua esegue il rendering di link reali, l'opzione
crawlLinks: truerileva automaticamente anche le pagine dimenticate nell'elenco.Gestisci le pagine 404 localizzate
OpzionaleIl layout del passaggio 7 lancia già
notFound()per prefissi di lingua sconosciuti. Aggiungi una route generica (catch-all) in modo che i percorsi sconosciuti all'interno di una lingua mostrino comunque il 404 localizzato, e contrassegnalo connoindex: React 19 sposta automaticamente il tag<meta>dentro<head>.src/components/NotFound.tsxCopiare il codiceCopiare il codice nella clipboard
src/routes/{-$locale}/$.tsxCopiare il codiceCopiare il codice nella clipboard
Accedi alla lingua nelle funzioni server
OpzionaleLe funzioni server non ricevono i parametri della route. Leggi il cookie della lingua e usa come fallback l'header
Accept-Languageper inviare email localizzate o salvare le preferenze dell'utente:src/server/getServerLocale.tsCopiare il codiceCopiare il codice nella clipboard
Per tradurre all'interno della funzione server, combinala con
loadMessagesecreateTranslatordiuse-intl.Automatizza le tue traduzioni usando Intlayer
Opzionaleuse-intl gestisce il rendering delle traduzioni, ma non ti aiuta a produrle. Intlayer è gratuito e open source, e colma questa lacuna anche se decidi di mantenere use-intl:
- Testa le traduzioni mancanti in CI o nei test unitari. Vedi testare le traduzioni.
- Traduci con l'IA usando la tua chiave API e il tuo provider preferito:
npx intlayer filltraduce le chiavi mancanti con il contesto della tua applicazione. Vedi auto fill e la CLI. - Mantieni i tuoi file JSON come fonte di verità grazie al plugin di sincronizzazione JSON.
- Modifica i contenuti visivamente con l'editor visuale e il CMS, consentendo a chi non è sviluppatore di aggiornare le traduzioni.
- Fornisci contesto al tuo agente IA con il server MCP e le agent skills.
- Scansiona il tuo sito distribuito alla ricerca di
hreflangmancanti, canonical errati e perdite di lingua con il comando scan.
Per scoprire tutte le funzionalità, consulta perché Intlayer.
Domande frequenti
Sì, se desideri l'API di next-intl al di fuori di Next.js. Offre messaggi ICU, formattatori e un buon supporto TypeScript, evitando vincoli specifici di Next.js come setRequestLocale. Il compromesso riguarda il peso: il benchmark misura ~76 KB gzip per il runtime, e una configurazione superficiale invia ogni lingua e ogni pagina al browser. Carica i namespace per route e per lingua, come illustrato in questa guida, per evitare dispersioni.
use-intl è il core di next-intl. next-intl vi aggiunge sopra integrazioni specifiche per Next.js: un middleware, helper di navigazione, getTranslations per Server Components e configurazione delle richieste. Su TanStack Start utilizzi direttamente use-intl e implementi il routing con TanStack Router, come mostrato in precedenza.
Usa un prefisso nell'URL. In questo modo ogni versione linguistica dispone di un proprio URL indicizzabile dai motori di ricerca e condivisibile dagli utenti. Un cookie rimane comunque utile per memorizzare una scelta esplicita, che è quanto gestito dal middleware di reindirizzamento del passaggio 16.
Il server e il browser formattano le date in fusi orari differenti. Passa un timeZone esplicito a IntlProvider (o il fuso orario del visitatore memorizzato in un cookie), in modo che entrambi i lati producano lo stesso testo.
Innanzitutto, suddividi i messaggi per namespace e caricali per route e per lingua con import.meta.glob, eliminando le dispersioni per lingua e pagina. Se poi la dimensione del runtime è critica, passa all'adattatore @intlayer/use-intl: medesima API, ~6.7 KB invece di ~75.9 KB nel benchmark.
Chiama createTranslator all'interno della funzione head() della route passando i messaggi restituiti dal loader della route, quindi restituisci title, description, link canonici e link hreflang. Il passaggio 13 fornisce un helper riutilizzabile.
Commenti
Ancora nessun commento. Sii il primo a condividere i tuoi pensieri.
