---
createdAt: 2025-09-22
updatedAt: 2026-01-26
title: "Новий Intlayer v8 - Що нового?"
description: "Дізнайтеся, що нового в Intlayer v8. Значні покращення досвіду розробника, валідації контенту та управління словниками."
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 — що нового?

Ласкаво просимо до Intlayer v8! У цьому випуску основна увага приділена покращенню досвіду розробника за допомогою автоматичного виявлення контенту, забезпеченню цілісності даних через валідацію схем і наданню більшого контролю над управлінням словниками.

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

## Зміст

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

---

## Еволюція розширеного вмісту: Markdown та HTML

Intlayer v8 вносить значні покращення в обробку розширеного вмісту, впроваджуючи **HTML-вузли** (яких не було у v7) та уніфікуючи API з **вузлами Markdown** (які були у v7, але були вдосконалені).

### Уніфікований API `.use()`

Ми впровадили метод `.use()` як для вузлів Markdown, так і для HTML. Цей метод дозволяє налаштовувати HTML-теги або компоненти, що використовуються під час відтворення.

- **Заміна компонентів**: Ви можете легко замінити HTML-теги або користувацькі компоненти компонентами вашого фреймворку (наприклад, замінити `<a>` на `NextLink` або `<CustomCmp>` на компонент React).
- **Типобезпека**: Усі функції для надання компонентів є повністю типізованими, що гарантує отримання правильних пропсів.

### Поведінка відтворення за замовчуванням

У v7, якщо провайдер не був визначений, вузли Markdown відтворювалися як сирі рядки, що часто вимагало зовнішніх бібліотек для їх парсингу.

**У v8 Intlayer включає власний внутрішній парсер Markdown.** За замовчуванням вузли Markdown тепер відтворюються безпосередньо як HTML без потреби в будь-яких зовнішніх бібліотеках.

### Нові утиліти Renderer та Provider

Ми впровадили нові автономні функції та компоненти рендерера, щоб дати вам більше контролю поза стандартним потоком `useIntlayer`.

- **Markdown**: `MarkdownRenderer`, `useMarkdownRenderer`, `renderMarkdown`. (Примітка: `MarkdownProvider` існував у v7, але тепер інтегрується з цими новими інструментами).
- **HTML**: `HTMLRenderer`, `useHTMLRenderer`, `renderHTML`, `HTMLProvider`.

#### Приклади: інструменти відтворення Markdown

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

    **1. Використання компонента:**

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

    <MarkdownRenderer
      forceBlock={true}
      components={{
        h1: ({ children }) => <h1 className="text-2xl">{children}</h1>
      }}
    >
      {"# Мій заголовок"}
    </MarkdownRenderer>
    ```

    **2. Використання хука:**

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

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

    return <div>{renderMarkdown("# Мій заголовок")}</div>;
    ```

    **3. Використання утиліти:**

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

    const html = renderMarkdown("# Мій заголовок", {
      forceBlock: true
    });
    ```

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

    **1. Використання компонента:**

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

    <template>
      <MarkdownRenderer :forceBlock="true" content="# Мій заголовок" />
    </template>
    ```

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

    **1. Використання компонента:**

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

    <MarkdownRenderer forceBlock={true} value="# Мій заголовок" />
    ```

    **2. Використання хука:**

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

    {@html render("# Мій заголовок")}
    ```

    **3. Використання утиліти:**

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

    {@html renderMarkdown("# Мій заголовок")}
    ```

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

    **1. Використання сервісу:**

    ```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. Використання компонента:**

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

    <MarkdownRenderer forceBlock={true}>
      {"# Мій заголовок"}
    </MarkdownRenderer>
    ```

    **2. Використання хука:**

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

    const render = useMarkdownRenderer();

    return <div>{render("# Мій заголовок")}</div>;
    ```

    **3. Використання утиліти:**

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

    return <div>{renderMarkdown("# Мій заголовок")}</div>;
    ```

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

    **1. Використання компонента:**

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

    <MarkdownRenderer forceBlock={true}>
      {"# Мій заголовок"}
    </MarkdownRenderer>
    ```

    **2. Використання хука:**

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

    const render = useMarkdownRenderer();

    return <div>{render("# Мій заголовок")}</div>;
    ```

    **3. Використання утиліти:**

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

    return <div>{renderMarkdown("# Мій заголовок")}</div>;
    ```

  </Tab>
</Tabs>

