Skip to main content

Den komplette guide til internationalisering i React

Fra nul til flere sprog: Konfigurer i18n i din React-app og automatiser derefter oversættelser med AI.

1

Installer pakker

Du skal bruge tre pakker: react-i18next (React-bindingerne), i18next (kernebiblioteket) og eventuelt i18next-browser-languagedetector til automatisk registrering af landestandard.

react-i18next indeholder React-hooks og -komponenter. i18next er kernemotoren, der håndterer indlæsning af oversættelser, interpolation og flertalsformer. Pluginet til sprogregistrering aflæser automatisk browserens sprogpræference.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Konfigurer i18n-instansen

Opret en i18n-konfigurationsfil, der initialiserer i18next med dit standardsprog, dine oversættelsesressourcer og din pluginkæde. Filen skal importeres ved appens indgangspunkt, før nogen komponent gengives.

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;
"Du skal angive en i18next-instans ved hjælp af initReactI18next" — denne fejl betyder, at du har glemt at kalde i18n.use(initReactI18next) før i18n.init(). Kaldet til .use() skal komme før .init().
3

Ombryd din app med I18nextProvider

Importer din i18n-konfigurationsfil ved appens rod og ombryd komponenttræet med I18nextProvider. Uden dette returnerer useTranslation() de rå nøgler i stedet for oversat tekst.

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>
);
Hvis oversættelser viser rå nøgler som "welcome" i stedet for "Velkommen til vores app", skyldes det oftest en manglende I18nextProvider eller at i18n-konfigurationsfilen ikke er importeret.
4

Opret oversættelsesfiler

Opret én JSON-fil pr. sprog. Brug indlejrede nøgler til at organisere tekster efter funktion eller side. Bevar dit kildesprog (normalt engelsk) som den eneste sandhedskilde.

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"
  }
}
Navngiv nøgler efter det, de beskriver, ikke efter hvor de vises: "cart.itemCount" er bedre end "homepageCartLabel". Nøglerne skal kunne overleve ændringer af brugergrænsefladen.
5

Brug oversættelser i komponenter

Kald useTranslation() i en hvilken som helst komponent for at hente funktionen t(). Brug den til enkle tekster, interpolerede variabler og oversættelser med indlejret JSX via komponenten 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" />
    }} />
  );
}
Dynamiske nøgler som t(`error.$'{code}'`) fungerer under kørsel, men kan ikke udtrækkes statisk af værktøjer som i18next-scanner. Hvis du bruger udtræksværktøjer, skal du angive dynamiske nøgler eksplicit eller bruge en kommentar som tip.
6

Håndter flertalsformer og variabler

i18next håndterer flertalsformer efter CLDR-regler — ikke kun ental og flertal. Arabisk har 6 former (zero, one, two, few, many, other). Japansk har 1 (other). Definer alle nødvendige former i dine oversættelsesfiler, så vælger i18next automatisk den korrekte.

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}}個のアイテム"
}
Brug aldrig en fast kontrol af count === 1 til at registrere ental. Sprog som fransk behandler 0 som ental. Russisk, arabisk og polsk har former, der ikke findes på engelsk. Lad i18next håndtere flertalsreglerne.
7

Tilføj sprogskift og registrering

Byg en sprogvælger, der kalder i18n.changeLanguage(). Kombiner den med registrering af browsersproget for automatisk at finde brugerens foretrukne sprog ved første besøg og gem derefter brugerens udtrykkelige valg.

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>
  );
}
Hvis du bruger SSR (Next.js, Remix), kan serveren registrere et andet sprog end klienten (serveren har ingen browserpræferencer). Det medfører en uoverensstemmelse ved hydrering. Løsning: Send den registrerede landestandard fra serveren til klienten som en prop eller cookie, så begge gengiver det samme sprog.
8

Automatiser oversættelser

Når din i18n-opsætning er færdig, kan du oversætte dine landestandardfiler med AI. Bed din AI-assistent i dit IDE om at oversætte kildefilen eller brug i18n Agent CLI i din CI/CD-pipeline.

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
Oversæt trinvist — når du føjer nye nøgler til kildefilen, skal du kun oversætte forskellen i stedet for at generere alle filer igen. Det bevarer oversættelser, som mennesker allerede har gennemgået.

Automatiser oversættelseskvaliteten

Find manglende nøgler og ødelagte pladsholdere med i18n-validate, før de udgives. Test din brugergrænseflade med simulerede oversættelser via i18n-pseudo, før de rigtige oversættelser er klar.

Almindelige faldgruber

Oversættelser viser rå nøgler

Mulige årsager: I18nextProvider mangler, i18n-konfigurationen er ikke importeret ved appens rod, navnerummet er ikke indlæst eller oversættelserne indlæses stadig asynkront. Se efter spor i browserkonsollen med debug: true.

Suspense-fejl uden reserveindhold

"En komponent blev sat på pause, mens den reagerede på synkront input" — tilføj en '&lt;Suspense&gt;'-grænse omkring din app eller angiv useSuspense: false i i18nexts init-konfiguration.

Uoverensstemmelse ved SSR-hydrering

Serveren gengiver én landestandard, mens klienten hydrerer en anden. Sørg for, at begge bruger den samme kilde til landestandard — send den som en prop fra serveren og brug ikke kun browserregistrering.

Ingen autofuldførelse af oversættelsesnøgler

Udvid i18next-modulet med din ressourcetype: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Det giver typesikre kald til t() med autofuldførelse.

Anbefalet filstruktur

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

Prøv i18n Agent nu

Slip din oversættelsesfil her

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

eller klik for at vælge en fil

Målsprog

Kræver ingen tilmeldingEstimat med det samme

Ofte stillede spørgsmål