---
createdAt: 2025-09-22
updatedAt: 2026-01-26
title: Intlayer v8 Baru - Apa yang Baru?
description: Temukan apa yang baru di Intlayer v8. Peningkatan besar pada pengalaman pengembang, validasi konten, dan pengelolaan kamus.
keywords:
  - Intlayer
  - CMS
  - Developer Experience
  - Features
  - React
  - Next.js
  - JavaScript
  - TypeScript
youtubeVideo: https://www.youtube.com/watch?v=ia6JmVf-kkU
slugs:
  - doc
  - releases
  - v8
---

# Intlayer v8 Baru - Apa yang Baru?

Selamat datang di Intlayer v8! Rilis ini berfokus pada peningkatan pengalaman pengembang dengan deteksi konten otomatis, memastikan integritas data melalui validasi skema, dan memberikan lebih banyak kontrol atas pengelolaan kamus.

<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"
/>

## Daftar Isi

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

---

## Evolusi Konten Kaya: Markdown & HTML

Intlayer v8 membawa peningkatan besar pada cara penanganan konten kaya, memperkenalkan **node HTML** (yang tidak ada di v7) dan menyatukan API dengan **node Markdown** (yang ada di v7 tetapi telah ditingkatkan).

### API `.use()` yang Terpadu

Kami memperkenalkan metode `.use()` untuk node Markdown dan HTML. Metode ini memungkinkan Anda menyesuaikan tag HTML atau komponen yang digunakan selama proses render.

- **Penggantian Komponen**: Anda dapat dengan mudah mengganti tag HTML atau komponen kustom dengan komponen framework Anda sendiri (misalnya, mengganti `<a>` dengan `NextLink` atau `<CustomCmp>` dengan komponen React).
- **Keamanan Tipe (Type Safety)**: Semua fungsi untuk menyediakan komponen diketik sepenuhnya (fully typed), memastikan Anda menerima props yang benar.

### Perilaku Render Default

Di v7, jika tidak ada provider yang didefinisikan, node Markdown dirender sebagai string mentah, seringkali membutuhkan library eksternal untuk memparsingnya.

**Di v8, Intlayer menyertakan parser Markdown internalnya sendiri.** Secara default, node Markdown sekarang dirender langsung sebagai HTML tanpa memerlukan library eksternal apa pun.

### Utilitas Renderer & Provider Baru

Kami telah memperkenalkan fungsi renderer dan komponen mandiri baru untuk memberi Anda kontrol lebih besar di luar alur standar `useIntlayer`.

- **Markdown**: `MarkdownRenderer`, `useMarkdownRenderer`, `renderMarkdown`. (Catatan: `MarkdownProvider` sudah ada di v7 tetapi sekarang terintegrasi dengan alat-alat baru ini).
- **HTML**: `HTMLRenderer`, `useHTMLRenderer`, `renderHTML`, `HTMLProvider`.