#### Приклади: інструменти відтворення HTML

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

    **1. Використання компонента:**

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

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

    **2. Використання хука:**

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

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

    return <div>{renderHTML("<p>Привіт <strong>Світ</strong></p>")}</div>;
    ```

    **3. Використання утиліти:**

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

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

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

    **1. Використання компонента:**

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

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

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

    **1. Використання компонента:**

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

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

    **2. Використання хука:**

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

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

    **3. Використання утиліти:**

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

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

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

    **1. Пряме використання:**

    В Angular ви можете використовувати стандартне зв'язування `[innerHTML]`.

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

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

    **1. Використання компонента:**

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

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

    **2. Використання хука:**

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

    const render = useHTMLRenderer();

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

    **3. Використання утиліти:**

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

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

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

    **1. Використання компонента:**

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

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

    **2. Використання хука:**

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

    const render = useHTMLRenderer();

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

    **3. Використання утиліти:**

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

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

  </Tab>
</Tabs>

Для отримання додаткової інформації див. [документацію з HTML-контенту](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dictionary/html.md) та [документацію з Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dictionary/markdown.md).

---

## Користувацькі переписування URL

Intlayer v8 додає підтримку **користувацьких переписувань URL**, що дозволяє визначати локалізовані шляхи, які відрізняються від стандартної структури `/locale/path`. Це потужна можливість для покращення локального SEO та забезпечення більш природного досвіду користувача для тих, хто не говорить англійською.

**Ключові покращення в v8:**

- **Форматери для фреймворків**: Нові `nextjsRewrite`, `svelteKitRewrite`, `reactRouterRewrite`, `vueRouterRewrite`, `solidRouterRewrite`, `tanstackRouterRewrite`, `nuxtRewrite` та `viteRewrite`, які надають ідіоматичний синтаксис шаблонів для кожного роутера.
- **`useRewriteURL` Hook**: Новий клієнтський хук, який безшумно виправляє адресний рядок до «гарної» локалізованої URL-адреси, не спричиняючи навігацій маршрутизатора.
- **Automatic SEO Redirects**: Вбудовані проксі тепер автоматично перенаправляють користувачів з вручну введених канонічних шляхів (наприклад, `/fr/about`) до їх більш привабливих локалізованих версій (наприклад, `/fr/a-propos`).

**Приклад конфігурації:**

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

Ця функція підтримується «з коробки» в **Next.js** та **Vite** через проксі Intlayer, і її можна легко інтегрувати в інші роутери, такі як **TanStack Router**, **React Router**, **Vue Router**, **SvelteKit** та **Solid Router**.

Для отримання додаткової інформації та посібників з інтеграції див. [документацію Custom URL Rewrites](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/custom_url_rewrites.md).

---

### Розширені значення вставок

У версії v8 значення вставок тепер можуть **приймати React-елементи (або Vue-вузли)** на додаток до рядків і чисел. Це дозволяє вставляти багаті, інтерактивні компоненти безпосередньо у ваші шаблони вставок.

Intlayer тепер надійно обробляє вкладені вузли React і Preact всередині вставок, гарантуючи, що складні UI-структури зберігаються та відображаються правильно.

**Приклад:**

```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, // число
          // або
          name: "John", // рядок
          // або
          name: <span>John</span>, // React-елемент
        })}
      </div>
    );
    ```

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

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

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

    return (
      <div>
        {myInsertion({
          name: 2, // число
          // або
          name: "John", // рядок
          // або
          name: <span>John</span>, // 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,
            // або
            name: 'John',
            // або
            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, // число
          // або
          name: "John", // рядок
          // або
          name: <span>John</span>, // елемент Preact
        })}
      </div>
    );
    ```

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

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

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

    return (
      <div>
        {myInsertion({
          name: 2, // число
          // або
          name: "John", // рядок
          // або
          name: <span>John</span>, // елемент 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, // число
        // або
        name: "John", // рядок
      })}
    </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>

## Валідація схем контенту

Intlayer v8 впроваджує валідацію схем для словників. Тепер ви можете визначати повторно використовувані схеми валідації у вашій конфігурації за допомогою Zod і застосовувати їх до ваших файлів контенту. Це гарантує, що ваш контент завжди відповідає очікуваній структурі, виявляючи помилки під час збірки.

### 1. Визначте схеми

Визначте свої схеми в `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. Застосуйте схеми до словників

Посилайтеся на ключ схеми у визначенні вашого словника:

```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<"seo-metadata">;

export default aboutPageMetaContent;
```

Якщо контент не відповідає схемі (наприклад, заголовок занадто короткий), процес збірки видасть помилку.

---

### Покращене автоматичне виявлення контенту

У v8 Intlayer інтелектуально виявляє синтаксис Markdown, HTML-теги та вставки змінних у рядках контенту. Це означає, що ви часто можете опустити допоміжні функції, такі як `md()`, `html()` або `insert()`.

Ця поведінка увімкнена за замовчуванням. Тепер ви можете тонко налаштувати це виявлення або глобально в `intlayer.config.ts`, або для кожного словника окремо.

#### Гранулярний контроль

Ви можете ввімкнути або вимкнути певні типи трансформацій:

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    // contentAutoTransformation: false (за замовчуванням)
    contentAutoTransformation: {
      markdown: true,
      html: true,
      insertion: false, // Вимкнути автоматичне виявлення вставок
    },
  },
};
```

**Поведінка v7 (ручне обгортання):**

```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}}"),
  },
};
```

**Поведінка v8 (автоматичне виявлення):**

```typescript fileName="src/example.content.ts"
export default {
  key: "my-key",
  contentAutoTransformation: true, // Також може бути встановлено у визначенні словника або глобально в intlayer.config.ts
  content: {
    myMarkdown: "## Hello World", // Автоматично визначається як Markdown
    myHTML: "<p>Hello World</p>", // Автоматично визначається як HTML
    myInsertion: "Hi {{name}}", // Автоматично визначається як Insertion
  },
};
```

Підлягаючий JSON-результат залишається незмінним, зберігаючи багату інформацію про типи, необхідну для відтворення:

```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}}"
    }
  }
}
```

---

## Локалізація: новий хук `useIntl`

Новий хук `useIntl()` тепер доступний у React, Next.js та Vue. Він надає прив'язаний до локалі об'єкт `Intl`, який автоматично використовує поточну мову для форматування чисел, дат та іншого, без необхідності вручну передавати локаль.

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

---

## Інструменти: Покращення розширення VSCode

Розширення Intlayer для VSCode отримало значні оновлення у v8 для оптимізації вашого робочого процесу інтернаціоналізації:

- **Starting Time**: Покращення продуктивності під час відкриття проєкту.
- **Caching**: Покращений шар кешування для майже миттєвої валідації та автозаповнення.
- **Unused Keys & Duplicated Keys Detection**: Нові функції для автоматичного виявлення **невикористовуваних ключів** та **повторюваних ключів** у ваших словниках, що допомагає підтримувати ваш контент чистим та ефективним.

---

## Оптимізації компілятора

Intlayer v8 включає новий шар кешування для компілятора Markdown та HTML. Це гарантує, що ідентичні рядки контенту з однаковою конфігурацією парсяться лише один раз, що значно зменшує витрати під час повторних відтворень або при використанні одного й того ж контенту в декількох місцях.

<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: [
        // Витягувати контент із компонентів у словники
        [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        // Оптимізувати імпорти, замінюючи useIntlayer прямими імпортами словників
        [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()],
    });
    ```

> Для Vue / Svelte вам потрібно буде встановити відповідний пакет компілятора:
>
> ```bash
> # Для Vue
> npm install @intlayer/vue-compiler
> ```
>
> ```bash
> # Для Svelte
> npm install @intlayer/svelte-compiler
> ```

  </Tab>
</Tabs>

---

## Гнучкість: Уніфікований режим імпорту

Властивість булевого типу `live` була застаріла на користь більш всеосяжної властивості `importMode`. Це дозволяє явно визначати, як словники мають завантажуватися: статично, динамічно або через live-синхронізацію.

### Режими

- **`static`** (Типово): Словник пакується під час збірки. Найкраще для продуктивності.
- **`dynamic`**: Словник завантажується під час виконання (наприклад, через завантаження JSON або suspense).
- **`fetch`**: Словник отримується з CMS/сервера під час виконання і синхронізується.

Міграція:

| Конфігурація v7 | Конфігурація v8                        |
| :-------------- | :------------------------------------- |
| `live: true`    | `importMode: 'fetch'`                  |
| `live: false`   | `importMode: 'static'` (або 'dynamic') |

Примітка: У Intlayer v8 властивість `importMode` було переміщено з конфігурації `build` до конфігурації `dictionary` у `intlayer.config.ts`. Це дозволяє визначити типовий режим імпорту для всіх ваших словників, при цьому зберігаючи можливість перевизначити його для кожного словника окремо.

**Приклад глобальної конфігурації:**

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    importMode: "dynamic", // Глобальне значення за замовчуванням
  },
  // ...
};
```

**Приклад словника:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    importMode: "fetch", // Перевизначає глобальну конфігурацію
    content: { ... }
}
```

---

## Керування розташуванням словників

v8 впроваджує властивість `location` для явного керування тим, де живуть словники та як вони синхронізуються. Це особливо корисно для гібридних робочих процесів, що включають як локальні файли, так і віддалений контент CMS.

### Параметри

- **`local`**: Словник існує лише локально. Він не буде надісланий до віддаленої CMS.
- **`remote`**: Словник керується віддалено. Після надсилання до CMS він буде від'єднаний від локального. Віддалений словник буде завантажений із CMS.
- **`local_and_remote`**: Словник існує в обох місцях. Локальні зміни надсилаються, а віддалені зміни завантажуються (синхронізуються).

**Приклад:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    location: "local", // Тримати цей словник лише локально
    content: { ... }
}
```

