Skip to main content

Guida completa all'internazionalizzazione React

Da zero a multilingue: configurare i18n nell'app React e automatizzare le traduzioni con l'IA.

1

Installare i pacchetti

Servono tre pacchetti: react-i18next (binding React), i18next (biblioteca principale) e, facoltativamente, i18next-browser-languagedetector per rilevare automaticamente la lingua.

react-i18next fornisce hook e componenti React. i18next è il motore che gestisce caricamento, interpolazione e plurali. Il plugin di rilevamento legge automaticamente la lingua preferita del browser.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Configurare l'istanza i18n

Creare un file di configurazione che inizializzi i18next con lingua predefinita, risorse e catena di plugin. Importarlo nel punto di ingresso prima del rendering dei componenti.

src/i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)  // Must come before .init()
  .init({
    fallbackLng: 'en',
    debug: process.env.NODE_ENV === 'development',
    interpolation: {
      escapeValue: false,  // React already escapes
    },
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json',
    },
  });

export default i18n;
«You will need to pass in an i18next instance by using initReactI18next»: questo errore indica che manca i18n.use(initReactI18next) prima di i18n.init(). La chiamata .use() deve precedere .init().
3

Racchiudere l'applicazione in I18nextProvider

Importare la configurazione i18n alla radice e racchiudere l'albero dei componenti in I18nextProvider. In caso contrario, useTranslation() restituisce le chiavi anziché il testo tradotto.

src/main.tsx
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';  // Import your config
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Suspense fallback={<div>Loading...</div>}>
      <I18nextProvider i18n={i18n}>
        <App />
      </I18nextProvider>
    </Suspense>
  </React.StrictMode>
);
Se compaiono chiavi come "welcome" anziché "Welcome to our app", in genere manca I18nextProvider o non è stato importato il file di configurazione.
4

Creare i file di traduzione

Creare un file JSON per lingua. Usare chiavi annidate per organizzare le stringhe per funzione o pagina e mantenere la lingua sorgente, solitamente l'inglese, come fonte di riferimento.

public/locales/en/translation.json
// public/locales/en/translation.json
{
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "greeting": "Hello, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} item",
    "itemCount_other": "{{count}} items"
  }
}

// public/locales/de/translation.json
{
  "nav": {
    "home": "Startseite",
    "about": "Über uns",
    "settings": "Einstellungen"
  },
  "greeting": "Hallo, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} Artikel",
    "itemCount_other": "{{count}} Artikel"
  }
}
Nominare le chiavi in base a ciò che descrivono, non alla posizione: "cart.itemCount" è preferibile a "homepageCartLabel". Devono resistere alle riprogettazioni dell'interfaccia.
5

Usare le traduzioni nei componenti

Chiamare useTranslation() in qualsiasi componente per ottenere t(). Usarlo per stringhe semplici, variabili interpolate e traduzioni con JSX tramite Trans.

Greeting.tsx
import { useTranslation } from 'react-i18next';

function Greeting({ userName }: { userName: string }) {
  const { t } = useTranslation();

  return (
    <div>
      <h1>{t('greeting', { name: userName })}</h1>
      <nav>
        <a href="/">{t('nav.home')}</a>
        <a href="/about">{t('nav.about')}</a>
      </nav>
    </div>
  );
}
Trans component for JSX
import { Trans, useTranslation } from 'react-i18next';

// For JSX inside translations:
// "terms": "By signing up, you agree to our <link>Terms</link>."

function SignUp() {
  const { t } = useTranslation();
  return (
    <Trans i18nKey="terms" components={{
      link: <a href="/terms" className="underline" />
    }} />
  );
}
Le chiavi dinamiche come t(`error.$'{code}'`) funzionano durante l'esecuzione, ma i18next-scanner non può estrarle staticamente. Elencarle esplicitamente o aggiungere un commento per lo strumento.
6

Gestire plurali e variabili

i18next gestisce i plurali con le regole CLDR, non soltanto singolare e plurale. L'arabo ha 6 forme (zero, one, two, few, many, other), il giapponese 1 (other). Definire tutte le forme necessarie e i18next sceglierà quella corretta.

Plural forms by language
// English: 2 forms (one, other)
{
  "itemCount_one": "{{count}} item",
  "itemCount_other": "{{count}} items"
}

