---
createdAt: 2025-09-22
updatedAt: 2026-01-26
title: Neues Intlayer v8 - Was ist neu?
description: Entdecken Sie die Neuerungen in Intlayer v8. Bedeutende Verbesserungen in der Developer Experience, der Inhaltsvalidierung und der Verwaltung von Dictionaries.
keywords:
  - Intlayer
  - CMS
  - Developer Experience
  - Funktionen
  - React
  - Next.js
  - JavaScript
  - TypeScript
youtubeVideo: https://www.youtube.com/watch?v=ia6JmVf-kkU
slugs:
  - doc
  - releases
  - v8
---

# Neues Intlayer v8 - Was ist neu?

Willkommen bei Intlayer v8! Diese Version konzentriert sich darauf, die Developer Experience durch automatische Inhaltserkennung zu verbessern, die Datenintegrität mittels Schema-Validierung sicherzustellen und mehr Kontrolle über die Verwaltung von Dictionaries zu bieten.

<iframe
  src="https://www.youtube.com/embed/ia6JmVf-kkU"
  className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
  title="Demo Video - New Intlayer v8 - What's new?"
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
  loading="lazy"
/>

## Inhaltsverzeichnis

<TOC levels={[2]} maxDepth={1} />

---

## Evolution von Rich Content: Markdown & HTML

Intlayer v8 bringt bedeutende Verbesserungen beim Umgang mit Rich Content mit sich, führt **HTML-Knoten** ein (die es in v7 nicht gab) und vereinheitlicht die API mit **Markdown-Knoten** (die es bereits in v7 gab, aber verbessert wurden).

### Die vereinheitlichte `.use()` API

Wir haben die `.use()` Methode sowohl für Markdown- als auch für HTML-Knoten eingeführt. Diese Methode ermöglicht es Ihnen, die HTML-Tags oder Komponenten anzupassen, die während des Renderings verwendet werden.

- **Komponentenersatz**: Sie können HTML-Tags oder benutzerdefinierte Komponenten ganz einfach durch Ihre eigenen Framework-Komponenten ersetzen (z. B. `<a>` durch `NextLink` oder `<CustomCmp>` durch eine React-Komponente).
- **Typsicherheit**: Alle Funktionen zur Bereitstellung von Komponenten sind vollständig getypt, um sicherzustellen, dass Sie die richtigen Props erhalten.

### Standard-Rendering-Verhalten

In v7 wurden Markdown-Knoten, wenn kein Provider definiert war, als reine Strings gerendert, was oft externe Bibliotheken zum Parsen erforderte.

**In v8 enthält Intlayer einen eigenen internen Markdown-Parser.** Standardmäßig werden Markdown-Knoten nun direkt als HTML gerendert, ohne dass externe Bibliotheken benötigt werden.

### Neue Renderer & Provider Utilities

Wir haben neue eigenständige Renderer-Funktionen und Komponenten eingeführt, um Ihnen mehr Kontrolle außerhalb des Standard-`useIntlayer`-Flows zu geben.

- **Markdown**: `MarkdownRenderer`, `useMarkdownRenderer`, `renderMarkdown`. (Hinweis: `MarkdownProvider` existierte bereits in v7, lässt sich aber nun in diese neuen Tools integrieren).
- **HTML**: `HTMLRenderer`, `useHTMLRenderer`, `renderHTML`, `HTMLProvider`.

#### Beispiele: Markdown-Rendering-Tools