---

## Розділення конфігурації системи

Intlayer v8 розділяє конфігурацію джерел контенту від внутрішніх системних та вихідних шляхів. Це очищує властивість `content` і робить зрозумілим, які налаштування призначені для керування користувачем, а які керуються системою Intlayer.

Наступні властивості були переміщені з `content` до нової властивості `system` в `intlayer.config.ts`:

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

**Поведінка v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
    dictionariesDir: ".intlayer/dictionary", // Змішано з конфігурацією джерела
  },
};
```

**Поведінка v8:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
  },
  system: {
    dictionariesDir: ".intlayer/dictionary", // Чітко розділено
  },
};
```

---

## Відокремлення директорій контенту та коду

Intlayer v8 розділяє конфігурацію для файлів визначення контенту та конфігурацію для трансформації коду. Це дозволяє більш точно налаштувати спостереження та сканування, покращуючи продуктивність збірки.

Раніше `contentDir` використовувався як для спостереження за файлами `.content.*`, так і для сканування коду на виклики `useIntlayer`. Тепер:

- **`contentDir`**: Спеціально для ваших файлів оголошення контенту.
- **`codeDir`**: Спеціально для коду вашого застосунку, який потребує трансформації (наприклад, обрізка, оптимізація).

**Міграція:**

Якщо у вас раніше було встановлено `contentDir`, Intlayer v8 використовуватиме його як типове значення для `codeDir` також, але виведе попередження. Вам слід явно визначити `codeDir` у вашій конфігурації.

