---
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 には存在しませんでした）の導入と、**Markdown ノード**（v7 から存在していましたが、強化されました）との API 統合が行われました。

### 統合された `.use()` API

Markdown と HTML ノードの両方に `.use()` メソッドが導入されました。このメソッドを使用すると、レンダリング時に使用される HTML タグやコンポーネントをカスタマイズできます。

- **コンポーネントの置換**: HTML タグやカスタムコンポーネントを、自身のフレームワークコンポーネント（例: `<a>` を `NextLink` に、`<CustomCmp>` を React コンポーネントに）で簡単に置き換えられます。
- **型安全性**: コンポーネントを提供するためのすべての関数は完全に型付けされており、正しいプロップを受け取ることが保証されます。

### デフォルトのレンダリング動作

v7 では、プロバイダーが定義されていない場合、Markdown ノードは生の文字列としてレンダリングされ、解析のために外部ライブラリが必要になることがよくありました。

**v8 では、Intlayer に独自の内部 Markdown パーサーが含まれています。** デフォルトで、Markdown ノードは外部ライブラリを必要とせずに直接 HTML としてレンダリングされるようになりました。

### 新しいレンダラーとプロバイダーのユーティリティ

標準の `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>
      }}
    >
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. フックの使用:**

    ```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. ユーティリティ関数の使用:**

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

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

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

    **1. コンポーネントの使用:**

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

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

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

    **1. コンポーネントの使用:**

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

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

    **2. フックの使用:**

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

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

    **3. ユーティリティ関数の使用:**

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

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

  </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}>
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. フックの使用:**

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

    const render = useMarkdownRenderer();

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

    **3. ユーティリティ関数の使用:**

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

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

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

    **1. コンポーネントの使用:**

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

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

    **2. フックの使用:**

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

    const render = useMarkdownRenderer();

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

    **3. ユーティリティ関数の使用:**

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

    return <div>{renderMarkdown("# My Title")}</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>Hello <strong>World</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/ja/dictionary/html.md) と [Markdown ドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/dictionary/markdown.md) を参照してください。

---

## カスタム URL リライト

Intlayer v8 は **カスタム URL リライト** を導入し、標準の `/locale/path` 構造と異なるロケール固有のパスを定義できるようになります。これはローカルSEOの改善や、英語以外のユーザーにとってより自然なユーザーエクスペリエンスを提供するための強力な機能です。

**v8 の主な強化点:**

- **Framework Formatters**: `nextjsRewrite`、`svelteKitRewrite`、`reactRouterRewrite`、`vueRouterRewrite`、`solidRouterRewrite`、`tanstackRouterRewrite`、`nuxtRewrite`、および `viteRewrite` を新たに追加し、各ルーターに対して慣用的なパターン構文を提供します。
- **`useRewriteURL` フック**: クライアントサイドの新しいフックで、ルーターのナビゲーションを発生させることなく、アドレスバーをより見栄えの良いローカライズされた URL に静かに修正します。
- **自動 SEO リダイレクト**: 組み込みのプロキシが、手で入力されたカノニカルパス（例: `/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>

この機能は Intlayer のプロキシを通じて **Next.js** と **Vite** でアウト・オブ・ザ・ボックスでサポートされており、**TanStack Router**、**React Router**、**Vue Router**、**SvelteKit**、**Solid Router** などの他のルーターにも簡単に統合できます。

詳細と統合ガイドについては、[カスタム URL リライトのドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/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;
```

コンテンツがスキーマと一致しない場合（例: title が短すぎる）、ビルドプロセスでエラーが発生します。

---

### 強化された自動コンテンツ検出

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` フック

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` プロパティは `intlayer.config.ts` の `build` 設定から `dictionary` 設定へ移動しました。これにより、すべての辞書に対するデフォルトのインポートモードを定義しつつ、各辞書ごとに上書きできるようになります。

**グローバル設定の例:**

```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` から `intlayer.config.ts` の新しい `system` プロパティに移動されました:

- `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 は、コンテンツ定義ファイルの設定とコード変換の設定を分離します。これにより、監視とスキャンの対象をより正確に指定でき、ビルドパフォーマンスが向上します。

以前は、`.content.*` ファイルの監視と `useIntlayer` 呼び出しのためのコードスキャンの両方に `contentDir` が使われていました。現在は以下のように分かれています:

- **`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"], // コード変換のためにのみスキャン
  },
};
```

---

## フレームワーク: Svelte の改善

Svelte 内の Markdown および HTML コンテンツは、文字列化（stringified）される際に自動的に 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/ja/configuration.md)
- [コンテンツファイルのドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/dictionary/content_file.md)
- [HTMLコンテンツのドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/dictionary/html.md)
- [Markdown コンテンツのドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/dictionary/markdown.md)
- [カスタム URL 書き換えのドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/custom_url_rewrites.md)
