Übersetzungen laden

Verwendung eines Providers zur Verwaltung von Nachrichten

Problem

Das Hardcoding von Text, wie 'Hello World', direkt in die Komponenten einer Anwendung koppelt den Inhalt mit dem Code. Um eine andere Sprache anzuzeigen, müssen Entwickler die Komponente duplizieren oder if/else-Logik hinzufügen, was die Übersetzung nicht skalierbar macht und für jedes neue Textstück eine vollständige Codeänderung erfordert.

Lösung

Verwenden Sie den IntlProvider von react-intl, um Übersetzungen bereitzustellen. Laden Sie Übersetzungsnachrichten auf dem Server im Root-Layout, übergeben Sie sie an eine clientseitige Provider-Komponente und nutzen Sie sie dann in anderen Client-Komponenten mit dem useIntl-Hook.

Schritte

1. Installieren Sie react-intl

Fügen Sie zunächst react-intl als Abhängigkeit zu Ihrem Projekt hinzu.

npm install react-intl

2. Erstellen Sie flache Übersetzungsdateien

Erstellen Sie einen dictionaries-Ordner. Fügen Sie darin eine JSON-Datei für jede Sprache hinzu. react-intl funktioniert am besten mit einer flachen Schlüssel-Wert-Struktur.

// dictionaries/en.json
{
  "home.title": "Home Page",
  "home.welcome": "Hello, welcome to our site!",
  "about.title": "About Us"
}
// dictionaries/es.json
{
  "home.title": "Página de Inicio",
  "home.welcome": "¡Hola, bienvenido a nuestro sitio!",
  "about.title": "Sobre Nosotros"
}

3. Erstellen Sie eine Funktion zum Laden von Wörterbüchern

Erstellen Sie eine Hilfsfunktion, um die richtige Wörterbuchdatei auf dem Server basierend auf dem lang-Parameter zu laden.

// app/get-dictionary.ts
import 'server-only';

// Define the type for our flat message object
type Messages = Record<string, string>;

const dictionaries: { [key: string]: () => Promise<Messages> } = {
  en: () => import('@/dictionaries/en.json').then((module) => module.default),
  es: () => import('@/dictionaries/es.json').then((module) => module.default),
  // fr: () => import('@/dictionaries/fr.json').then((module) => module.default),
};

export const getDictionary = async (lang: string) => {
  const load = dictionaries[lang];
  if (load) {
    return load();
  }
  // Fallback to English
  return dictionaries.en();
};

4. Erstellen eines clientseitigen Providers

IntlProvider ist eine Client-Komponente, die den Context von React verwendet. Wir müssen einen Wrapper dafür erstellen, der Nachrichten vom Server laden kann.

// app/components/IntlClientProvider.tsx
'use client';

import { IntlProvider } from 'react-intl';

type Props = {
  children: React.ReactNode;
  locale: string;
  messages: Record<string, string>; // Flat messages object
};

export default function IntlClientProvider({
  children,
  locale,
  messages,
}: Props) {
  return (
    <IntlProvider messages={messages} locale={locale} defaultLocale="en">
      {children}
    </IntlProvider>
  );
}

5. Aktualisieren des Root-Layouts

Modifizieren Sie Ihr app/[lang]/layout.tsx, um eine async-Komponente zu erstellen. Diese wird die Nachrichten laden und an den IntlClientProvider übergeben.

// app/[lang]/layout.tsx
import { getDictionary } from '@/app/get-dictionary';
import IntlClientProvider from '@/app/components/IntlClientProvider';

export async function generateStaticParams() {
  return [{ lang: 'en' }, { lang: 'es' }];
}

export default async function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  // Load messages on the server
  const messages = await getDictionary(params.lang);

  return (
    <html lang={params.lang}>
      <body>
        {/* Pass messages to the client provider */}
        <IntlClientProvider locale={params.lang} messages={messages}>
          {children}
        </IntlClientProvider>
      </body>
    </html>
  );
}

6. Verwendung von Übersetzungen in einer Client-Komponente

Sie können jetzt den useIntl-Hook in jeder Client-Komponente verwenden. Server-Komponenten können diesen Hook nicht nutzen.

Erstellen Sie eine neue Client-Komponente, um den übersetzten Text anzuzeigen:

// app/components/HomePageContent.tsx
'use client';

import { useIntl } from 'react-intl';

export default function HomePageContent() {
  const intl = useIntl();

  return (
    <div>
      <h1>{intl.formatMessage({ id: 'home.title' })}</h1>
      <p>{intl.formatMessage({ id: 'home.welcome' })}</p>
    </div>
  );
}

7. Fügen Sie die Komponente zu Ihrer Seite hinzu

Fügen Sie schließlich Ihre neue Client-Komponente zu Ihrer Seite hinzu.

// app/[lang]/page.tsx
import HomePageContent from '@/app/components/HomePageContent';

export default function Home() {
  // Diese Seite ist eine Server-Komponente
  return (
    <div>
      {/* Sie rendert die Client-Komponente */}
      <HomePageContent />
    </div>
  );
}