#### Contoh: Alat Rendering Markdown

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

    **1. Menggunakan Komponen:**

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

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

    **2. Menggunakan Hook:**

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

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

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

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

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

    **1. Menggunakan Komponen:**

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

    <template>
      <MarkdownRenderer :forceBlock="true" content="# My Title" />
    </template>
    ```

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

    **1. Menggunakan Komponen:**

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

    <MarkdownRenderer forceBlock={true} value="# My Title" />
    ```

    **2. Menggunakan Hook:**

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

    {@html render("# My Title")}
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    {@html renderMarkdown("# My Title")}
    ```

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

    **1. Menggunakan Layanan (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. Menggunakan Komponen:**

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

    <MarkdownRenderer forceBlock={true}>
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. Menggunakan Hook:**

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

    const render = useMarkdownRenderer();

    return <div>{render("# My Title")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

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

    **1. Menggunakan Komponen:**

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

    <MarkdownRenderer forceBlock={true}>
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. Menggunakan Hook:**

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

    const render = useMarkdownRenderer();

    return <div>{render("# My Title")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

  </Tab>
</Tabs>

#### Contoh: Alat Rendering HTML

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

    **1. Menggunakan Komponen:**

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

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

    **2. Menggunakan Hook:**

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

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

    return <div>{renderHTML("<p>Hello <strong>World</strong></p>")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    const html = renderHTML("<p>Hello World</p>");
    ```

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

    **1. Menggunakan Komponen:**

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

    <template>
      <HTMLRenderer content="<p>Hello World</p>" />
    </template>
    ```

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

    **1. Menggunakan Komponen:**

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

    <HTMLRenderer value="<p>Hello World</p>" />
    ```

    **2. Menggunakan Hook:**

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

    {@html render("<p>Hello World</p>")}
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    {@html renderHTML("<p>Hello World</p>")}
    ```

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

    **1. Penggunaan Langsung:**

    Di Angular, Anda dapat menggunakan binding `[innerHTML]` standar.

    ```html
    <div [innerHTML]="'<p>Hello World</p>'"></div>
    ```

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

    **1. Menggunakan Komponen:**

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

    <HTMLRenderer>
      {"<p>Hello World</p>"}
    </HTMLRenderer>
    ```

    **2. Menggunakan Hook:**

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

    const render = useHTMLRenderer();

    return <div>{render("<p>Hello World</p>")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    return <div>{renderHTML("<p>Hello World</p>")}</div>;
    ```

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

    **1. Menggunakan Komponen:**

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

    <HTMLRenderer>
      {"<p>Hello World</p>"}
    </HTMLRenderer>
    ```

    **2. Menggunakan Hook:**

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

    const render = useHTMLRenderer();

    return <div>{render("<p>Hello World</p>")}</div>;
    ```

    **3. Menggunakan Fungsi Utilitas:**

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

    return <div>{renderHTML("<p>Hello World</p>")}</div>;
    ```

  </Tab>
</Tabs>

Untuk detail lebih lanjut, lihat [Dokumentasi Konten HTML](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/html.md) dan [Dokumentasi Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/markdown.md).

---

## Penulisan Ulang URL Kustom

Intlayer v8 memperkenalkan dukungan untuk **Penulisan Ulang URL Kustom**, yang memungkinkan Anda mendefinisikan jalur spesifik-locale yang berbeda dari struktur standar `/locale/path`. Ini adalah fitur yang kuat untuk meningkatkan SEO lokal dan memberikan pengalaman pengguna yang lebih alami bagi pengguna non-Inggris.

**Peningkatan utama di v8:**

- **Framework Formatters**: `nextjsRewrite`, `svelteKitRewrite`, `reactRouterRewrite`, `vueRouterRewrite`, `solidRouterRewrite`, `tanstackRouterRewrite`, `nuxtRewrite`, dan `viteRewrite` baru untuk menyediakan sintaks pola idiomatik bagi setiap router.
- **Hook `useRewriteURL`**: Hook sisi klien baru yang secara diam-diam memperbaiki bilah alamat ke URL lokal yang "cantik" tanpa memicu navigasi router.
- **Automatic SEO Redirects**: Proxy bawaan sekarang secara otomatis mengarahkan pengguna dari path kanonik yang diketik manual (mis. `/fr/about`) ke versi lokal yang lebih rapi (mis. `/fr/a-propos`).

**Contoh Konfigurasi:**

<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>

Fitur ini didukung langsung (out-of-the-box) di **Next.js** dan **Vite** melalui proxy Intlayer, dan dapat dengan mudah diintegrasikan ke router lain seperti **TanStack Router**, **React Router**, **Vue Router**, **SvelteKit**, dan **Solid Router**.

Untuk informasi lebih lanjut dan panduan integrasi, lihat [Dokumentasi Penulisan Ulang URL Kustom](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/custom_url_rewrites.md).

---

### Nilai Insertion yang Ditingkatkan

Di v8, nilai insertion sekarang dapat **menerima elemen React (atau node Vue)** selain string dan angka. Ini memungkinkan Anda menyisipkan komponen interaktif yang kaya langsung ke dalam template insertion Anda.

Intlayer sekarang secara andal menangani node React dan Preact yang bersarang di dalam insertions, memastikan bahwa struktur UI yang kompleks dipertahankan dan dirender dengan benar.

**Contoh:**

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

export default {
  key: "my-key",
  content: {
    myInsertion: insert("Hi {{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, // angka
          // atau
          name: "John", // string
          // atau
          name: <span>John</span>, // elemen React
        })}
      </div>
    );
    ```

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

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

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

    return (
      <div>
        {myInsertion({
          name: 2, // angka
          // atau
          name: "John", // string
          // atau
          name: <span>John</span>, // elemen React
        })}
      </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,
            // atau
            name: 'John',
            // atau
            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, // angka
          // atau
          name: "John", // string
          // atau
          name: <span>John</span>, // elemen Preact
        })}
      </div>
    );
    ```

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

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

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

    return (
      <div>
        {myInsertion({
          name: 2, // angka
          // atau
          name: "John", // string
          // atau
          name: <span>John</span>, // elemen Solid
        })}
      </div>
    );
    ```

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

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

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

    <div>
      {myInsertion({
        name: 2, // angka
        // atau
        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>

## Validasi Skema Konten

Intlayer v8 memperkenalkan validasi skema untuk dictionaries. Sekarang Anda dapat mendefinisikan skema validasi yang dapat digunakan ulang dalam konfigurasi Anda menggunakan Zod dan menerapkannya pada file konten Anda. Ini memastikan konten Anda selalu sesuai dengan struktur yang diharapkan, sehingga menangkap kesalahan saat proses build.

### 1. Definisikan Skema

Definisikan skema Anda di `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. Terapkan Skema ke Dictionaries

