---
title: ブラウザーの言語でルーティング
description: デフォルトロケールの URL を、訪問者のブラウザー言語に合うロケールへ転送します。
---

`routeByBrowserLanguage()` は、Blume の i18n が持つルーティングをそのまま使う Astro 統合です。デフォルトロケールはプレフィックスなしで配信されます。訪問者のブラウザーが英語を優先する場合、統合は `/guide` のようなデフォルトロケールのページを `/en/guide` へ転送します。デフォルトロケールを優先する場合は `/guide` のまま表示します。

## できること [#what-it-does]

- ローカルストレージの `blume-locale` に保存されたロケールがそのページを配信している場合は、そのロケールへ転送します。Blume の言語スイッチャーで選んだ言語が保存されており、ブラウザーの言語設定より優先されます。
- 保存されたロケールが使えない場合は、ブラウザーの言語設定（`navigator.languages`）を先頭から調べ、一致するロケールへ転送します。`ja-JP` は `ja` に一致します。
- どちらにも一致する言語がない場合は、そのページを配信している範囲で、Blume のフォールバックロケール、`en`、候補の先頭の順に選びます。
- `/ja/guide` のようなデフォルトロケールのプレフィックス付きの別名 URL を、正規の `/guide` へ転送します。そのあと、正規のページでブラウザー言語による転送が実行されます。
- `/en/guide` のようなほかのロケールの URL はそのままにします。
- クエリ文字列と URL フラグメントを引き継ぎます。

## 仕組み [#how-it-works]

この統合は、Blume の i18n を設定したサイトに次の 2 つを追加します。

1. ミドルウェアで、デフォルトロケールの各ページの `<head>` に小さなインラインスクリプトを挿入します。スクリプトはページの描画前に実行され、そのページを配信している別のロケールがあれば、そのロケールの URL へ転送します。
2. `/<defaultLocale>/[...slug]` のルートを追加し、ビルド時にリダイレクトページを生成します。このページは、プレフィックス付きのデフォルトロケールの URL を、プレフィックスなしの正規 URL へ転送します。

この統合は Astro や Blume の i18n 設定を変更しません。`i18n.defaultLocale` には `i18n.locales` のいずれかのコードを設定し、Blume の規則に従ってデフォルトロケールのコンテンツをコンテンツのルートに置いてください。

## セットアップ [#setup]

```package-install
npm i @tai-kun/blume-integrations
```

`blume.config.ts` の `integrations` に統合を追加し、Blume の i18n に実際のデフォルトロケールを設定します。

```ts blume.config.ts
import { routeByBrowserLanguage } from "@tai-kun/blume-integrations";
import { defineConfig } from "blume";

export default defineConfig({
  integrations: [routeByBrowserLanguage()],

  i18n: {
    defaultLocale: "ja",
    locales: [
      { code: "ja", label: "日本語" },
      { code: "en", label: "English" },
    ],
  },
});
```

`defaultLocale` には、`locales` に含まれるいずれかのコードを設定します。プレースホルダーのロケールを追加する必要はありません。

:::note
Blume の i18n が設定されていない場合、この統合は転送スクリプトを挿入せず、リダイレクトページも作成しません。
:::

## コンテンツの配置 [#content-layout]

デフォルトロケールのページはコンテンツのルートに置きます。それ以外のロケールは、コードを名前とするトップレベルのフォルダーに置きます。

```txt
content/
  index.mdx
  guide.mdx
  en/
    index.mdx
    guide.mdx
```

`defaultLocale: "ja"` の場合、Blume は `content/index.mdx` を `/` で、`content/en/index.mdx` を `/en` で配信します。日本語が優先される場合、`/` と `/guide` へのアクセスは日本語のページを表示します。英語が優先される場合は、`/en` と `/en/guide` へ転送します。

## 動作確認 [#verify]

ビルドしたサイトで、`/guide` のようなデフォルトロケールの URL を開きます。ブラウザーの言語設定に一致するロケール、または Blume の言語スイッチャーで最後に選んだ言語のページへ転送されれば成功です。言語の選択が保存されていない場合、ブラウザーの言語設定を変えると、選ばれるロケールも変わります。