**Поведінка v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src", "@packages/design-system"], // Використовувався як для контенту, так і для коду
  },
};
```

**Поведінка v8:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src/content", "@packages/design-system"], // Спостерігати тільки за файлами src/content/*.content.* та @packages/design-system/dist/*.content.* тут
    codeDir: ["src", "@packages/design-system"], // Сканувати тільки для трансформації коду та файлів @packages/design-system/src/*.content.* тут
  },
};
```

---

## Фреймворк: Покращення для Svelte

Контент Markdown та HTML у Svelte тепер автоматично парситься в HTML при перетворенні на рядок. Це значно полегшує використання синтаксису Svelte `{@html}`, оскільки тепер ви можете просто передати вузол контенту безпосередньо.

---

## Примітки до міграції з v7

### Зміни в конфігурації

- **Властивість `live`**: Властивість `live` у словниках видалена. Використовуйте `importMode: 'fetch'` замість неї.
- **importMode**: Властивість `build.importMode` у конфігурації застаріла. Використовуйте `dictionary.importMode` замість неї.
- **`contentDir` та `codeDir`**: `contentDir` тепер призначений саме для файлів контенту. Додано нову властивість `codeDir` для трансформації коду. Якщо `codeDir` не встановлено, Intlayer повернеться до `contentDir` та виведе попередження.
- **Валідація схеми**: Щоб використовувати нову функцію `schema`, переконайтеся, що у вашому проєкті встановлено `zod`.

---

## Корисні посилання

- [Довідник з конфігурації](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/configuration.md)
- [Документація про файли контенту](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dictionary/content_file.md)
- [Документація контенту HTML](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dictionary/html.md)
- [Документація контенту Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dictionary/markdown.md)
- [Документація про власні переписування URL](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/custom_url_rewrites.md)