Referensikan kunci skema dalam definisi dictionary Anda:

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

const aboutPageMetaContent = {
  key: "about-page-meta",
  schema: "seo-metadata", // <--
  content: {
    title: "About Our Company - Learn More About Us",
    description: "Discover our company's mission, values, and team.",
  },
} satisfies Dictionary;

export default aboutPageMetaContent;
```

Jika konten tidak cocok dengan skema (mis. judul terlalu pendek), proses build akan menghasilkan error.

---

### Pendeteksian Konten Otomatis yang Ditingkatkan

Di v8, Intlayer secara cerdas mendeteksi sintaks Markdown, tag HTML, dan penyisipan variabel dalam string konten Anda. Ini berarti Anda sering dapat menghilangkan fungsi pembantu seperti `md()`, `html()`, atau `insert()`.

Perilaku ini diaktifkan secara default. Anda sekarang dapat menyetel deteksi ini baik secara global di `intlayer.config.ts` atau per kamus.

#### Kontrol Granular

Anda dapat mengaktifkan atau menonaktifkan jenis transformasi tertentu:

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    // contentAutoTransformation: false (nilai default)
    contentAutoTransformation: {
      markdown: true,
      html: true,
      insertion: false, // Nonaktifkan deteksi insertion otomatis
    },
  },
};
```

**Perilaku v7 (Pembungkusan Manual):**

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

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

**Perilaku v8 (Deteksi otomatis):**

```typescript fileName="src/example.content.ts"
export default {
  key: "my-key",
  contentAutoTransformation: true, // Dapat juga diatur oleh definisi kamus atau secara global di intlayer.config.ts
  content: {
    myMarkdown: "## Hello World", // Otomatis terdeteksi sebagai Markdown
    myHTML: "<p>Hello World</p>", // Otomatis terdeteksi sebagai HTML
    myInsertion: "Hi {{name}}", // Otomatis terdeteksi sebagai Insertion
  },
};
```

Hasil JSON dasar tetap sama, mempertahankan informasi tipe kaya yang diperlukan untuk rendering:

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

---

## Lokalisasi: hook `useIntl` baru

Hook `useIntl()` baru sekarang tersedia di React, Next.js dan Vue. Hook ini menyediakan objek `Intl` yang terikat pada locale yang secara otomatis menggunakan bahasa saat ini untuk memformat angka, tanggal, dan lainnya, tanpa perlu mengoper locale secara manual.

<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: Peningkatan Ekstensi VSCode

Ekstensi Intlayer untuk VSCode menerima pembaruan besar di v8 untuk menyederhanakan alur kerja internasionalisasi Anda:

- **Waktu Mulai**: Peningkatan kinerja saat membuka proyek.
- **Caching**: Lapisan caching yang ditingkatkan untuk validasi dan autocompletion hampir seketika.
- **Deteksi Kunci Tidak Terpakai & Duplikat**: Fitur baru untuk secara otomatis mendeteksi **kunci yang tidak terpakai** dan **kunci duplikat** di seluruh kamus Anda, membantu menjaga konten tetap bersih dan efisien.

---

## Optimisasi Kompiler

Intlayer v8 menyertakan lapisan caching baru untuk compiler Markdown dan HTML. Ini memastikan bahwa string konten yang identik dengan konfigurasi yang sama hanya diparse sekali, secara signifikan mengurangi overhead selama re-render atau saat menggunakan konten yang sama di beberapa tempat.

<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: [
        // Ekstrak konten dari komponen ke dalam kamus
        [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        // Optimalkan impor dengan mengganti useIntlayer menjadi impor kamus langsung
        [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()],
    });
    ```

> Untuk Vue / Svelte Anda perlu menginstal paket compiler yang sesuai:
>
> ```bash
> # Untuk Vue
> npm install @intlayer/vue-compiler
> ```
>
> ```bash
> # Untuk Svelte
> npm install @intlayer/svelte-compiler
> ```

  </Tab>
</Tabs>

---

## Fleksibilitas: Mode Impor Terpadu

Properti boolean `live` telah usang (deprecated) digantikan oleh properti `importMode` yang lebih komprehensif. Ini memungkinkan definisi eksplisit tentang bagaimana dictionary harus dimuat: secara statis, dinamis, atau melalui sinkronisasi langsung.

### Mode

- **`static`** (Default): Dictionary dikemas pada saat build. Terbaik untuk performa.
- **`dynamic`**: Dictionary dimuat saat runtime (misalnya melalui fetch JSON atau suspense).
- **`fetch`**: Dictionary di-fetch dari CMS/Server saat runtime dan disinkronkan.

**Migrasi:**

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

Catatan: Di Intlayer v8, properti `importMode` telah dipindahkan dari konfigurasi `build` ke konfigurasi `dictionary` di `intlayer.config.ts`. Ini memungkinkan Anda mendefinisikan import mode default untuk semua kamus Anda sambil tetap dapat menimpanya pada tingkat per-kamus.

**Contoh Konfigurasi Global:**

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    importMode: "dynamic", // Default untuk semua kamus
  },
  // ...
};
```