`/ja/guide` も開いてみてください。デフォルトロケールの正規 URL である `/guide` へ転送されます。

## 転送先の選び方 [#matching]

転送先の候補は、そのページを配信しているロケールだけです。候補は `i18n.locales` の設定順に並び、デフォルトロケールは常に候補に含まれます。クライアント側では次の順に転送先を決めます。

1. ローカルストレージの `blume-locale` にロケールが保存されており、そのロケールがページを配信している場合は、そのロケールを選びます。Blume の言語スイッチャーで選んだ言語は、このキーに保存されます。
2. 保存されたロケールが使えない場合は、`navigator.languages` を先頭から調べ、ロケールコードと完全に一致するか、ロケールコードの後ろに `-` が続く言語タグを探します。たとえば `ja-JP` は `ja` に一致します。
3. 一致するものがない場合は、Blume の `fallbackLocale` を選びます。ただし、そのページを配信している場合に限ります。
4. `fallbackLocale` が使えない場合は `en` を選びます。ただし、そのページを配信している場合に限ります。
5. どれも使えない場合は、候補の先頭のロケールを選びます。

| ブラウザーの言語 | ページを配信するロケール | 転送先                                    |
| ---------------- | ------------------------ | ----------------------------------------- |
| `ja-JP`          | `ja`、`en`               | `/guide`                                  |
| `en-US`          | `ja`、`en`               | `/en/guide`                               |
| `fr-FR`          | `ja`、`en`               | `fallbackLocale` が `en` なら `/en/guide` |
| `fr-FR`          | `ja` のみ                | `/guide`                                  |

転送では `window.location.replace()` を使うため、元の URL はブラウザーの履歴に残りません。この統合は言語の選択を保存しません。保存するのは Blume の言語スイッチャーだけです。ストレージが使えない環境では保存されたロケールを読めないため、ブラウザーの言語設定から選びます。

## リダイレクトの対象 [#scope]

ブラウザー言語による転送は、デフォルトロケールのページだけで実行します。サイドバーで非表示にしたページ（`sidebar.hidden: true` または `hidden: true`）は転送しません。ほかのロケールの URL は転送しないため、明示的に開いた `/en/guide` は英語のまま表示されます。

デフォルトロケールのプレフィックス付きの別名 URL は、表示されているすべてのデフォルトロケールのページに対して作成します。バージョン付きの URL にも対応します。`/ja/v1/guide` は `/v1/guide` へ転送され、そのページでもブラウザー言語による転送が実行されます。デプロイ先のベースパスと Blume の `basePath` も転送先に含まれます。

## JavaScript を実行しない場合 [#without-javascript]

デフォルトロケールのページは、実際に生成された通常のページです。JavaScript を実行できない場合、訪問者は言語による転送を受けず、デフォルトロケールのコンテンツをそのまま閲覧します。

プレフィックス付きの別名ページ（`/ja/…`）は転送専用のページです。JavaScript を実行できない場合に備えて、正規のデフォルトロケールのページをリンクとして表示します。AI エージェントやクローラーも、このリンクからページへ到達できます。

## API [#api]

| エクスポート             | 型                       | 説明               |
| ------------------------ | ------------------------ | ------------------ |
| `routeByBrowserLanguage` | `() => AstroIntegration` | 統合を作成します。 |

## 注意点 [#caveats]

- ブラウザー言語による転送はクライアント側の JavaScript で実行するため、初回表示時にデフォルトロケールのページが一瞬表示されることがあります。別名ページは最初の 1 秒間、内容を非表示にしてちらつきを防ぎます。
- 生成されるのは静的な HTML です。サーバー側で言語を判定するわけではありません。
- この統合は Blume の i18n データを使い、`defaultLocale` が設定済みの `locales` に含まれることを前提としています。
- デフォルトロケール専用のコンテンツフォルダーは作りません。コンテンツのルートにあるページはデフォルトロケールのページであり、ほかのロケールはコードを名前とするフォルダーを使います。