// Arabic: 6 forms (zero, one, two, few, many, other)
{
  "itemCount_zero": "لا عناصر",
  "itemCount_one": "عنصر واحد",
  "itemCount_two": "عنصران",
  "itemCount_few": "{{count}} عناصر",
  "itemCount_many": "{{count}} عنصرًا",
  "itemCount_other": "{{count}} عنصر"
}

// Japanese: 1 form (other)
{
  "itemCount_other": "{{count}}個のアイテム"
}
Non codificare mai count === 1 per rilevare il singolare. Il francese tratta 0 come singolare e russo, arabo e polacco hanno forme assenti in inglese. Lasciare gestire le regole a i18next.
7

Aggiungere cambio e rilevamento della lingua

Creare un selettore che chiami i18n.changeLanguage(). Abbinarlo al rilevatore del browser per individuare la preferenza alla prima visita e conservare poi la scelta esplicita.

LanguageSwitcher.tsx
import { useTranslation } from 'react-i18next';

const LANGUAGES = [
  { code: 'en', label: 'English' },
  { code: 'de', label: 'Deutsch' },
  { code: 'ja', label: '日本語' },
  { code: 'es', label: 'Español' },
];

function LanguageSwitcher() {
  const { i18n } = useTranslation();

  return (
    <select
      value={i18n.language}
      onChange={(e) => i18n.changeLanguage(e.target.value)}
    >
      {LANGUAGES.map(({ code, label }) => (
        <option key={code} value={code}>{label}</option>
      ))}
    </select>
  );
}
Con SSR (Next.js, Remix), server e client possono rilevare lingue diverse, causando una mancata corrispondenza di idratazione. Passare la lingua rilevata dal server al client come proprietà o cookie.
8

Automatizzare le traduzioni

Completata la configurazione i18n, tradurre i file con l'IA. Chiedere all'assistente nell'IDE o usare i18n Agent CLI nella pipeline CI/CD.

Terminal
# In your IDE, ask your AI assistant:
> Translate public/locales/en/translation.json to German, Japanese, and Spanish

✓ de/translation.json created (1.2s)
✓ ja/translation.json created (1.5s)
✓ es/translation.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate public/locales/en/translation.json --lang de,ja,es
Tradurre in modo incrementale: quando vengono aggiunte chiavi, tradurre soltanto le differenze anziché rigenerare tutti i file. Le traduzioni revisionate restano intatte.

Automatizzare la qualità

Rilevare chiavi mancanti e segnaposto danneggiati con i18n-validate. Provare l'interfaccia con traduzioni fittizie tramite i18n-pseudo prima che arrivino quelle reali.

Problemi comuni

Le traduzioni mostrano le chiavi grezze

Cause: I18nextProvider mancante, configurazione non importata alla radice, namespace non caricato o traduzioni ancora in caricamento asincrono. Controllare la console con debug: true.

Errore Suspense senza fallback

«A component suspended while responding to synchronous input»: aggiungere un limite '&lt;Suspense&gt;' attorno all'applicazione oppure impostare useSuspense: false nella configurazione init di i18next.

Mancata corrispondenza nell'idratazione SSR

Il server esegue il rendering in una lingua e il client l'idrata in un'altra. Assicurarsi che entrambi usino la stessa fonte: passarla dal server come proprietà, senza affidarsi soltanto al rilevamento del browser.

Nessun completamento automatico per le chiavi

Estendere il modulo i18next con il tipo delle risorse: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Le chiamate t() saranno così type-safe e dotate di completamento automatico.

Struttura dei file consigliata

Project Structure
my-react-app/
├── public/
│   └── locales/
│       ├── en/
│       │   ├── translation.json    # Default namespace
│       │   ├── common.json         # Shared strings
│       │   └── dashboard.json      # Feature namespace
│       ├── de/
│       │   ├── translation.json
│       │   ├── common.json
│       │   └── dashboard.json
│       └── ja/
│           └── ...
├── src/
│   ├── i18n.ts                     # i18n configuration
│   ├── main.tsx                    # App entry with Provider
│   ├── App.tsx
│   └── components/
│       └── LanguageSwitcher.tsx
└── package.json

Provi subito i18n Agent

Trascinare qui il file di traduzione

JSON, YAML, PO, XML, CSV, Markdown, Properties

oppure fare clic per selezionarlo

Lingue di destinazione

Nessuna registrazione richiestaPreventivo immediato

Domande frequenti