<Tabs group='framework'>
  <Tab label="React / Next.js" value="react">

    **1. Verwendung der Komponente:**

    ```tsx
    import { MarkdownRenderer } from "react-intlayer";

    <MarkdownRenderer
      forceBlock={true}
      components={{
        h1: ({ children }) => <h1 className="text-2xl">{children}</h1>
      }}
    >
      {"# Mein Titel"}
    </MarkdownRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useMarkdownRenderer } from "react-intlayer";

    const renderMarkdown = useMarkdownRenderer({
      components: {
        h1: ({ children }) => <h1 className="text-red-500">{children}</h1>
      }
    });

    return <div>{renderMarkdown("# Mein Titel")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderMarkdown } from "react-intlayer";

    const html = renderMarkdown("# Mein Titel", {
      forceBlock: true
    });
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    **1. Verwendung der Komponente:**

    ```vue
    <script setup>
    import { MarkdownRenderer } from "vue-intlayer";
    </script>

    <template>
      <MarkdownRenderer :forceBlock="true" content="# Mein Titel" />
    </template>
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    **1. Verwendung der Komponente:**

    ```svelte
    <script>
      import { MarkdownRenderer } from "svelte-intlayer";
    </script>

    <MarkdownRenderer forceBlock={true} value="# Mein Titel" />
    ```

    **2. Verwendung des Hooks:**

    ```svelte
    <script>
      import { useMarkdownRenderer } from "svelte-intlayer";
      const render = useMarkdownRenderer();
    </script>

    {@html render("# Mein Titel")}
    ```

    **3. Verwendung der Utility-Funktion:**

    ```svelte
    <script>
      import { renderMarkdown } from "svelte-intlayer";
    </script>

    {@html renderMarkdown("# Mein Titel")}
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    **1. Verwendung des Service:**

    ```typescript
    import { Component } from "@angular/core";
    import { IntlayerMarkdownService } from "angular-intlayer";

    @Component({ ... })
    export class MyComponent {
      constructor(private markdownService: IntlayerMarkdownService) {}

      render(markdown: string) {
        return this.markdownService.renderMarkdown(markdown);
      }
    }
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    **1. Verwendung der Komponente:**

    ```tsx
    import { MarkdownRenderer } from "solid-intlayer";

    <MarkdownRenderer forceBlock={true}>
      {"# Mein Titel"}
    </MarkdownRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useMarkdownRenderer } from "solid-intlayer";

    const render = useMarkdownRenderer();

    return <div>{render("# Mein Titel")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderMarkdown } from "solid-intlayer";

    return <div>{renderMarkdown("# Mein Titel")}</div>;
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    **1. Verwendung der Komponente:**

    ```tsx
    import { MarkdownRenderer } from "preact-intlayer";

    <MarkdownRenderer forceBlock={true}>
      {"# Mein Titel"}
    </MarkdownRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useMarkdownRenderer } from "preact-intlayer";

    const render = useMarkdownRenderer();

    return <div>{render("# Mein Titel")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderMarkdown } from "preact-intlayer";

    return <div>{renderMarkdown("# Mein Titel")}</div>;
    ```

  </Tab>
</Tabs>

#### Beispiele: HTML-Rendering-Tools

<Tabs group='framework'>
  <Tab label="React / Next.js" value="react">

    **1. Verwendung der Komponente:**

    ```tsx
    import { HTMLRenderer } from "react-intlayer";

    <HTMLRenderer
      components={{
        p: ({ children }) => <p className="mb-4">{children}</p>
      }}
    >
      {"<p>Hallo Welt</p>"}
    </HTMLRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useHTMLRenderer } from "react-intlayer";

    const renderHTML = useHTMLRenderer({
      components: {
        strong: ({ children }) => <b className="font-bold">{children}</b>
      }
    });

    return <div>{renderHTML("<p>Hallo <strong>Welt</strong></p>")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderHTML } from "react-intlayer";

    const html = renderHTML("<p>Hallo Welt</p>");
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    **1. Verwendung der Komponente:**

    ```vue
    <script setup>
    import { HTMLRenderer } from "vue-intlayer";
    </script>

    <template>
      <HTMLRenderer content="<p>Hallo Welt</p>" />
    </template>
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    **1. Verwendung der Komponente:**

    ```svelte
    <script>
      import { HTMLRenderer } from "svelte-intlayer";
    </script>

    <HTMLRenderer value="<p>Hallo Welt</p>" />
    ```

    **2. Verwendung des Hooks:**

    ```svelte
    <script>
      import { useHTMLRenderer } from "svelte-intlayer";
      const render = useHTMLRenderer();
    </script>

    {@html render("<p>Hallo Welt</p>")}
    ```

    **3. Verwendung der Utility-Funktion:**

    ```svelte
    <script>
      import { renderHTML } from "svelte-intlayer";
    </script>

    {@html renderHTML("<p>Hallo Welt</p>")}
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    **1. Direkte Verwendung:**

    In Angular können Sie die Standard-`[innerHTML]`-Bindung verwenden.

    ```html
    <div [innerHTML]="'<p>Hallo Welt</p>'"></div>
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    **1. Verwendung der Komponente:**

    ```tsx
    import { HTMLRenderer } from "solid-intlayer";

    <HTMLRenderer>
      {"<p>Hallo Welt</p>"}
    </HTMLRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useHTMLRenderer } from "solid-intlayer";

    const render = useHTMLRenderer();

    return <div>{render("<p>Hallo Welt</p>")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderHTML } from "solid-intlayer";

    return <div>{renderHTML("<p>Hallo Welt</p>")}</div>;
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    **1. Verwendung der Komponente:**

    ```tsx
    import { HTMLRenderer } from "preact-intlayer";

    <HTMLRenderer>
      {"<p>Hallo Welt</p>"}
    </HTMLRenderer>
    ```

    **2. Verwendung des Hooks:**

    ```tsx
    import { useHTMLRenderer } from "preact-intlayer";

    const render = useHTMLRenderer();

    return <div>{render("<p>Hallo Welt</p>")}</div>;
    ```

    **3. Verwendung der Utility-Funktion:**

    ```tsx
    import { renderHTML } from "preact-intlayer";

    return <div>{renderHTML("<p>Hallo Welt</p>")}</div>;
    ```

  </Tab>
