Übersetzungen laden

Verwendung eines Providers zur Verwaltung von Nachrichten

Problem

Das direkte Einbetten von Text wie „Hello World" 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 jeden neuen Text 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 diese an eine clientseitige Provider-Komponente und nutzen Sie sie dann in anderen Client-Komponenten über den useIntl-Hook.

Schritte

1. react-intl installieren

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

npm install react-intl

2. Flache Übersetzungsdateien erstellen

Erstellen Sie einen dictionaries-Ordner. Fügen Sie darin für jede Sprache eine JSON-Datei hinzu. react-intl funktioniert am besten mit einer flachen Key-Value-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. Funktion zum Laden von Dictionaries erstellen

Erstellen Sie eine Hilfsfunktion, um die korrekte Dictionary-Datei 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. Clientseitigen Provider erstellen

IntlProvider ist eine Client-Komponente, die React Context verwendet. Wir müssen einen Wrapper dafür erstellen, der vom Server geladene Nachrichten akzeptieren 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. Root-Layout aktualisieren

Ändern Sie Ihr app/[lang]/layout.tsx in eine async-Komponente. Diese lädt die Nachrichten und übergibt sie an den IntlClientProvider.

// 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. Übersetzungen in einer Client-Komponente verwenden

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

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. Komponente zu Ihrer Seite hinzufügen

Fügen Sie abschließend Ihre neue Client-Komponente zu Ihrer Seite hinzu.

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

export default function Home() {
  // This page is a Server Component
  return (
    <div>
      {/* It renders the Client Component */}
      <HomePageContent />
    </div>
  );
}