**Contoh Kamus:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    importMode: "fetch", // Menimpa konfigurasi global
    content: { ... }
}
```

---

## Kontrol Lokasi Kamus

v8 memperkenalkan properti `location` untuk secara eksplisit mengelola di mana dictionary berada dan bagaimana mereka disinkronkan. Ini sangat berguna untuk alur kerja hibrida yang melibatkan file lokal dan konten CMS remote.

### Opsi

- **`local`**: Dictionary hanya ada secara lokal. Ini tidak akan didorong ke CMS remote.
- **`remote`**: Dictionary dikelola secara remote. Setelah didorong ke CMS, ia akan dipisahkan dari yang lokal. Dictionary remote akan ditarik dari CMS.
- **`local_and_remote`**: Dictionary ada di kedua tempat. Perubahan lokal didorong, dan perubahan remote ditarik (disinkronkan).

**Contoh:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    location: "local", // Biarkan dictionary ini hanya lokal
    content: { ... }
}
```

---

## Pemisahan Konfigurasi Sistem

Intlayer v8 memisahkan konfigurasi sumber konten dari jalur sistem internal dan jalur output. Ini membersihkan properti `content` dan membuatnya jelas pengaturan mana yang dimaksudkan untuk dikelola pengguna versus yang dikelola oleh sistem Intlayer.

Properti berikut telah dipindahkan dari `content` ke properti baru `system` di `intlayer.config.ts`:

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

**Perilaku v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
    dictionariesDir: ".intlayer/dictionary", // Tercampur dengan konfigurasi sumber
  },
};
```

**Perilaku v8:**

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

---

## Pemisahan Direktori Konten dan Kode

Intlayer v8 memisahkan konfigurasi untuk file definisi konten dari konfigurasi untuk transformasi kode. Ini memungkinkan pemantauan dan pemindaian yang lebih tepat, meningkatkan performa build.

Sebelumnya, `contentDir` digunakan untuk kedua pemantauan file `.content.*` dan pemindaian kode untuk pemanggilan `useIntlayer`. Sekarang:

- **`contentDir`**: Secara khusus untuk file deklarasi konten Anda.
- **`codeDir`**: Secara khusus untuk kode aplikasi Anda yang membutuhkan transformasi (mis. pruning, optimasi).

**Migrasi:**

Jika sebelumnya Anda telah mengatur `contentDir`, Intlayer v8 akan menggunakannya sebagai default untuk `codeDir` juga, tetapi akan mencatat peringatan. Anda harus secara eksplisit mendefinisikan `codeDir` dalam konfigurasi Anda.

**Perilaku v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src", "@packages/design-system"], // Digunakan untuk konten dan kode
  },
};
```

**Perilaku v8:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src/content", "@packages/design-system"], // Hanya memantau file src/content/*.content.* di sini dan file @packages/design-system/dist/*.content.*
    codeDir: ["src", "@packages/design-system"], // Hanya memindai untuk transformasi kode di sini
  },
};
```

---

## Framework: Peningkatan Svelte

Konten Markdown dan HTML di Svelte sekarang secara otomatis di-parse menjadi HTML saat distringifikasi. Hal ini membuatnya jauh lebih mudah digunakan dengan sintaks `{@html}` Svelte, karena Anda sekarang dapat langsung meneruskan node konten.

---

## Catatan migrasi dari v7

### Perubahan Konfigurasi

- **Properti `live`**: Properti `live` pada kamus telah dihapus. Gunakan `importMode: 'fetch'` sebagai gantinya.
- **importMode**: Properti `build.importMode` dalam konfigurasi sudah deprecated. Gunakan `dictionary.importMode` sebagai gantinya.
- **`contentDir` dan `codeDir`**: `contentDir` sekarang secara khusus untuk file konten. Properti baru `codeDir` ditambahkan untuk transformasi kode. Jika `codeDir` tidak diatur, Intlayer akan menggunakan `contentDir` sebagai fallback dan menampilkan peringatan di log.
- **Validasi Skema**: Untuk menggunakan fitur `schema` baru, pastikan Anda telah menginstal `zod` di proyek Anda.

---

## Tautan berguna

- [Konfigurasi Referensi](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/configuration.md)
- [Dokumentasi File Konten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/content_file.md)
- [Dokumentasi Konten HTML](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/html.md)
- [Dokumentasi Konten Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/markdown.md)
- [Dokumentasi Penulisan Ulang URL Kustom](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/custom_url_rewrites.md)