</Tabs>

Weitere Einzelheiten finden Sie in der [Dokumentation zu HTML-Inhalten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/html.md) und in der [Markdown-Dokumentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/markdown.md).

---

## Benutzerdefinierte URL-Umschreibungen (Rewrites)

Intlayer v8 führt Unterstützung für **benutzerdefinierte URL-Umschreibungen** ein, mit denen Sie locale-spezifische Pfade definieren können, die von der Standardstruktur `/locale/path` abweichen. Dies ist eine leistungsstarke Funktion zur Verbesserung der lokalen SEO und bietet eine natürlichere Benutzererfahrung für nicht-englischsprachige Nutzer.

**Wesentliche Verbesserungen in v8:**

- **Framework-Formatter**: Neue `nextjsRewrite`, `svelteKitRewrite`, `reactRouterRewrite`, `vueRouterRewrite`, `solidRouterRewrite`, `tanstackRouterRewrite`, `nuxtRewrite` und `viteRewrite`, um für jeden Router eine idiomatische Mustersyntax bereitzustellen.
- **`useRewriteURL` Hook**: Ein neues clientseitiges Hook, das die Adressleiste stillschweigend auf die "schöne" lokalisierte URL korrigiert, ohne Router-Navigationen auszulösen.
- **Automatische SEO-Weiterleitungen**: Eingebaute Proxys leiten Benutzer nun automatisch von manuell eingegebenen kanonischen Pfaden (z. B. `/fr/about`) zu ihren schöneren lokalisierten Versionen (z. B. `/fr/a-propos`) weiter.

**Beispiel-Konfiguration:**

