---
createdAt: 2024-12-06
updatedAt: 2025-12-30
title: Next.js i18n - Wie Sie Ihre Next.js 15 App übersetzen – Leitfaden 2026
description: Entdecken Sie, wie Sie Ihre Next.js 15 Website mehrsprachig machen. Folgen Sie der Dokumentation, um sie zu internationalisieren (i18n) und zu übersetzen.
keywords:
- Internationalisierung
- Dokumentation
- Intlayer
- Next.js 15
- JavaScript
- React
slugs:
- doc
- environment
- nextjs
- 15
applicationTemplate: https://github.com/aymericzip/intlayer-next-15-template
youtubeVideo: https://www.youtube.com/watch?v=e_PPG7PTqGU
history:
- version: 7.5.9
date: 2025-12-30
changes: Init-Befehl hinzufügen
- version: 5.5.10
date: 2025-06-29
changes: Initiale Historie
---
# Übersetzen Sie Ihre Next.js 15 mit Intlayer | Internationalisierung (i18n)
<iframe title="Die beste i18n-Lösung für Next.js? Entdecken Sie Intlayer" class="m-auto aspect-16/9 w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/e_PPG7PTqGU?autoplay=0&origin=http://intlayer.org&controls=0&rel=1"/>
Siehe [Anwendungsvorlage](https://github.com/aymericzip/intlayer-next-15-template) auf GitHub.
## Was ist Intlayer?
**Intlayer** ist eine innovative, Open-Source-Internationalisierungsbibliothek (i18n), die entwickelt wurde, um die mehrsprachige Unterstützung in modernen Webanwendungen zu vereinfachen. Intlayer integriert sich nahtlos in das neueste **Next.js 15** Framework, einschließlich seines leistungsstarken **App Routers**. Es ist optimiert für die Arbeit mit **Server Components** für effizientes Rendering und ist vollständig kompatibel mit [**Turbopack**](https://nextjs.org/docs/architecture/turbopack).
Mit Intlayer können Sie:
- **Übersetzungen einfach verwalten** mithilfe deklarativer Wörterbücher auf Komponentenebene.
- **Metadaten, Routen und Inhalte dynamisch lokalisieren**.
- **Übersetzungen sowohl in Client- als auch in Server-Komponenten nutzen**.
- **TypeScript-Unterstützung sicherstellen** mit automatisch generierten Typen, die die Autovervollständigung und Fehlererkennung verbessern.
- **Profitieren Sie von erweiterten Funktionen**, wie dynamischer Spracherkennung und Umschaltung.
> Intlayer ist kompatibel mit Next.js 12, 13, 14 und 15. Wenn Sie den Next.js Page Router verwenden, können Sie sich an dieser [Anleitung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_with_nextjs_page_router.md) orientieren. Für Next.js 12, 13, 14 mit App Router, siehe diese [Anleitung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_with_nextjs_14.md).
---
## Schritt-für-Schritt-Anleitung zur Einrichtung von Intlayer in einer Next.js-Anwendung
### Schritt 1: Abhängigkeiten installieren
Installieren Sie die notwendigen Pakete mit npm:
```bash packageManager="npm"
npm install intlayer next-intlayer
npx intlayer init
```
```bash packageManager="pnpm"
pnpm add intlayer next-intlayer
pnpm intlayer init
```
```bash packageManager="yarn"
yarn add intlayer next-intlayer
yarn intlayer init
```
```bash packageManager="bun"
bun add intlayer next-intlayer
bunx intlayer init
```
- **intlayer**
Das Kernpaket, das Internationalisierungswerkzeuge für Konfigurationsmanagement, Übersetzung, [Inhaltsdeklaration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/get_started.md), Transpilierung und [CLI-Befehle](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_cli.md) bereitstellt.
- **next-intlayer**
Das Paket, das Intlayer mit Next.js integriert. Es stellt Kontextanbieter und Hooks für die Internationalisierung in Next.js bereit. Zusätzlich enthält es das Next.js-Plugin zur Integration von Intlayer mit [Webpack](https://webpack.js.org/) oder [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack) sowie Middleware zur Erkennung der bevorzugten Sprache des Benutzers, zur Verwaltung von Cookies und zur Handhabung von URL-Weiterleitungen.
### Schritt 2: Konfigurieren Sie Ihr Projekt
Here is the final structure that we will make:
```bash
.
├── src
│ ├── app
│ │ ├── [locale]
│ │ │ ├── layout.tsx # Locale layout for the Intlayer provider
│ │ │ ├── page.content.ts
│ │ │ └── page.tsx
│ │ └── layout.tsx # Root layout for style and global providers
│ ├── components
│ │ ├── client-component-example.content.ts
│ │ ├── ClientComponentExample.tsx
│ │ ├── LocaleSwitcher
│ │ │ ├── localeSwitcher.content.ts
│ │ │ └── LocaleSwitcher.tsx
│ │ ├── server-component-example.content.ts
│ │ └── ServerComponentExample.tsx
│ └── middleware.ts
├── intlayer.config.ts
├── next.config.ts
├── package.json
└── tsconfig.json
```
> If you don't want locale routing, intlayer can be used as a simple provider / hook. See [this guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_no_locale_path.md) for more details.
Erstellen Sie eine Konfigurationsdatei, um die Sprachen Ihrer Anwendung zu konfigurieren:
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Ihre weiteren Sprachversionen
],
defaultLocale: Locales.ENGLISH,
},
};
export default config;
```
```javascript fileName="intlayer.config.mjs" codeFormat="esm"
import { Locales } from "intlayer";
/** @type {import('intlayer').IntlayerConfig} */
const config = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Ihre weiteren Sprachversionen
],
defaultLocale: Locales.ENGLISH,
},
};
export default config;
```
```javascript fileName="intlayer.config.cjs" codeFormat="commonjs"
const { Locales } = require("intlayer");
/** @type {import('intlayer').IntlayerConfig} */
const config = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Ihre weiteren Sprachversionen
],
defaultLocale: Locales.ENGLISH,
},
};
module.exports = config;
```
> Durch diese Konfigurationsdatei können Sie lokalisierte URLs, Middleware-Weiterleitungen, Cookie-Namen, den Speicherort und die Erweiterung Ihrer Inhaltsdeklarationen einrichten, Intlayer-Logs in der Konsole deaktivieren und vieles mehr. Für eine vollständige Liste der verfügbaren Parameter lesen Sie bitte die [Konfigurationsdokumentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/configuration.md).
### Schritt 3: Integrieren Sie Intlayer in Ihre Next.js-Konfiguration
Konfigurieren Sie Ihre Next.js-Umgebung, um Intlayer zu verwenden:
```typescript fileName="next.config.ts" codeFormat="typescript"
import type { NextConfig } from "next";
import { withIntlayer } from "next-intlayer/server";
const nextConfig: NextConfig = {
/* Konfigurationsoptionen hier */
};
export default withIntlayer(nextConfig);
```
```typescript fileName="next.config.mjs" codeFormat="esm"
import { withIntlayer } from "next-intlayer/server";
/** @type {import('next').NextConfig} */
const nextConfig = {
/* Konfigurationsoptionen hier */
};
export default withIntlayer(nextConfig);
```
```typescript fileName="next.config.cjs" codeFormat="commonjs"
const { withIntlayer } = require("next-intlayer/server");
/** @type {import('next').NextConfig} */
const nextConfig = {
/* Konfigurationsoptionen hier */
};
module.exports = withIntlayer(nextConfig);
```
> Das `withIntlayer()` Next.js-Plugin wird verwendet, um Intlayer mit Next.js zu integrieren. Es stellt sicher, dass Inhaltsdeklarationsdateien erstellt und im Entwicklungsmodus überwacht werden. Es definiert Intlayer-Umgebungsvariablen innerhalb der [Webpack](https://webpack.js.org/) oder [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack)-Umgebungen. Zusätzlich bietet es Aliase zur Leistungsoptimierung und gewährleistet die Kompatibilität mit Serverkomponenten.
### Schritt 4: Dynamische Locale-Routen definieren
Entfernen Sie alles aus `RootLayout` und ersetzen Sie es durch den folgenden Code:
```tsx {3} fileName="src/app/layout.tsx" codeFormat="typescript"
import type { PropsWithChildren, FC } from "react";
import "./globals.css";
const RootLayout: FC<PropsWithChildren> = ({ children }) => children;
export default RootLayout;
```
```jsx {3} fileName="src/app/layout.mjx" codeFormat="esm"
import "./globals.css";
const RootLayout = ({ children }) => children;
export default RootLayout;
```
```jsx {1,8} fileName="src/app/layout.csx" codeFormat="commonjs"
require("./globals.css");
const RootLayout = ({ children }) => children;
module.exports = {
default: RootLayout,
generateStaticParams,
};
```
> Die Beibehaltung der `RootLayout`-Komponente als leer ermöglicht es, die [`lang`](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/lang) und [`dir`](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/dir) Attribute im `<html>`-Tag zu setzen.
Um dynamisches Routing zu implementieren, geben Sie den Pfad für die Locale an, indem Sie ein neues Layout in Ihrem `[locale]`-Verzeichnis hinzufügen:
```tsx fileName="src/app/[locale]/layout.tsx" codeFormat="typescript"
import type { NextLayoutIntlayer } from "next-intlayer";
import { Inter } from "next/font/google";
import { getHTMLTextDir } from "intlayer";
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
const { locale } = await params;
return (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>{children}</body>
</html>
);
};
export default LocaleLayout;
```
```jsx fileName="src/app/[locale]/layout.mjx" codeFormat="esm"
import { getHTMLTextDir } from "intlayer";
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout = async ({ children, params: { locale } }) => {
const { locale } = await params;
return (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>{children}</body>
</html>
);
};
export default LocaleLayout;
```
```jsx fileName="src/app/[locale]/layout.csx" codeFormat="commonjs"
const { Inter } = require("next/font/google");
const { getHTMLTextDir } = require("intlayer");
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout = async ({ children, params: { locale } }) => {
const { locale } = await params;
return (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>{children}</body>
</html>
);
};
module.exports = LocaleLayout;
```
> Das Pfadsegment `[locale]` wird verwendet, um die Locale zu definieren. Beispiel: `/en-US/about` bezieht sich auf `en-US` und `/fr/about` auf `fr`.
> In diesem Stadium wird der Fehler `Error: Missing <html> and <body> tags in the root layout.` auftreten. Dies ist zu erwarten, da die Datei `/app/page.tsx` nicht mehr verwendet wird und entfernt werden kann. Stattdessen aktiviert das Pfadsegment `[locale]` die Seite `/app/[locale]/page.tsx`. Folglich sind die Seiten über Pfade wie `/en`, `/fr`, `/es` in Ihrem Browser zugänglich. Um die Standard-Locale als Root-Seite festzulegen, siehe die `middleware`-Konfiguration in Schritt 7.
Implementieren Sie anschließend die Funktion `generateStaticParams` in Ihrem Anwendungs-Layout.
```tsx {1} fileName="src/app/[locale]/layout.tsx" codeFormat="typescript"
export { generateStaticParams } from "next-intlayer"; // Zeile zum Einfügen
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
/*... Rest des Codes*/
};
export default LocaleLayout;
```
```jsx {1} fileName="src/app/[locale]/layout.mjx" codeFormat="esm"
export { generateStaticParams } from "next-intlayer"; // Zeile zum Einfügen
const LocaleLayout = async ({ children, params: { locale } }) => {
/*... Rest des Codes*/
};
// ... Rest des Codes
```
```jsx {1,7} fileName="src/app/[locale]/layout.csx" codeFormat="commonjs"
const { generateStaticParams } = require("next-intlayer"); // Zeile zum Einfügen
const LocaleLayout = async ({ children, params: { locale } }) => {
/*... Rest des Codes*/
};
module.exports = { default: LocaleLayout, generateStaticParams };
```
> `generateStaticParams` stellt sicher, dass Ihre Anwendung die notwendigen Seiten für alle Sprachen vorab erstellt, wodurch die Laufzeitberechnung reduziert und die Benutzererfahrung verbessert wird. Für weitere Details siehe die [Next.js-Dokumentation zu generateStaticParams](https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering#generate-static-params).
### Schritt 5: Deklarieren Sie Ihren Inhalt
Erstellen und verwalten Sie Ihre Inhaltsdeklarationen, um Übersetzungen zu speichern:
```tsx fileName="src/app/[locale]/page.content.ts" contentDeclarationFormat="typescript"
import { t, type Dictionary } from "intlayer";
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
en: "Get started by editing",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
} satisfies Dictionary;
export default pageContent;
```
```javascript fileName="src/app/[locale]/page.content.mjs" contentDeclarationFormat="esm"
import { t } from "intlayer";
/** @type {import('intlayer').Dictionary} */
// SeiteInhalt ist das Wörterbuch für die Seite
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
en: "Get started by editing",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
};
export default pageContent;
```
```javascript fileName="src/app/[locale]/page.content.cjs" contentDeclarationFormat="commonjs"
const { t } = require("intlayer");
/** @type {import('intlayer').Dictionary} */
// SeiteInhalt ist das Wörterbuch für die Seite
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
en: "Get started by editing",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
};
module.exports = pageContent;
```
```json fileName="src/app/[locale]/page.content.json" contentDeclarationFormat="json"
{
"$schema": "https://intlayer.org/schema.json",
"key": "page",
"content": {
"getStarted": {
"nodeType": "translation",
"translation": {
"de": "Beginnen Sie mit der Bearbeitung",
"en": "Get started by editing",
"fr": "Commencez par éditer",
"es": "Comience por editar"
}
},
"pageLink": "src/app/page.tsx"
}
}
```
> Ihre Inhaltsdeklarationen können überall in Ihrer Anwendung definiert werden, sobald sie in das Verzeichnis `contentDir` (standardmäßig `./src`) aufgenommen werden. Und sie müssen der Dateierweiterung für Inhaltsdeklarationen entsprechen (standardmäßig `.content.{json,ts,tsx,js,jsx,mjs,cjs}`).
> Für weitere Details siehe die [Dokumentation zur Inhaltsdeklaration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/get_started.md).
### Schritt 6: Inhalte in Ihrem Code verwenden
Greifen Sie in Ihrer gesamten Anwendung auf Ihre Inhaltswörterbücher zu:
```tsx fileName="src/app/[locale]/page.tsx" codeFormat="typescript"
import type { FC } from "react";
import { ClientComponentExample } from "@components/ClientComponentExample";
import { ServerComponentExample } from "@components/ServerComponentExample";
import { type NextPageIntlayer, IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const PageContent: FC = () => {
const content = useIntlayer("page");
return (
<>
<p>{content.getStarted.main}</p>
<code>{content.getStarted.pageLink}</code>
</>
);
};
const Page: NextPageIntlayer = async ({ params }) => {
const { locale } = await params;
return (
<IntlayerServerProvider locale={locale}>
<PageContent />
<ServerComponentExample />
<IntlayerClientProvider locale={locale}>
<ClientComponentExample />
</IntlayerClientProvider>
</IntlayerServerProvider>
);
};
export default Page;
```
```jsx fileName="src/app/[locale]/page.mjx" codeFormat="esm"
import { ClientComponentExample } from "@components/ClientComponentExample";
import { ServerComponentExample } from "@components/ServerComponentExample";
import { IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const PageContent = () => {
const content = useIntlayer("page");
return (
<>
<p>{content.getStarted.main}</p>
<code>{content.getStarted.pageLink}</code>
</>
);
};
const Page = async ({ params }) => {
const { locale } = await params;
return (
<IntlayerServerProvider locale={locale}>
<PageContent />
<ServerComponentExample />
<IntlayerClientProvider locale={locale}>
<ClientComponentExample />
</IntlayerClientProvider>
</IntlayerServerProvider>
);
};
export default Page;
```
```jsx fileName="src/app/[locale]/page.csx" codeFormat="commonjs"
import { ClientComponentExample } from "@components/ClientComponentExample";
import { ServerComponentExample } from "@components/ServerComponentExample";
import { IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const PageContent = () => {
const content = useIntlayer("page");
return (
<>
<p>{content.getStarted.main}</p>
<code>{content.getStarted.pageLink}</code>
</>
);
};
const Page = async ({ params }) => {
const { locale } = await params;
return (
<IntlayerServerProvider locale={locale}>
<PageContent />
<ServerComponentExample />
<IntlayerClientProvider locale={locale}>
<ClientComponentExample />
</IntlayerClientProvider>
</IntlayerServerProvider>
);
};
```
- **`IntlayerClientProvider`** wird verwendet, um die Locale an clientseitige Komponenten bereitzustellen. Es kann in jedem übergeordneten Element platziert werden, einschließlich des Layouts. Es wird jedoch empfohlen, es im Layout zu platzieren, da Next.js Layout-Code über Seiten hinweg teilt, was effizienter ist. Durch die Verwendung von `IntlayerClientProvider` im Layout vermeidet man die erneute Initialisierung für jede Seite, verbessert die Leistung und sorgt für einen konsistenten Lokalisierungskontext in der gesamten Anwendung.
- **`IntlayerServerProvider`** wird verwendet, um die Locale an die Server-Kinder bereitzustellen. Es kann nicht im Layout gesetzt werden.
> Layout und Seite können keinen gemeinsamen Server-Kontext teilen, da das Server-Kontext-System auf einem pro-Anfrage-Datenspeicher basiert (über den [React-Cache](https://react.dev/reference/react/cache)-Mechanismus), wodurch jeder "Kontext" für verschiedene Segmente der Anwendung neu erstellt wird. Das Platzieren des Providers in einem gemeinsamen Layout würde diese Isolation aufheben und die korrekte Weitergabe der Server-Kontextwerte an Ihre Server-Komponenten verhindern.
```tsx {4,7} fileName="src/components/ClientComponentExample.tsx" codeFormat="typescript"
"use client";
import type { FC } from "react";
import { useIntlayer } from "next-intlayer";
export const ClientComponentExample: FC = () => {
const content = useIntlayer("client-component-example"); // Erstelle zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
```jsx {3,6} fileName="src/components/ClientComponentExample.mjx" codeFormat="esm"
"use client";
import { useIntlayer } from "next-intlayer";
const ClientComponentExample = () => {
const content = useIntlayer("client-component-example"); // Erstelle zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
```jsx {3,6} fileName="src/components/ClientComponentExample.csx" codeFormat="commonjs"
"use client";
const { useIntlayer } = require("next-intlayer");
const ClientComponentExample = () => {
const content = useIntlayer("client-component-example"); // Erstelle zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
```tsx {2} fileName="src/components/ServerComponentExample.tsx" codeFormat="typescript"
import type { FC } from "react";
import { useIntlayer } from "next-intlayer/server";
export const ServerComponentExample: FC = () => {
const content = useIntlayer("server-component-example"); // Erstelle zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
```jsx {1} fileName="src/components/ServerComponentExample.mjx" codeFormat="esm"
import { useIntlayer } from "next-intlayer/server";
const ServerComponentExample = () => {
const content = useIntlayer("server-component-example"); // Erstelle zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
```jsx {1} fileName="src/components/ServerComponentExample.csx" codeFormat="commonjs"
const { useIntlayer } = require("next-intlayer/server");
const ServerComponentExample = () => {
const content = useIntlayer("server-component-example"); // Erstelle die zugehörige Inhaltsdeklaration
return (
<div>
<h2>{content.title}</h2>
<p>{content.content}</p>
</div>
);
};
```
> Wenn Sie Ihren Inhalt in einem `string`-Attribut verwenden möchten, wie z.B. `alt`, `title`, `href`, `aria-label` usw., müssen Sie den Wert der Funktion aufrufen, zum Beispiel:
> ```jsx
> <img src={content.image.src.value} alt={content.image.value} />
> ```
> Um mehr über den `useIntlayer` Hook zu erfahren, lesen Sie die [Dokumentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useIntlayer.md).
### (Optional) Schritt 7: Middleware für die Lokalerkennung konfigurieren
Richten Sie Middleware ein, um die bevorzugte Sprache des Benutzers zu erkennen:
```typescript fileName="src/middleware.ts" codeFormat="typescript"
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
export const config = {
matcher:
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};
```
```javascript fileName="src/middleware.mjs" codeFormat="esm"
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
export const config = {
matcher:
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};
```
```javascript fileName="src/middleware.cjs" codeFormat="commonjs"
const { intlayerMiddleware } = require("next-intlayer/middleware");
const config = {
matcher:
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};
module.exports = { middleware: intlayerMiddleware, config };
```
> Das `intlayerMiddleware` wird verwendet, um die bevorzugte Sprache des Benutzers zu erkennen und ihn auf die entsprechende URL weiterzuleiten, wie in der [Konfiguration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/configuration.md) angegeben. Zusätzlich ermöglicht es das Speichern der bevorzugten Sprache des Benutzers in einem Cookie.
### (Optional) Schritt 8: Internationalisierung Ihrer Metadaten
Falls Sie Ihre Metadaten, wie z.B. den Titel Ihrer Seite, internationalisieren möchten, können Sie die von Next.js bereitgestellte Funktion `generateMetadata` verwenden. Innerhalb dieser Funktion können Sie den Inhalt aus der Funktion `getIntlayer` abrufen, um Ihre Metadaten zu übersetzen.
```typescript fileName="src/app/[locale]/metadata.content.ts" contentDeclarationFormat="typescript"
import { type Dictionary, t } from "intlayer";
import { Metadata } from "next";
const metadataContent = {
key: "page-metadata",
content: {
title: t({
en: "Create Next App",
fr: "Créer une application Next.js",
es: "Crear una aplicación Next.js",
}),
description: t({
en: "Generated by create next app",
fr: "Généré par create next app",
es: "Generado por create next app",
}),
},
} satisfies Dictionary<Metadata>;
export default metadataContent;
```
```javascript fileName="src/app/[locale]/metadata.content.mjs" contentDeclarationFormat="esm"
import { t } from "intlayer";
/** @type {import('intlayer').Dictionary<import('next').Metadata>} */
const metadataContent = {
key: "seiten-metadaten",
content: {
title: t({
en: "Create Next App",
fr: "Créer une application Next.js",
es: "Crear una aplicación Next.js",
}),
description: t({
en: "Generated by create next app",
fr: "Généré par create next app",
es: "Generado por create next app",
}),
},
};
export default metadataContent;
```
```javascript fileName="src/app/[locale]/metadata.content.cjs" contentDeclarationFormat="commonjs"
const { t } = require("intlayer");
/** @type {import('intlayer').Dictionary<import('next').Metadata>} */
const metadataContent = {
key: "page-metadata",
content: {
title: t({
en: "Create Next App",
fr: "Créer une application Next.js",
es: "Crear una aplicación Next.js",
de: "Next App erstellen",
}),
description: t({
en: "Generated by create next app",
fr: "Généré par create next app",
es: "Generado por create next app",
de: "Erstellt mit create next app",
}),
},
};
module.exports = metadataContent;
```
```json fileName="src/app/[locale]/metadata.content.json" contentDeclarationFormat="json"
{
"key": "page-metadata",
"content": {
"title": {
"nodeType": "translation",
"translation": {
"en": "Preact logo",
"fr": "Logo Preact",
"es": "Logo Preact",
"de": "Preact-Logo"
}
},
"description": {
"nodeType": "translation",
"translation": {
"en": "Generated by create next app",
"fr": "Généré par create next app",
"es": "Generado por create next app",
"de": "Erstellt mit create next app"
},
},
},
};
```
````typescript fileName="src/app/[locale]/layout.tsx or src/app/[locale]/page.tsx" codeFormat="typescript"
import { getIntlayer, getMultilingualUrls } from "intlayer";
import type { Metadata } from "next";
import type { LocalPromiseParams } from "next-intlayer";
export const generateMetadata = async ({
params,
}: LocalPromiseParams): Promise<Metadata> => {
const { locale } = await params;
const metadata = getIntlayer("page-metadata", locale);
/**
* Erzeugt ein Objekt, das alle URLs für jede Locale enthält.
*
* Beispiel:
* ```ts
* getMultilingualUrls('/about');
*
* // Gibt zurück
* // {
* // en: '/about',
* // fr: '/fr/about',
* // es: '/es/about',
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
const localizedUrl =
multilingualUrls[locale as keyof typeof multilingualUrls];
return {
...metadata,
alternates: {
canonical: localizedUrl,
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: localizedUrl,
},
};
};
// ... Rest des Codes
````
````javascript fileName="src/app/[locale]/layout.mjs or src/app/[locale]/page.mjs" codeFormat="esm"
import { getIntlayer, getMultilingualUrls } from "intlayer";
export const generateMetadata = async ({ params }) => {
const { locale } = await params;
const metadata = getIntlayer("page-metadata", locale);
/**
* Erzeugt ein Objekt, das alle URLs für jede Locale enthält.
*
* Beispiel:
* ```ts
* getMultilingualUrls('/about');
*
* // Gibt zurück
* // {
* // en: '/about',
* // fr: '/fr/about',
* // es: '/es/about'
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
const localizedUrl = multilingualUrls[locale];
return {
...metadata,
alternates: {
canonical: localizedUrl,
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: localizedUrl,
},
};
};
// ... Rest des Codes
````
````javascript fileName="src/app/[locale]/layout.cjs or src/app/[locale]/page.cjs" codeFormat="commonjs"
const { getIntlayer, getMultilingualUrls } = require("intlayer");
const generateMetadata = async ({ params }) => {
const { locale } = await params;
const metadata = getIntlayer("page-metadata", locale);
/**
* Erzeugt ein Objekt, das alle URLs für jede Locale enthält.
*
* Beispiel:
* ```ts
* getMultilingualUrls('/about');
*
* // Gibt zurück
* // {
* // en: '/about',
* // fr: '/fr/about',
* // es: '/es/about'
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
const localizedUrl = multilingualUrls[locale];
return {
...metadata,
alternates: {
canonical: localizedUrl,
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: localizedUrl,
},
};
};
module.exports = { generateMetadata };
// ... Rest des Codes
````
> Beachten Sie, dass die Funktion `getIntlayer`, die aus `next-intlayer` importiert wird, Ihren Inhalt in einem `IntlayerNode` kapselt, was die Integration mit dem visuellen Editor ermöglicht. Im Gegensatz dazu gibt die aus `intlayer` importierte Funktion `getIntlayer` Ihren Inhalt direkt ohne zusätzliche Eigenschaften zurück.
Alternativ können Sie die Funktion `getTranslation` verwenden, um Ihre Metadaten zu deklarieren. Es wird jedoch empfohlen, Inhaltsdeklarationsdateien zu verwenden, um die Übersetzung Ihrer Metadaten zu automatisieren und den Inhalt irgendwann auszulagern.
```typescript fileName="src/app/[locale]/layout.tsx or src/app/[locale]/page.tsx" codeFormat="typescript"
import {
type IConfigLocales,
getTranslation,
getMultilingualUrls,
} from "intlayer";
import type { Metadata } from "next";
import type { LocalPromiseParams } from "next-intlayer";
export const generateMetadata = async ({
params,
}: LocalPromiseParams): Promise<Metadata> => {
const { locale } = await params;
const t = <T>(content: IConfigLocales<T>) => getTranslation(content, locale);
return {
title: t<string>({
en: "My title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: "My description",
fr: "Ma description",
es: "Mi descripción",
}),
};
};
// ... Rest des Codes
```
```javascript fileName="src/app/[locale]/layout.mjs or src/app/[locale]/page.mjs" codeFormat="esm"
import { getTranslation, getMultilingualUrls } from "intlayer";
export const generateMetadata = async ({ params }) => {
const { locale } = await params;
const t = (content) => getTranslation(content, locale);
return {
title: t({
en: "My title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: "My description",
fr: "Ma description",
es: "Mi descripción",
}),
};
};
// ... Rest des Codes
```
```javascript fileName="src/app/[locale]/layout.cjs or src/app/[locale]/page.cjs" codeFormat="commonjs"
const { getTranslation, getMultilingualUrls } = require("intlayer");
const generateMetadata = async ({ params }) => {
const { locale } = await params;
const t = (content) => getTranslation(content, locale);
return {
title: t({
en: "My title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: "My description",
fr: "Ma description",
es: "Mi descripción",
}),
};
};
module.exports = { generateMetadata };
// ... Rest des Codes
```
> Erfahren Sie mehr über die Optimierung von Metadaten [in der offiziellen Next.js-Dokumentation](https://nextjs.org/docs/app/building-your-application/optimizing/metadata).
### (Optional) Schritt 9: Internationalisierung Ihrer sitemap.xml und robots.txt
Um Ihre `sitemap.xml` und `robots.txt` zu internationalisieren, können Sie die von Intlayer bereitgestellte Funktion `getMultilingualUrls` verwenden. Diese Funktion ermöglicht es Ihnen, mehrsprachige URLs für Ihre Sitemap zu generieren.
```tsx fileName="src/app/sitemap.ts" codeFormat="typescript"
import { getMultilingualUrls } from "intlayer";
import type { MetadataRoute } from "next";
const sitemap = (): MetadataRoute.Sitemap => [
{
url: "https://example.com",
alternates: {
languages: {
...getMultilingualUrls("https://example.com"),
"x-default": "https://example.com",
},
},
},
{
url: "https://example.com/login",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/login"),
"x-default": "https://example.com/login",
},
},
},
{
url: "https://example.com/register",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/register"),
"x-default": "https://example.com/register",
},
},
},
];
export default sitemap;
```
```jsx fileName="src/app/sitemap.mjx" codeFormat="esm"
import { getMultilingualUrls } from "intlayer";
const sitemap = () => [
{
url: "https://example.com",
alternates: {
languages: {
...getMultilingualUrls("https://example.com"),
"x-default": "https://example.com",
},
},
},
{
url: "https://example.com/login",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/login"),
"x-default": "https://example.com/login",
},
},
},
{
url: "https://example.com/register",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/register"),
"x-default": "https://example.com/register",
},
},
},
];
export default sitemap;
```
```jsx fileName="src/app/sitemap.csx" codeFormat="commonjs"
const { getMultilingualUrls } = require("intlayer");
const sitemap = () => [
{
url: "https://example.com",
alternates: {
languages: {
...getMultilingualUrls("https://example.com"),
"x-default": "https://example.com",
},
},
},
{
url: "https://example.com/login",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/login"),
"x-default": "https://example.com/login",
},
},
},
{
url: "https://example.com/register",
alternates: {
languages: {
...getMultilingualUrls("https://example.com/register"),
"x-default": "https://example.com/register",
},
},
},
];
module.exports = sitemap;
```
```tsx fileName="src/app/robots.ts" codeFormat="typescript"
import type { MetadataRoute } from "next";
import { getMultilingualUrls } from "intlayer";
// Funktion, die alle mehrsprachigen URLs aus einer Liste von URLs extrahiert
const getAllMultilingualUrls = (urls: string[]) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
// Definition der Robots-Metadaten mit Regeln für Suchmaschinen-Crawler
const robots = (): MetadataRoute.Robots => ({
rules: {
userAgent: "*",
allow: ["/"], // Erlaubt den Zugriff auf die Startseite
disallow: getAllMultilingualUrls(["/login", "/register"]), // Verweigert Zugriff auf Login- und Registrierungsseiten in allen Sprachen
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
export default robots;
```
```jsx fileName="src/app/robots.mjx" codeFormat="esm"
import { getMultilingualUrls } from "intlayer";
const getAllMultilingualUrls = (urls) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)));
const robots = () => ({
rules: {
userAgent: "*",
allow: ["/"],
disallow: getAllMultilingualUrls(["/login", "/register"]),
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
export default robots;
```
```jsx fileName="src/app/robots.csx" codeFormat="commonjs"
const { getMultilingualUrls } = require("intlayer");
const getAllMultilingualUrls = (urls) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)));
const robots = () => ({
rules: {
userAgent: "*",
allow: ["/"],
disallow: getAllMultilingualUrls(["/login", "/register"]),
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
module.exports = robots;
```
> Erfahren Sie mehr über die Sitemap-Optimierung [in der offiziellen Next.js-Dokumentation](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap). Erfahren Sie mehr über die robots.txt-Optimierung [in der offiziellen Next.js-Dokumentation](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots).
### (Optional) Schritt 10: Ändern Sie die Sprache Ihres Inhalts
Um die Sprache Ihres Inhalts in Next.js zu ändern, wird empfohlen, die `Link`-Komponente zu verwenden, um Benutzer auf die entsprechende lokalisierte Seite weiterzuleiten. Die `Link`-Komponente ermöglicht das Vorabrufen der Seite, was hilft, ein vollständiges Neuladen der Seite zu vermeiden.
```tsx fileName="src/components/LocaleSwitcher.tsx" codeFormat="typescript"
"use client";
import type { FC } from "react";
import {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} from "intlayer";
import { useLocale } from "next-intlayer";
import Link from "next/link";
export const LocaleSwitcher: FC = () => {
const { locale, pathWithoutLocale, availableLocales, setLocale } =
useLocale();
return (
<div>
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
<div id="localePopover" popover="auto">
{availableLocales.map((localeItem) => (
<Link
href={getLocalizedUrl(pathWithoutLocale, localeItem)}
hrefLang={localeItem}
key={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={() => setLocale(localeItem)}
>
<span>
{/* Gebietsschema - z.B. FR */}
{localeItem}
</span>
<span>
{/* Sprache im eigenen Gebietsschema - z.B. Français */}
{getLocaleName(localeItem, locale)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* Sprache im aktuellen Gebietsschema - z.B. Francés, wenn aktuelles Gebietsschema auf Locales.SPANISH gesetzt ist */}
{getLocaleName(localeItem)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* Sprache auf Englisch - z.B. French */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
</Link>
))}
</div>
</div>
);
};
```
```jsx fileName="src/components/LocaleSwitcher.msx" codeFormat="esm"
"use client";
import {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} from "intlayer";
import { useLocale } from "next-intlayer";
import Link from "next/link";
export const LocaleSwitcher = () => {
const { locale, pathWithoutLocale, availableLocales, setLocale } =
useLocale();
return (
<div>
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
<div id="localePopover" popover="auto">
{availableLocales.map((localeItem) => (
<Link
href={getLocalizedUrl(pathWithoutLocale, localeItem)}
hrefLang={localeItem}
key={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={() => setLocale(localeItem)}
>
<span>
{/* Gebietsschema - z.B. FR */}
{localeItem}
</span>
<span>
{/* Sprache in ihrem eigenen Gebietsschema - z.B. Français */}
{getLocaleName(localeItem, locale)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* Sprache im aktuellen Gebietsschema - z.B. Francés, wenn das aktuelle Gebietsschema auf Locales.SPANISH gesetzt ist */}
{getLocaleName(localeItem)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* Sprache auf Englisch - z.B. French */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
</Link>
))}
</div>
</div>
);
};
```
```jsx fileName="src/components/LocaleSwitcher.csx" codeFormat="commonjs"
"use client";
const {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} = require("intlayer");
const { useLocale } = require("next-intlayer");
const Link = require("next/link");
export const LocaleSwitcher = () => {
const { locale, pathWithoutLocale, availableLocales, setLocale } =
useLocale();
return (
<div>
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
<div id="localePopover" popover="auto">
{availableLocales.map((localeItem) => (
<Link
href={getLocalizedUrl(pathWithoutLocale, localeItem)}
hrefLang={localeItem}
key={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={() => setLocale(localeItem)}
>
<span>
{/* Gebietsschema - z.B. FR */}
{localeItem}
</span>
<span>
{/* Sprache im eigenen Gebietsschema - z.B. Français */}
{getLocaleName(localeItem, locale)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* Sprache im aktuellen Gebietsschema - z.B. Francés mit aktuellem Gebietsschema auf Locales.SPANISH gesetzt */}
{getLocaleName(localeItem)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* Sprache auf Englisch - z.B. Französisch */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
</Link>
))}
</div>
</div>
);
};
```
> Eine alternative Möglichkeit ist die Verwendung der Funktion `setLocale`, die vom `useLocale` Hook bereitgestellt wird. Diese Funktion erlaubt kein Prefetching der Seite und lädt die Seite neu.
> In diesem Fall ändert nur Ihr serverseitiger Code die Sprache des Inhalts, ohne eine Weiterleitung mittels `router.push` durchzuführen.
```tsx fileName="src/components/LocaleSwitcher.tsx" codeFormat="typescript"
"use client";
import { useRouter } from "next/navigation";
import { useLocale } from "next-intlayer";
import { getLocalizedUrl } from "intlayer";
// ... Rest des Codes
const router = useRouter();
const { setLocale } = useLocale({
onLocaleChange: (locale) => {
router.push(getLocalizedUrl(pathWithoutLocale, locale));
},
});
return (
<button onClick={() => setLocale(Locales.FRENCH)}>
Wechsel zu Französisch
</button>
);
```
> Dokumentationsverweise:
>
> - [`useLocale` Hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useLocale.md)
> - [`getLocaleName` Hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/intlayer/getLocaleName.md)
> - [`getLocalizedUrl` Hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/intlayer/getLocalizedUrl.md)
> - [`getHTMLTextDir` Hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/intlayer/getHTMLTextDir.md)
> - [`hrefLang` Attribut](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)
> - [`lang` Attribut](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)
> - [`dir` Attribut](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
> - [`aria-current` Attribut](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)
### (Optional) Schritt 11: Erstellen einer lokalisierten Link-Komponente
Um sicherzustellen, dass die Navigation Ihrer Anwendung die aktuelle Sprache berücksichtigt, können Sie eine benutzerdefinierte `Link`-Komponente erstellen. Diese Komponente fügt internen URLs automatisch das aktuelle Sprachpräfix hinzu. Zum Beispiel wird ein französischsprachiger Benutzer, der auf einen Link zur „Über uns“-Seite klickt, zu `/fr/about` statt zu `/about` weitergeleitet.
Dieses Verhalten ist aus mehreren Gründen nützlich:
- **SEO und Benutzererfahrung**: Lokalisierte URLs helfen Suchmaschinen, sprachspezifische Seiten korrekt zu indexieren, und bieten den Benutzern Inhalte in ihrer bevorzugten Sprache.
- **Konsistenz**: Durch die Verwendung eines lokalisierten Links in der gesamten Anwendung wird sichergestellt, dass die Navigation innerhalb der aktuellen Sprache bleibt und unerwartete Sprachwechsel vermieden werden.
- **Wartbarkeit**: Die Zentralisierung der Lokalisierungslogik in einer einzigen Komponente vereinfacht die Verwaltung von URLs und macht Ihren Code leichter wartbar und erweiterbar, wenn Ihre Anwendung wächst.
Nachfolgend finden Sie die Implementierung einer lokalisierten `Link`-Komponente in TypeScript:
```tsx fileName="src/components/Link.tsx" codeFormat="typescript"
"use client";
import { getLocalizedUrl } from "intlayer";
import NextLink, { type LinkProps as NextLinkProps } from "next/link";
import { useLocale } from "next-intlayer";
import type { PropsWithChildren, FC } from "react";
/**
* Hilfsfunktion zur Überprüfung, ob eine gegebene URL extern ist.
* Wenn die URL mit http:// oder https:// beginnt, wird sie als extern betrachtet.
*/
export const checkIsExternalLink = (href?: string): boolean =>
/^https?:\/\//.test(href ?? "");
/**
* Eine benutzerdefinierte Link-Komponente, die das href-Attribut basierend auf der aktuellen Sprache anpasst.
* Für interne Links wird `getLocalizedUrl` verwendet, um die URL mit dem Sprachpräfix zu versehen (z. B. /fr/about).
* Dies stellt sicher, dass die Navigation im gleichen Sprachkontext bleibt.
*/
export const Link: FC<PropsWithChildren<NextLinkProps>> = ({
href,
children,
...props
}) => {
const { locale } = useLocale();
const isExternalLink = checkIsExternalLink(href.toString());
// Wenn der Link intern ist und eine gültige href vorhanden ist, wird die lokalisierte URL ermittelt.
const hrefI18n: NextLinkProps["href"] =
href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;
return (
<NextLink href={hrefI18n} {...props}>
{children}
</NextLink>
);
};
```
```jsx fileName="src/components/Link.mjx" codeFormat="esm"
"use client";
import { getLocalizedUrl } from "intlayer";
import NextLink from "next/link";
import { useLocale } from "next-intlayer";
/**
* Hilfsfunktion, um zu prüfen, ob eine gegebene URL extern ist.
* Wenn die URL mit http:// oder https:// beginnt, wird sie als extern betrachtet.
*/
export const checkIsExternalLink = (href) => /^https?:\/\//.test(href ?? "");
/**
* Eine benutzerdefinierte Link-Komponente, die das href-Attribut basierend auf der aktuellen Locale anpasst.
* Für interne Links wird `getLocalizedUrl` verwendet, um die URL mit der Locale zu versehen (z.B. /fr/about).
* Dies stellt sicher, dass die Navigation im gleichen Locale-Kontext bleibt.
*/
export const Link = ({ href, children, ...props }) => {
const { locale } = useLocale();
const isExternalLink = checkIsExternalLink(href.toString());
// Wenn der Link intern ist und eine gültige href angegeben ist, wird die lokalisierte URL ermittelt.
const hrefI18n =
href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;
return (
<NextLink href={hrefI18n} {...props}>
{children}
</NextLink>
);
};
```
```jsx fileName="src/components/Link.csx" codeFormat="commonjs"
"use client";
const { getLocalizedUrl } = require("intlayer");
const NextLink = require("next/link");
const { useLocale } = require("next-intlayer");
/**
* Hilfsfunktion, um zu prüfen, ob eine gegebene URL extern ist.
* Wenn die URL mit http:// oder https:// beginnt, wird sie als extern betrachtet.
*/
const checkIsExternalLink = (href) => /^https?:\/\//.test(href ?? "");
/**
* Eine benutzerdefinierte Link-Komponente, die das href-Attribut basierend auf der aktuellen Sprache anpasst.
* Für interne Links wird `getLocalizedUrl` verwendet, um die URL mit dem Sprachpräfix zu versehen (z.B. /fr/about).
* Dies stellt sicher, dass die Navigation im gleichen Sprachkontext bleibt.
*/
const Link = ({ href, children, ...props }) => {
const { locale } = useLocale();
const isExternalLink = checkIsExternalLink(href.toString());
// Wenn der Link intern ist und eine gültige href vorhanden ist, wird die lokalisierte URL ermittelt.
const hrefI18n =
href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;
return (
<NextLink href={hrefI18n} {...props}>
{children}
</NextLink>
);
};
```
#### Funktionsweise
- **Erkennung externer Links**:
Die Hilfsfunktion `checkIsExternalLink` bestimmt, ob eine URL extern ist. Externe Links bleiben unverändert, da sie keine Lokalisierung benötigen.
- **Abrufen der aktuellen Locale**:
Der Hook `useLocale` liefert die aktuelle Locale (z.B. `fr` für Französisch).
- **Lokalisierung der URL**:
Für interne Links (d.h. nicht extern) wird `getLocalizedUrl` verwendet, um die URL automatisch mit der aktuellen Locale zu versehen. Das bedeutet, wenn Ihr Benutzer Französisch eingestellt hat, wird `/about` als `href` zu `/fr/about` umgewandelt.
- **Rückgabe des Links**:
Die Komponente gibt ein `<a>`-Element mit der lokalisierten URL zurück, wodurch sichergestellt wird, dass die Navigation konsistent mit der Locale erfolgt.
Indem Sie diese `Link`-Komponente in Ihrer gesamten Anwendung integrieren, gewährleisten Sie eine kohärente und sprachbewusste Benutzererfahrung und profitieren gleichzeitig von verbesserter SEO und Benutzerfreundlichkeit.
### (Optional) Schritt 12: Optimieren Sie Ihre Bundle-Größe
Bei der Verwendung von `next-intlayer` werden Wörterbücher standardmäßig in das Bundle jeder Seite aufgenommen. Um die Bundle-Größe zu optimieren, stellt Intlayer ein optionales SWC-Plugin bereit, das `useIntlayer`-Aufrufe mithilfe von Makros intelligent ersetzt. Dadurch werden Wörterbücher nur in die Bundles der Seiten aufgenommen, die sie tatsächlich verwenden.
Um diese Optimierung zu aktivieren, installieren Sie das Paket `@intlayer/swc`. Nach der Installation erkennt `next-intlayer` das Plugin automatisch und verwendet es:
```bash packageManager="npm"
npm install @intlayer/swc --save-dev
```
```bash packageManager="pnpm"
pnpm add @intlayer/swc --save-dev
```
```bash packageManager="yarn"
yarn add @intlayer/swc --save-dev
```
```bash packageManager="bun"
bun add @intlayer/swc --dev
```
> Hinweis: Diese Optimierung ist nur für Next.js 13 und höher verfügbar.
> Hinweis: Dieses Paket ist nicht standardmäßig installiert, da SWC-Plugins in Next.js noch experimentell sind. Dies kann sich in Zukunft ändern.
### TypeScript konfigurieren
Intlayer verwendet Module Augmentation, um die Vorteile von TypeScript zu nutzen und Ihren Code robuster zu machen.


Stellen Sie sicher, dass Ihre TypeScript-Konfiguration die automatisch generierten Typen einschließt.
```json5 fileName="tsconfig.json"
{
// ... Ihre bestehenden TypeScript-Konfigurationen
"include": [
// ... Ihre bestehenden TypeScript-Konfigurationen
".intlayer/**/*.ts", // Einschluss der automatisch generierten Typen
],
}
```
### Git-Konfiguration
Es wird empfohlen, die von Intlayer generierten Dateien zu ignorieren. So vermeiden Sie, dass diese in Ihr Git-Repository committet werden.
Dazu können Sie die folgenden Anweisungen in Ihre `.gitignore`-Datei aufnehmen:
```plaintext fileName=".gitignore"
# Ignoriere die von Intlayer generierten Dateien
.intlayer
```
### VS Code Erweiterung
Um Ihre Entwicklungserfahrung mit Intlayer zu verbessern, können Sie die offizielle **Intlayer VS Code Erweiterung** installieren.
[Installation aus dem VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
Diese Erweiterung bietet:
- **Autovervollständigung** für Übersetzungsschlüssel.
- **Echtzeit-Fehlererkennung** für fehlende Übersetzungen.
- **Inline-Vorschauen** des übersetzten Inhalts.
- **Schnellaktionen**, um Übersetzungen einfach zu erstellen und zu aktualisieren.
Für weitere Details zur Nutzung der Erweiterung siehe die [Intlayer VS Code Extension Dokumentation](https://intlayer.org/doc/vs-code-extension).
### Weiterführende Schritte
Um weiterzugehen, können Sie den [visuellen Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_visual_editor.md) implementieren oder Ihre Inhalte mit dem [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_CMS.md) auslagern.