---
createdAt: 2025-09-22
updatedAt: 2026-01-26
title: Новый Intlayer v8. Что нового?
description: Узнайте, что нового в Intlayer v8. Существенные улучшения в опыте разработчика, валидации контента и управлении словарями.
keywords:
  - Intlayer
  - CMS
  - Developer Experience
  - Функции
  - 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"
/>

## Table of contents

<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>Привет, мир</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>Привет, мир</p>");
    ```

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

    **1. Использование компонента:**

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

    <template>
      <HTMLRenderer content="<p>Привет, мир</p>" />
    </template>
    ```

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

    **1. Использование компонента:**

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

    <HTMLRenderer value="<p>Привет, мир</p>" />
    ```

    **2. Использование хука:**

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

    {@html render("<p>Привет, мир</p>")}
    ```

    **3. Использование утилитарной функции:**

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

    {@html renderHTML("<p>Привет, мир</p>")}
    ```

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

    **1. Прямое использование:**

    В Angular вы можете использовать стандартную привязку `[innerHTML]`.

    ```html
    <div [innerHTML]="'<p>Привет, мир</p>'"></div>
    ```

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

    **1. Использование компонента:**

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

    <HTMLRenderer>
      {"<p>Привет, мир</p>"}
    </HTMLRenderer>
    ```

    **2. Использование хука:**

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

    const render = useHTMLRenderer();

    return <div>{render("<p>Привет, мир</p>")}</div>;
    ```

    **3. Использование утилитарной функции:**

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

    return <div>{renderHTML("<p>Привет, мир</p>")}</div>;
    ```

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

    **1. Использование компонента:**

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

    <HTMLRenderer>
      {"<p>Привет, мир</p>"}
    </HTMLRenderer>
    ```

    **2. Использование хука:**

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

    const render = useHTMLRenderer();

    return <div>{render("<p>Привет, мир</p>")}</div>;
    ```

    **3. Использование утилитарной функции:**

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

    return <div>{renderHTML("<p>Привет, мир</p>")}</div>;
    ```

  </Tab>
</Tabs>

Для получения более подробной информации см. [Документацию по HTML-контенту](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/dictionary/html.md) и [Документацию по Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/dictionary/markdown.md).

---

## Пользовательские правила перезаписи URL

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

**Основные улучшения в v8:**

- **Форматтеры для фреймворков**: новые `nextjsRewrite`, `svelteKitRewrite`, `reactRouterRewrite`, `vueRouterRewrite`, `solidRouterRewrite`, `tanstackRouterRewrite`, `nuxtRewrite` и `viteRewrite`, обеспечивающие идиоматичный синтаксис паттернов для каждого роутера.
- **`useRewriteURL` Hook**: Новый 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**.

Для получения дополнительной информации и руководств по интеграции смотрите [Документацию по пользовательским правилам переписывания URL](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/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("Привет, {{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: "О нашей компании, узнайте больше о нас",
    description: "Узнайте о миссии, ценностях и команде нашей компании.",
  },
} satisfies Dictionary;

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("Привет, {{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: "Привет, {{name}}", // Автоматически определяется как Вставка
  },
};
```

Подлежащий 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`

В React, Next.js и Vue теперь доступен новый хук `useIntl()`. Он предоставляет объект `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 для упрощения рабочего процесса интернационализации:

- **Время запуска**: Повышение производительности при открытии проекта.
- **Кэширование**: Улучшенный слой кэширования для почти мгновенной валидации и автодополнения.
- **Обнаружение неиспользуемых и дублированных ключей**: Новые функции для автоматического обнаружения **неиспользуемых ключей** и **дублированных ключей** в ваших словарях, что помогает поддерживать контент чистым и эффективным.

---

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

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`. Это позволяет явно задавать, как словари должны загружаться: статически, динамически или посредством синхронизации в реальном времени.

### Режимы

- **`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`**: предназначен исключительно для кода вашего приложения, который требует трансформации (например, pruning, удаление неиспользуемого кода, оптимизация).

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

Если ранее вы устанавливали `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` property**: Свойство `live` в словарях удалено. Используйте `importMode: 'fetch'` вместо него.
- **importMode**: Свойство `build.importMode` в конфигурации устарело. Используйте `dictionary.importMode` вместо него.
- **`contentDir` и `codeDir`**: `contentDir` теперь специально для файлов контента. Добавлено новое свойство `codeDir` для трансформации кода. Если `codeDir` не установлен, Intlayer будет использовать `contentDir` и выведет предупреждение.
- **Валидация схемы**: Для использования новой функции `schema` убедитесь, что в вашем проекте установлен `zod`.

---

## Полезные ссылки

- [Configuration Reference](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/configuration.md)
- [Content File Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/dictionary/content_file.md)
- [HTML Content Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/dictionary/html.md)
- [Документация по Markdown-контенту](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/dictionary/markdown.md)
- [Документация по пользовательским правилам переписывания URL](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/custom_url_rewrites.md)