<Tabs group='routers'>
  <Tab label="Next.js" value="nextjs">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { nextjsRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-no-default",
        rewrite: nextjsRewrite({
          "/[locale]/about": {
            fr: "/[locale]/a-propos",
            es: "/[locale]/acerca-de",
          },
          "/[locale]/products/[id]": {
            fr: "/[locale]/produits/[id]",
            es: "/[locale]/productos/[id]",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
    <Tab label="React Router" value="reactrouter">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { reactRouterRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: reactRouterRewrite({
          "/:locale/about": {
            fr: "/:locale/a-propos",
            es: "/:locale/acerca-de",
          },
          "/:locale/products/:id": {
            fr: "/:locale/produits/:id",
            es: "/:locale/productos/:id",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="Vite (Vue, Solid, Svelte)" value="vite">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { viteRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: viteRewrite({
          "/:locale/about": {
            fr: "/:locale/a-propos",
            es: "/:locale/acerca-de",
          },
          "/:locale/products/:id": {
            fr: "/:locale/produits/:id",
            es: "/:locale/productos/:id",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="Nuxt" value="nuxt">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { nuxtRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: nuxtRewrite({
          "/[locale]/about": {
            fr: "/[locale]/a-propos",
            es: "/[locale]/acerca-de",
          },
          "/[locale]/products/[id]": {
            fr: "/[locale]/produits/[id]",
            es: "/[locale]/productos/[id]",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="SvelteKit" value="sveltekit">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { svelteKitRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: svelteKitRewrite({
          "/[locale]/about": {
            fr: "/[locale]/a-propos",
            es: "/[locale]/acerca-de",
          },
          "/[locale]/products/[id]": {
            fr: "/[locale]/produits/[id]",
            es: "/[locale]/productos/[id]",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
</Tabs>

Diese Funktion wird standardmäßig in **Next.js** und **Vite** über die Intlayer-Proxys unterstützt und kann problemlos in andere Router wie **TanStack Router**, **React Router**, **Vue Router**, **SvelteKit** und **Solid Router** integriert werden.

Weitere Informationen und Integrationsleitfäden finden Sie in der [Dokumentation zu benutzerdefinierten URL-Umschreibungen](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/custom_url_rewrites.md).

---

### Verbesserte Insertion-Werte

In v8 können Insertion-Werte nun neben Strings und Zahlen auch **React-Elemente (oder Vue-Knoten)** akzeptieren. Dies ermöglicht es Ihnen, reichhaltige, interaktive Komponenten direkt in Ihre Insertion-Vorlagen einzufügen.

Intlayer verarbeitet jetzt robust verschachtelte React- und Preact-Knoten innerhalb von Insertions und stellt sicher, dass komplexe UI-Strukturen erhalten bleiben und korrekt gerendert werden.

**Beispiel:**

```typescript fileName="src/example.content.ts"
import { insert } from "intlayer";

export default {
  key: "my-key",
  content: {
    myInsertion: insert("Hallo {{name}}"),
  },
};
```

<Tabs group='framework'>
  <Tab label="Next.js" value="nextjs">

    ```tsx
    import { useIntlayer } from "next-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // Zahl
          // oder
          name: "John", // String
          // oder
          name: <span>John</span>, // React-Element
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="React" value="react">

    ```tsx
    import { useIntlayer } from "react-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // Zahl
          // oder
          name: "John", // String
          // oder
          name: <span>John</span>, // React-Element
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    ```vue
    <script setup>
    import { h } from "vue";
    import { useIntlayer } from "vue-intlayer";

    const { myInsertion } = useIntlayer("my-key");
    </script>

    <template>
      <div>
        <component
          :is="myInsertion({
            name: 2,
            // oder
            name: 'John',
            // oder
            name: h('span', 'John'),
          })"
        />
      </div>
    </template>
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    ```tsx
    import { useIntlayer } from "preact-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // Zahl
          // oder
          name: "John", // String
          // oder
          name: <span>John</span>, // Preact-Element
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    ```tsx
    import { useIntlayer } from "solid-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // Zahl
          // oder
          name: "John", // String
          // oder
          name: <span>John</span>, // Solid-Element
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    ```svelte
    <script>
      import { useIntlayer } from "svelte-intlayer";

      const { myInsertion } = useIntlayer("my-key");
    </script>

    <div>
      {myInsertion({
        name: 2, // Zahl
        // oder
        name: "John", // String
      })}
    </div>
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    ```typescript
    import { Component } from "@angular/core";
    import { useIntlayer } from "angular-intlayer";

    @Component({
      selector: "app-insertion-example",
      template: `
        <div>
          {{ content().myInsertion({
            name: 'John'
          }) }}
        </div>
      `,
    })
    export class InsertionExampleComponent {
      content = useIntlayer("my-key");
    }
    ```

  </Tab>
</Tabs>

## Inhalts-Schema-Validierung

Intlayer v8 führt die Schema-Validierung für Dictionaries ein. Sie können jetzt wiederverwendbare Validierungsschemata in Ihrer Konfiguration mit Zod definieren und auf Ihre Inhaltsdateien anwenden. Dies stellt sicher, dass Ihr Inhalt immer der erwarteten Struktur entspricht, und fängt Fehler bereits zur Build-Zeit ab.

### 1. Schemata definieren

Definieren Sie Ihre Schemata in `intlayer.config.ts`:

```typescript fileName="intlayer.config.ts"
import { z } from "zod";

export default {
  schemas: {
    "seo-metadata": z.object({
      title: z.string().min(50).max(60),
      description: z.string().min(150).max(160),
    }),
  },
};
```

### 2. Schemata auf Dictionaries anwenden

Verweisen Sie in Ihrer Dictionary-Definition auf den Schema-Schlüssel:

```typescript fileName="src/example.content.ts"
import { type Dictionary } from "intlayer";

const aboutPageMetaContent = {
  key: "about-page-meta",
  schema: "seo-metadata", // <--
  content: {
    title: "Über unser Unternehmen – Erfahren Sie mehr über uns",
    description:
      "Entdecken Sie die Mission, Werte und das Team unseres Unternehmens.",
  },
} satisfies Dictionary;

export default aboutPageMetaContent;
```

Wenn der Inhalt nicht mit dem Schema übereinstimmt (z. B. der Titel zu kurz ist), gibt der Build-Prozess einen Fehler aus.

---

### Verbesserte automatische Inhaltserkennung

In v8 erkennt Intlayer intelligent Markdown-Syntax, HTML-Tags und Variablen-Insertions in Ihren Inhaltsstrings. Das bedeutet, dass Sie häufig auf Hilfsfunktionen wie `md()`, `html()` oder `insert()` verzichten können.

Dieses Verhalten ist standardmäßig aktiviert. Sie können diese Erkennung nun entweder global in Ihrer `intlayer.config.ts` oder pro Dictionary feinabstimmen.

#### Granulare Steuerung

Sie können bestimmte Arten von Transformationen aktivieren oder deaktivieren:

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    // contentAutoTransformation: false (Standard)
    contentAutoTransformation: {
      markdown: true,
      html: true,
      insertion: false, // Deaktiviert die automatische Erkennung von Insertions
    },
  },
};
```

**v7 Verhalten (manuelles Wrapping):**

```typescript fileName="src/example.content.ts"
import { md, insert } from "intlayer";

export default {
  key: "my-key",
  content: {
    myMarkdown: md("## Hallo Welt"),
    myInsertion: insert("Hallo {{name}}"),
  },
};
```

**v8 Verhalten (automatische Erkennung):**

```typescript fileName="src/example.content.ts"
export default {
  key: "my-key",
  contentAutoTransformation: true, // Kann auch über die Dictionary-Definition oder global in intlayer.config.ts gesetzt werden
  content: {
    myMarkdown: "## Hallo Welt", // Automatisch als Markdown erkannt
    myHTML: "<p>Hallo Welt</p>", // Automatisch als HTML erkannt
    myInsertion: "Hallo {{name}}", // Automatisch als Insertion erkannt
  },
};
```

Das zugrunde liegende JSON-Ergebnis bleibt gleich und bewahrt die umfangreichen Typinformationen, die für das Rendering erforderlich sind:

```json
{
  "key": "my-key",
  "content": {
    "myMarkdown": {
      "nodeType": "markdown",
      "markdown": "## Hallo Welt"
    },
    "myHTML": {
      "nodeType": "html",
      "html": "<p>Hallo Welt</p>"
    },
    "myInsertion": {
      "nodeType": "insertion",
      "insertion": "Hallo {{name}}"
    }
  }
}
```

---

## Lokalisierung: neuer `useIntl` Hook

Ein neuer `useIntl()` Hook ist jetzt in React, Next.js und Vue verfügbar. Er stellt ein an die Locale gebundenes `Intl`-Objekt bereit, das automatisch die aktuelle Sprache für die Formatierung von Zahlen, Daten und mehr verwendet, ohne dass die Locale manuell übergeben werden muss.

<Tabs group='framework'>
  <Tab label="Next.js" value="nextjs">

    ```tsx
    import { useIntl } from "next-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="React" value="react">

    ```tsx
    import { useIntl } from "react-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    ```vue
    <script setup>
    import { useIntl } from "vue-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    </script>
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    ```tsx
    import { useIntl } from "preact-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    ```tsx
    import { useIntl } from "solid-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    ```svelte
    <script>
      import { useIntl } from "svelte-intlayer";

      const intl = useIntl();

      const formattedPrice = new intl.NumberFormat({
        style: "currency",
        currency: "USD",
      }).format(123.45);
    </script>
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    ```typescript
    import { Component, computed } from "@angular/core";
    import { useIntl } from "angular-intlayer";

    @Component({
      selector: "app-intl-example",
      template: `<div>{{ formattedPrice() }}</div>`,
    })
    export class IntlExampleComponent {
      intl = useIntl();

      formattedPrice = computed(() =>
        new (this.intl().NumberFormat)({
          style: "currency",
          currency: "USD",
        }).format(123.45)
      );
    }
    ```

  </Tab>
</Tabs>

---

## Tooling: Erweiterungen der VSCode-Extension

Die Intlayer VSCode-Extension erhält in v8 bedeutende Updates, um Ihren Internationalisierungs-Workflow zu rationalisieren:

- **Startzeit**: Leistungsverbesserungen beim Öffnen eines Projekts.
- **Caching**: Verbesserte Caching-Schicht für nahezu sofortige Validierung und Autovervollständigung.
- **Erkennung ungenutzter & doppelt vergebener Schlüssel**: Neue Funktionen zur automatischen Erkennung von **ungenutzten Schlüsseln** und **doppelt vergebenen Schlüsseln** in Ihren Dictionaries, die Ihnen helfen, Ihren Inhalt sauber und effizient zu halten.

---

## Compiler-Optimierungen

Intlayer v8 enthält eine neue Caching-Schicht für den Markdown- und HTML-Compiler. Dies stellt sicher, dass identische Inhaltsstrings mit derselben Konfiguration nur einmal geparst werden, was den Overhead bei Re-Renderings oder bei der Verwendung desselben Inhalts an mehreren Stellen erheblich reduziert.

<Tabs group='bundler'>
  <Tab label="Next.js" value="nextjs">
  
    ```typescript fileName="babel.config.js"
      const {
      intlayerExtractBabelPlugin,
      intlayerOptimizeBabelPlugin,
      getExtractPluginOptions,
      getOptimizePluginOptions,
    } = require('@intlayer/babel');

    module.exports = {
      presets: ['next/babel'],
      plugins: [
        // Extrahiert Inhalte aus Komponenten in Dictionaries
        [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        // Optimiert Importe, indem useIntlayer durch direkte Dictionary-Importe ersetzt wird
        [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],
      ],
    };
    ```

  </Tab>
  <Tab label="Vite" value="vite">
   
    ```typescript fileName="vite.config.js"
    import { defineConfig } from 'vite';
    import {intlayer, intlayerCompiler} from 'vite-intlayer';

    export default defineConfig({
      plugins: [intlayer(), intlayerCompiler()],
    });
    ```

> Für Vue / Svelte müssen Sie das entsprechende Compiler-Paket installieren:
>
> ```bash
> # Für Vue
> npm install @intlayer/vue-compiler
> ```
>
> ```bash
> # Für Svelte
> npm install @intlayer/svelte-compiler
> ```

  </Tab>
</Tabs>

---

## Flexibilität: Einheitlicher Import-Modus

Die boolesche Eigenschaft `live` wurde zugunsten der umfassenderen Eigenschaft `importMode` als veraltet markiert. Dies ermöglicht eine explizite Definition, wie Dictionaries geladen werden sollen: statisch, dynamisch oder via Live-Synchronisierung.

### Modi

- **`static`** (Standard): Das Dictionary wird zum Zeitpunkt der Erstellung gebündelt. Am besten für die Performance.
- **`dynamic`**: Das Dictionary wird zur Laufzeit geladen (z. B. via JSON-Fetch oder Suspense).
- **`fetch`**: Das Dictionary wird zur Laufzeit vom CMS/Server abgerufen und synchronisiert.

**Migration:**

| v7 Konfig     | v8 Konfig                               |
| :------------ | :-------------------------------------- |
| `live: true`  | `importMode: 'fetch'`                   |
| `live: false` | `importMode: 'static'` (oder 'dynamic') |

Hinweis: In Intlayer v8 wurde die Eigenschaft `importMode` von der `build`-Konfiguration in die `dictionary`-Konfiguration in `intlayer.config.ts` verschoben. Dies ermöglicht es Ihnen, einen Standard-Importmodus für alle Ihre Dictionaries zu definieren und ihn dennoch für jedes Dictionary einzeln zu überschreiben.

**Beispiel für globale Konfiguration:**

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    importMode: "dynamic", // Globaler Standard
  },
  // ...
};
```

**Beispiel für ein Dictionary:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    importMode: "fetch", // Überschreibt die globale Konfiguration
    content: { ... }
}
```

---

## Steuerung des Speicherorts von Dictionaries

v8 führt die Eigenschaft `location` ein, um explizit zu verwalten, wo Dictionaries gespeichert werden und wie sie synchronisiert werden. Dies ist besonders nützlich für hybride Workflows, die sowohl lokale Dateien als auch Remote-CMS-Inhalte umfassen.

### Optionen

- **`local`**: Das Dictionary existiert nur lokal. Es wird nicht zum Remote-CMS übertragen.
- **`remote`**: Das Dictionary wird remote verwaltet. Sobald es auf das CMS übertragen wurde, wird es vom lokalen getrennt. Das Remote-Dictionary wird vom CMS abgerufen.
- **`local_and_remote`**: Das Dictionary existiert an beiden Orten. Lokale Änderungen werden übertragen, und Remote-Änderungen werden abgerufen (synchronisiert).

**Beispiel:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    location: "local", // Dieses Dictionary nur lokal belassen
    content: { ... }
}
```

---

## Trennung der Systemkonfiguration

Intlayer v8 trennt die Konfiguration von Inhaltsquellen von internen System- und Ausgabepfaden. Dies entschlackt die `content`-Eigenschaft und macht deutlich, welche Einstellungen für die Benutzerverwaltung vorgesehen sind und welche vom Intlayer-System verwaltet werden.

Die folgenden Eigenschaften wurden von `content` in eine neue `system`-Eigenschaft in `intlayer.config.ts` verschoben:

- `dictionariesDir`
- `moduleAugmentationDir`
- `unmergedDictionariesDir`
- `typesDir`
- `mainDir`
- `configDir`
- `cacheDir`
- `outputFilesPatternWithPath`

**v7 Verhalten:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
    dictionariesDir: ".intlayer/dictionary", // Vermischt mit Quellkonfiguration
  },
};
```

**v8 Verhalten:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
  },
  system: {
    dictionariesDir: ".intlayer/dictionary", // Klar getrennt
  },
};
```

---

## Trennung von Inhalts- und Code-Verzeichnissen

Intlayer v8 trennt die Konfiguration für Inhalts-Definitionsdateien von der Konfiguration für die Code-Transformation. Dies ermöglicht genaueres Watching und Scanning, was die Build-Performance verbessert.

Zuvor wurde `contentDir` sowohl für das Beobachten von `.content.*`-Dateien als auch für das Scannen von Code nach `useIntlayer`-Aufrufen verwendet. Jetzt:

- **`contentDir`**: Speziell für Ihre Inhalts-Deklarationsdateien.
- **`codeDir`**: Speziell für Ihren Anwendungscode, der transformiert werden muss (z. B. Bereinigung, Optimierung).

**Migration:**

Wenn Sie zuvor `contentDir` festgelegt hatten, verwendet Intlayer v8 dieses standardmäßig auch für `codeDir`, protokolliert jedoch eine Warnung. Sie sollten `codeDir` explizit in Ihrer Konfiguration definieren.

**v7 Verhalten:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src", "@packages/design-system"], // Sowohl für Inhalt als auch für Code verwendet
  },
};
```

**v8 Verhalten:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src/content", "@packages/design-system"], // Beobachtet hier nur src/content/*.content.* Dateien und @packages/design-system/dist/*.content.* Dateien
    codeDir: ["src", "@packages/design-system"], // Scant nur hier nach Code-Transformationen und @packages/design-system/src/*.content.* Dateien
  },
};
```

---

## Framework: Svelte-Verbesserungen

Markdown- und HTML-Inhalte in Svelte werden nun automatisch in HTML geparst, wenn sie in einen String umgewandelt werden. Dies erleichtert die Verwendung der Svelte-Syntax `{@html}` erheblich, da Sie nun einfach den Inhaltsknoten direkt übergeben können.

---

## Migrationshinweise von v7

### Konfigurationsänderungen

- **`live`-Eigenschaft**: Die `live`-Eigenschaft in Dictionaries wurde entfernt. Verwenden Sie stattdessen `importMode: 'fetch'`.
- **importMode**: Die Eigenschaft `build.importMode` in der Konfiguration ist veraltet. Verwenden Sie stattdessen `dictionary.importMode`.
- **`contentDir` und `codeDir`**: `contentDir` ist jetzt speziell für Inhaltsdateien. Eine neue Eigenschaft `codeDir` wurde für die Code-Transformation hinzugefügt. Wenn `codeDir` nicht gesetzt ist, fällt Intlayer auf `contentDir` zurück und protokolliert eine Warnung.
- **Schema-Validierung**: Um die neue `schema`-Funktion zu nutzen, stellen Sie sicher, dass `zod` in Ihrem Projekt installiert ist.

---

## Nützliche Links

- [Konfigurationsreferenz](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/configuration.md)
- [Dokumentation der Inhaltsdatei](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/content_file.md)
- [Dokumentation zu HTML-Inhalten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/html.md)
- [Dokumentation zu Markdown-Inhalten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/dictionary/markdown.md)
- [Dokumentation zu benutzerdefinierten URL-Umschreibungen](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/custom_url_rewrites.md)
