著者:
    作成:2025-11-20最終更新:2026-06-23

    Intlayerを使ってSvelteKitのウェブサイトを翻訳する | 国際化(i18n)

    ide.intlayer.org
    intlayer-sveltekit-template.vercel.app

    目次

    代替手段ではなく Interlayer を使用する理由

    「svelte-i18n」や「i18next」などの主要なソリューションと比較して、Intlayer は次のような統合された最適化を備えたソリューションです。

    SvelteKit を完全にカバー

    Intlayer は、多言語ルーティングSSR サポート、およびスケーリング国際化 (i18n) に必要なすべての機能を提供することにより、SvelteKit と完全に連携するように最適化されています。

    バンドルサイズ

    大量の JSON ファイルをページにロードするのではなく、必要なコンテンツのみをロードします。 Intlayer は、バンドルとページのサイズを最大 50% 削減するのに役立ちます。

    保守性

    アプリケーションのコンテンツのスコープを設定すると、大規模なアプリケーションの メンテナンスが容易になります。コンテンツ コードベース全体を確認するという精神的な負担を負うことなく、単一の機能フォルダーを複製または削除できます。さらに、Intlayer は完全に型指定されており、コンテンツの正確性を保証します。

    AI エージェント

    コンテンツを同じ場所に配置すると、大規模言語モデル (LLM) によって 必要なコンテキストが削減されます。 Intlayer には、翻訳の欠落をテストする CLILSPMCP などのツール スイートも付属しています。および agent skills により、AI エージェントの開発者エクスペリエンス (DX) がさらにスムーズになります。

    オートメーション

    AI プロバイダーの費用で、選択した LLM を使用して CI/CD パイプラインで自動化を変換します。 Intlayer は、コンテンツ抽出を自動化する コンパイラー と、バックグラウンドでの翻訳を支援する Web プラットフォーム も提供します。

    パフォーマンス

    大量の JSON ファイルをコンポーネントに接続すると、パフォーマンスと反応性の問題が発生する可能性があります。 Intlayer は、ビルド時のコンテンツの読み込みを最適化します。

    非開発によるスケーリング

    Intlayer は単なる i18n ソリューションではなく、自己ホスト型 ビジュアル エディター完全な CMS を提供します。 リアルタイムで多言語コンテンツを管理できるようになり、翻訳者、コピーライター、その他のチーム メンバーとのコラボレーションがシームレスになります。コンテンツはローカルおよび/またはリモートに保存できます。

    </AccordionGroup>


    SvelteKitアプリケーションでIntlayerをセットアップするステップバイステップガイド

    Application Template を GitHub で参照してください。

    まずは新しいSvelteKitプロジェクトを作成しましょう。以下は最終的に作成する構成です:

    bash
    .
    ├── intlayer.config.ts
    ├── package.json
    ├── src
       ├── app.d.ts
    │   ├── app.html
    │   ├── hooks.server.ts
    │   ├── lib
    │   │   ├── getLocale.ts
    │   │   ├── LocaleSwitcher.svelte
    │   │   └── LocalizedLink.svelte
    │   ├── params
    │   │   └── locale.ts
    │   └── routes
    │       ├── [[locale=locale]]
    │       │   ├── +layout.svelte
    │       │   ├── +layout.ts
    │       │   ├── +page.svelte
    │       │   ├── +page.ts
    │       │   ├── about
    │       │   │   ├── +page.svelte
    │       │   │   ├── +page.ts
    │       │   │   └── page.content.ts
    │       │   ├── Counter.content.ts
    │       │   ├── Counter.svelte
    │       │   ├── Header.content.ts
    │       │   ├── Header.svelte
    │       │   ├── home.content.ts
    │       │   └── layout.content.ts
    │       ├── +layout.svelte
    │       └── layout.css
    ├── static
    │   ├── favicon.svg
    │   └── robots.txt
    ├── svelte.config.js
    ├── tsconfig.json
    └── vite.config.ts
    
    1. 依存関係をインストール

      npm を使用して必要なパッケージをインストールしてください:

      bash
      npx intlayer init --interactive
      
      --interactive フラグはオプションです。AI エージェントの場合は intlayer-cli init を使用してください。
      このコマンドはあなたの環境を検出し、必要なパッケージをインストールします。例えば:
      bash
      npm install intlayer svelte-intlayer
      npm install vite-intlayer --save-dev
      
      • intlayer: コアとなるi18nパッケージ。
      • svelte-intlayer: Svelte/SvelteKit向けのコンテキストプロバイダーとストアを提供します。
      • vite-intlayer: コンテンツ宣言をビルドプロセスに統合するViteプラグイン。
    2. プロジェクトの設定

      プロジェクトのルートに設定ファイルを作成します:

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
      };
      
      export default config;
      
    3. Intlayer を Vite 設定に統合する

      vite.config.ts を更新して、Intlayer プラグインを含めます。このプラグインは、コンテンツファイルのトランスパイルを処理します。

      vite.config.ts
      import { sveltekit } from "@sveltejs/kit/vite";
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [intlayer(), sveltekit()], // 順序が重要です。Intlayerはsvelteより前に配置する必要があります
      });
      
    4. コンテンツを宣言する

      src フォルダ内の任意の場所(例:src/lib/content またはコンポーネントの隣)にコンテンツ宣言ファイルを作成します。これらのファイルは、各ロケールに対して t() 関数を使用してアプリケーション用の翻訳可能なコンテンツを定義します。

    5. Intlayerをコンポーネントで利用する

      これで、任意の Svelte コンポーネントで useIntlayer 関数を使用できます。これはロケールが変更されると自動的に更新されるリアクティブストアを返します。この関数は現在のロケール (SSR とクライアント側のナビゲーション の両方) を自動的に尊重します。

      注記: useIntlayer は Svelte store を返すため、リアクティブ値にアクセスするには $ プレフィックスを使用する必要があります (例: $content.title)。
      src/lib/components/Component.svelte
      <script lang="ts">
        import { useIntlayer } from "svelte-intlayer";
      
        // "hero-section" は Step 4 で定義されたキーに対応しています
        const content = useIntlayer("hero-section");
      </script>
      
      <!-- シンプルなコンテンツとしてレンダリング  -->
      <h1>{$content.title}</h1>
      <!-- エディタを使用して編集可能なコンテンツをレンダリング -->
      <h1>{@const Title = $content.title}<Title /></h1>
      <!-- コンテンツを文字列としてレンダリング -->
      <div aria-label={$content.title.value}></div>
      <div aria-label={$content.title.toString()}></div>
      <div aria-label={String($content.title)}></div>
      
    6. ルーティングの設定

      オプション

      以下の手順は、SvelteKit でロケールベースのルーティングをセットアップする方法を示しています。これにより、URL にロケールプレフィックス (例: /en/about, /fr/about) を含めることができ、SEO とユーザー体験が向上します。

      bash
      .
      └─── src
          ├── app.d.ts                  # ロケール型を定義
          ├── hooks.server.ts           # ロケールルーティングを管理
          ├── lib
         └── getLocale.ts          # ヘッダー、クッキーからロケールを確認
          ├── params
         └── locale.ts             # ロケールパラメータを定義
          └── routes
              ├── [[locale=locale]]     # ロケールを設定するためにルートグループでラップ
         ├── +layout.svelte    # ルートのローカルレイアウト
         ├── +layout.ts
         ├── +page.svelte
         ├── +page.ts
         └── about
             ├── +page.svelte
             └── +page.ts
              └── +layout.svelte         # フォントとグローバルスタイルのルートレイアウト
      
    7. サーバーサイドのロケール検出を処理する

      SvelteKit では、SSR 時に正しいコンテンツをレンダリングするため、サーバーはユーザーのロケールを認識する必要があります。hooks.server.ts を使用して、URL またはクッキーからロケールを検出します。

      src/hooks.server.tsを作成または変更します:

      src/hooks.server.ts
      import type { Handle } from "@sveltejs/kit";
      import { getLocalizedUrl } from "intlayer";
      import { getLocale } from "$lib/getLocale";
      
      export const handle: Handle = async ({ event, resolve }) => {
        const detectedLocale = getLocale(event);
      
        // 現在のパスがすでにロケール(例:/fr、/en)で始まっているかチェック
        const pathname = event.url.pathname;
        const targetPathname = getLocalizedUrl(pathname, detectedLocale);
      
        // URLにロケールが存在しない場合(例:ユーザーが「/」にアクセス)、リダイレクト
        if (targetPathname !== pathname) {
          return new Response(undefined, {
            headers: { Location: targetPathname },
            status: 307, // 一時的なリダイレクト
          });
        }
      
        return resolve(event, {
          transformPageChunk: ({ html }) => html.replace("%lang%", detectedLocale),
        });
      };
      

      次に、リクエストイベントからユーザーのロケールを取得するヘルパーを作成します:

      src/lib/getLocale.ts
      import {
        configuration,
        getLocaleFromStorage,
        localeDetector,
        type Locale,
      } from "intlayer";
      import type { RequestEvent } from "@sveltejs/kit";
      
      /**
       * リクエストイベントからユーザーのロケールを取得します。
       * この関数は `src/hooks.server.ts` の `handle` フック内で使用されます。
       *
       * まず Intlayer ストレージ(cookies またはカスタムヘッダー)からロケールを取得しようとします。
       * ロケールが見つからない場合は、ブラウザの "Accept-Language" ネゴシエーションにフォールバックします。
       *
       * @param event - SvelteKit からのリクエストイベント
       * @returns ユーザーのロケール
       */
      export const getLocale = (event: RequestEvent): Locale => {
        const defaultLocale = configuration?.internationalization?.defaultLocale;
      
        // Intlayer ストレージ(Cookies またはヘッダー)からロケールを取得してみます
        const storedLocale = getLocaleFromStorage({
          // SvelteKit cookies アクセス
          getCookie: (name: string) => event.cookies.get(name) ?? null,
          // SvelteKit headers アクセス
          getHeader: (name: string) => event.request.headers.get(name) ?? null,
        });
      
        if (storedLocale) {
          return storedLocale;
        }
      
        // ブラウザの "Accept-Language" ネゴシエーションにフォールバック
        const negotiatorHeaders: Record<string, string> = {};
      
        // SvelteKit Headers オブジェクトをプレーンな Record<string, string> に変換
        event.request.headers.forEach((value, key) => {
          negotiatorHeaders[key] = value;
        });
      
        // `Accept-Language` ヘッダーからロケールをチェック
        const userFallbackLocale = localeDetector(negotiatorHeaders);
      
        if (userFallbackLocale) {
          return userFallbackLocale;
        }
      
        // マッチが見つからない場合はデフォルトロケールを返す
        return defaultLocale;
      };
      
      getLocaleFromStorage はあなたの設定に応じて、ヘッダーまたはクッキーからロケールをチェックします。詳細は Configuration を参照してください。
      localeDetector 関数は Accept-Language ヘッダーを処理し、最適なマッチを返します。

      ロケールが設定されていない場合、404エラーを返したいです。これを簡単にするために、ロケールが有効かどうかをチェックする match 関数を作成できます:

      /src/params/locale.ts
      import { defaultLocale, locales, type Locale } from "intlayer";
      export const match = (param: Locale = defaultLocale): boolean =>
        locales.includes(param);
      

      Note: src/app.d.ts にロケール定義が含まれていることを確認してください:

      typescript
      declare global {
        namespace App {
          interface Locals {
            locale: import("intlayer").Locale;
          }
        }
      }
      

      +layout.svelte ファイルの場合、i18n に関連しない静的コンテンツのみを保持するために、すべてを削除できます:

      src/+layout.svelte
      <script lang="ts">
           import './layout.css';
      
          let { children } = $props();
      </script>
      
      <div class="app">
          {@render children()}
      </div>
      
      <style>
          .app {
          /*  */
          }
      </style>
      

      次に、[[locale=locale]] グループの下に新しいページとレイアウトを作成します:

      src/routes/[[locale=locale]]/+layout.ts
      import type { Load } from "@sveltejs/kit";
      import { defaultLocale, type Locale } from "intlayer";
      
      export const prerender = true;
      
      // ジェネリック Load 型を使用
      export const load: Load = ({ params }) => {
        const locale: Locale = (params.locale as Locale) ?? defaultLocale;
      
        return {
          locale,
        };
      };
      
      src/routes/[[locale=locale]]/+layout.svelte
      <script lang="ts">
          import type { Snippet } from 'svelte';
          import { useIntlayer, setupIntlayer } from "svelte-intlayer";
          import Header from './Header.svelte';
          import type { LayoutData } from './$types';
      
          let { children, data }: { children: Snippet, data: LayoutData } = $props();
      
          // ルートからのロケールでIntlayerを初期化
        $effect(() => {
            setupIntlayer(data.locale);
        });
          // レイアウトコンテンツ辞書を使用
          const layoutContent = useIntlayer('layout');
      </script>
      
      <Header />
      
      <main>
          {@render children()}
      </main>
      
      <footer>
          <p>
              {$layoutContent.footer.prefix.value}{' '}
              <a href="https://svelte.dev/docs/kit">{$layoutContent.footer.linkLabel.value}</a>{' '}
              {$layoutContent.footer.suffix.value}
          </p>
      </footer>
      
      <style>
        /*  */
      </style>
      
      src/routes/[[locale=locale]]/+page.ts
      export const prerender = true;
      
      src/routes/[[locale=locale]]/+page.svelte
      <script lang="ts">
          import { useIntlayer } from "svelte-intlayer";
      
          // ホームコンテンツ辞書を使用
          const homeContent = useIntlayer('home');
      </script>
      
      <svelte:head>
          <title>{$homeContent.title.value}</title>
      </svelte:head>
      
      <section>
          <h1>
              {$homeContent.title}
          </h1>
      </section>
      
      <style>
        /*  */
      </style>
      
    8. 国際化されたリンク

      オプション

      SEO のため、ルートをロケール接頭辞を付けることが推奨されます (例: /en/about, /fr/about)。このコンポーネントは現在のロケールで自動的にリンクに接頭辞を付けます。

      src/lib/components/LocalizedLink.svelte
      <script lang="ts">
        import { getLocalizedUrl } from "intlayer";
        import { useLocale } from "svelte-intlayer";
      
        let { href = "" } = $props();
        const { locale } = useLocale();
      
        // 現在のロケールでURLにプレフィックスを付けるヘルパー
        $: localizedHref = getLocalizedUrl(href, $locale);
      </script>
      
      <a href={localizedHref}>
        <slot />
      </a>
      

      SvelteKit の goto を使用する場合、同じロジックを getLocalizedUrl と共に使用してローカライズされた URL にナビゲートできます:

      typescript
      import { goto } from "$app/navigation";
      import { getLocalizedUrl } from "intlayer";
      import { useLocale } from "svelte-intlayer";
      
      const { locale } = useLocale();
      const localizedPath = getLocalizedUrl("/about", $locale);
      goto(localizedPath); // ロケールに応じて /en/about または /fr/about にナビゲートします
      
    9. コンポーネントのコンテンツを抽出する

      オプション

      既存のコードベースがある場合、数千のファイルを変換するのは時間がかかることがあります。

      src/lib/components/LanguageSwitcher.svelte
      <script lang="ts">
        import { getLocalizedUrl, getLocaleName } from 'intlayer';
        import { useLocale } from "svelte-intlayer";
        import { page } from '$app/stores';
        import { goto } from '$app/navigation';
      
        const { locale, setLocale, availableLocales } = useLocale({
          onLocaleChange: (newLocale) => {
            const localizedPath = getLocalizedUrl($page.url.pathname, newLocale);
            goto(localizedPath);
          },
        });
      </script>
      
      <ul class="locale-list">
        {#each availableLocales as localeEl}
          <li>
            <a
              href={getLocalizedUrl($page.url.pathname, localeEl)}
              onclick={(e) => {
                e.preventDefault();
                setLocale(localeEl); // ストアにロケールを設定し、onLocaleChangeをトリガーします
              }}
              class:active={$locale === localeEl}
            >
              {getLocaleName(localeEl)}
            </a>
          </li>
        {/each}
      </ul>
      
      <style>
        /* */
      </style>
      
    10. バックエンドプロキシを追加する

      オプション

      SvelteKitアプリケーションにバックエンドプロキシを追加するには、vite-intlayerプラグインが提供するintlayerProxy関数を使用できます。このプラグインは、URL、クッキー、およびブラウザーの言語設定に基づいて、ユーザーに最適なロケールを自動的に検出します。

      Intlayer v9以降、intlayerProxy()intlayer()プラグインに直接バンドルされ、routing.enableProxyオプション(デフォルトでtrue)を通じてデフォルトで有効になります。以下に示すように個別に登録することはオプションになりました — これは後方互換性のためと、プラグインの順序を制御する必要があるセットアップのために保持されています。routing.enableProxy: falseを設定してオプトアウトできます。v9リリースノートを参照してください。
      vite.config.ts
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      import { sveltekit } from "@sveltejs/kit/vite";
      
      // https://vitejs.dev/config/
      export default defineConfig({
        plugins: [
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
          sveltekit(),
        ],
      });
      
    11. intlayer editor / CMS を設定する

      オプション

      intlayer エディターをセットアップするには、intlayer エディターのドキュメントに従う必要があります。

      intlayer CMSをセットアップするには、intlayer CMSドキュメントに従う必要があります。

      intlayer editor selector を視覚化するには、intlayer のコンテンツ内でコンポーネント構文を使用する必要があります。

      Component.svelte
      <script lang="ts">
        import { useIntlayer } from "svelte-intlayer";
      
        const content = useIntlayer("component");
      </script>
      
      <div>
      
        <!-- シンプルなコンテンツとしてレンダリング  -->
        <h1>{$content.title}</h1>
      
        <!-- コンポーネントとしてレンダリング(エディタで必要) -->
        {@const Component = $content.component}<Component />
      </div>
      
    12. コンポーネントのコンテンツを抽出する

      オプション

      既存の codebase がある場合、数千のファイルを変換するのに時間がかかる可能性があります。

      このプロセスを容易にするために、Intlayerは、コンポーネントを変換しコンテンツを抽出するための コンパイラ / エクストラクタ を提案しています。

      セットアップするには、intlayer.config.ts ファイルに compiler セクションを追加します。

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... 他の構成
        compiler: {
          /**
           * コンパイラを有効にするかどうかを指定します。
           */
          enabled: true,
      
          /**
           * 出力ファイルのパスを定義します。
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * 変換後にコンポーネントを保存するかどうかを指定します。これにより、コンパイラを一度だけ実行してアプリを変換し、その後削除することができます。
           */
          saveComponents: false,
      
          /**
           * 辞書キーの接頭辞
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      コンポーネントを変換してコンテンツを抽出するためにエクストラクタを実行します

      bash
      npx intlayer extract
      
      Since v9, the intlayerCompiler is included in the intlayer plugin. So you don't need to add it manually.
      babel.config.js
      const {
        intlayerExtractBabelPlugin,
        getExtractPluginOptions,
      } = require("@intlayer/babel");
      
      module.exports = {
        presets: ["next/babel"],
        plugins: [
          // コンポーネントから辞書へコンテンツを抽出する
          [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        ],
      };
      
      bash
      npm run build # または npm run dev
      

    Git Configuration

    Intlayerによって生成されたファイルを無視することをお勧めします。

    .gitignore
    # Intlayerによって生成されたファイルを無視する
    .intlayer
    

    さらに進む

    • ビジュアルエディター: UIから直接翻訳を編集するために、Intlayer Visual Editorを統合します。
    • CMS: コンテンツ管理を外部化するために、Intlayer CMSを使用します。