Skip to main content

Guia completa de la internacionalització de React

De zero a multilingüe: configuri l’i18n a la seva aplicació React i automatitzi les traduccions amb IA.

1

Instal·lar els paquets

Necessita tres paquets: react-i18next (els enllaços per a React), i18next (la biblioteca principal) i, opcionalment, i18next-browser-languagedetector per detectar automàticament la configuració regional.

react-i18next proporciona hooks i components de React. i18next és el motor principal que gestiona la càrrega de traduccions, la interpolació i la pluralització. El connector de detecció d’idioma llegeix automàticament la preferència lingüística del navegador.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Configurar la instància d’i18n

Creï un fitxer de configuració d’i18n que inicialitzi i18next amb l’idioma predeterminat, els recursos de traducció i la cadena de connectors. Cal importar aquest fitxer al punt d’entrada de l’aplicació abans que es renderitzi cap component.

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" — aquest error vol dir que no ha cridat i18n.use(initReactI18next) abans de i18n.init(). La crida .use() ha d’anar abans de .init().
3

Embolcallar l’aplicació amb I18nextProvider

Importi el fitxer de configuració d’i18n a l’arrel de l’aplicació i embolcalli l’arbre de components amb I18nextProvider. Sense això, useTranslation() retorna les claus sense processar en lloc del text traduït.

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>
);
Si les traduccions mostren claus sense processar com ara "welcome" en lloc de "Li donem la benvinguda a la nostra aplicació", la causa més habitual és que falti I18nextProvider o que no s’hagi importat el fitxer de configuració d’i18n.
4

Crear els fitxers de traducció

Creï un fitxer JSON per idioma. Utilitzi claus imbricades per organitzar les cadenes per funcionalitat o pàgina. Mantingui l’idioma d’origen (normalment l’anglès) com a única font de referència.

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"
  }
}
Anomeni les claus segons allò que descriuen, no segons el lloc on apareixen: "cart.itemCount" és millor que "homepageCartLabel". Les claus han de resistir els redissenys de la interfície.
5

Utilitzar traduccions als components

Cridi useTranslation() en qualsevol component per obtenir la funció t(). Utilitzi-la per a cadenes simples, variables interpolades i traduccions amb JSX incrustat mitjançant el component 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" />
    }} />
  );
}
Les claus dinàmiques com t(`error.$'{code}'`) funcionen en temps d’execució, però eines com i18next-scanner no les poden extreure estàticament. Si utilitza eines d’extracció, enumeri explícitament les claus dinàmiques o faci servir un comentari indicatiu.
6

Gestionar els plurals i les variables

i18next gestiona els plurals mitjançant les regles CLDR, no només amb singular i plural. L’àrab té 6 formes (zero, one, two, few, many, other). El japonès en té 1 (other). Defineixi totes les formes necessàries als fitxers de traducció i i18next seleccionarà automàticament la correcta.

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}}個のアイテム"
}
No codifiqui mai count === 1 de manera fixa per detectar el singular. Idiomes com el francès tracten el 0 com a singular. El rus, l’àrab i el polonès tenen formes que no existeixen en anglès. Deixi que i18next gestioni les regles de plural.
7

Afegir la selecció i la detecció d’idioma

Creï un selector d’idioma que cridi i18n.changeLanguage(). Combini’l amb el detector d’idioma del navegador per detectar automàticament l’idioma preferit de l’usuari en la primera visita i, després, conservar-ne la tria explícita.

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>
  );
}
Si utilitza SSR (Next.js, Remix), el servidor pot detectar un idioma diferent del client, ja que no té les preferències del navegador. Això provoca una discrepància d’hidratació. Solució: passi la configuració regional detectada del servidor al client com a prop o galeta perquè tots dos renderitzin el mateix idioma.
8

Automatitzar les traduccions

Un cop completada la configuració d’i18n, tradueixi els fitxers de configuració regional amb IA. Demani a l’assistent d’IA de l’IDE que tradueixi el fitxer d’origen o utilitzi la CLI d’i18n Agent a la canalització de 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
Tradueixi de manera incremental: quan afegeixi claus noves al fitxer d’origen, tradueixi només les diferències en lloc de tornar a generar tots els fitxers. Així conservarà les traduccions revisades per persones.

Automatitzar la qualitat de les traduccions

Detecti les claus que falten i els marcadors de posició malmesos abans de publicar-los amb i18n-validate. Provi la interfície amb traduccions fictícies mitjançant i18n-pseudo abans que arribin les traduccions reals.

Errors habituals

Les traduccions mostren claus sense processar

Causes: falta I18nextProvider, la configuració d’i18n no s’ha importat a l’arrel de l’aplicació, l’espai de noms no s’ha carregat o les traduccions encara es carreguen de manera asíncrona. Cerqui pistes a la consola del navegador amb debug: true.

Error de Suspense sense alternativa

"A component suspended while responding to synchronous input" — afegeixi un límit '&lt;Suspense&gt;' al voltant de l’aplicació o estableixi useSuspense: false a la configuració d’inicialització d’i18next.

Discrepància d’hidratació amb SSR

El servidor renderitza amb una configuració regional i el client s’hidrata amb una altra. Asseguri’s que tots dos utilitzin la mateixa font de configuració regional: passi-la com a prop des del servidor i no confiï només en la detecció del navegador.

No hi ha compleció automàtica per a les claus de traducció

Ampliï el mòdul i18next amb el tipus del recurs: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Això proporciona crides t() amb seguretat de tipus i compleció automàtica.

Estructura de fitxers recomanada

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

Provar i18n Agent ara

Arrossegar aquí el fitxer de traducció

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

o fer clic per explorar

Idiomes de destinació

No cal registrePressupost instantani

Preguntes més freqüents