---
title: "Edge-side i18nリダイレクト実装ガイド | Cloudflare Pages Functionsで多言語対応"
description: "Accept-LanguageヘッダーとCookieを使用した自動言語判定、SEO対策(ボット検出)、セキュアなCookie実装を完全解説。Cloudflare Pages Functionsでの実装手順を35個のテストケース付きで紹介。"
created: "2026-01-08"
status: "published"
platforms:
wordpress:
published: true
wp_status: "future"
url: "https://wakatchi.dev/?p=2537"
published_date: "2026-02-03T06:00:00+09:00"
post_id: 2537
slug: "edge-side-i18n-cloudflare"
tags: ["i18n", "Edge Functions", "VitePress", "TypeScript", "Cookie", "Accept-Language"]
---

## 背景
多言語Webサイトの課題は、**ユーザーの言語設定を自動判定し、最適な言語バージョンへシームレスにリダイレクトする**ことです。
VitePressで構築した多言語サイト(英語 `/` と日本語 `/ja/`)において、従来はユーザーが手動で言語を切り替える必要がありました。初回訪問時に**Accept-Languageヘッダー**から自動判定し、Cookieで言語選択を永続化することで、UXを大幅に改善できます。
**エッジサイド処理(Cloudflare Pages Functions)** を活用することで、以下のメリットが得られます:
- **低レイテンシ**: オリジンサーバーへのリクエスト前に言語判定が完了
- **高パフォーマンス**: CDNレベルでのリダイレクト処理で不要なオリジンリクエストを削減
- **SEO維持**: ボット検出により検索エンジンクローラーにはリダイレクトしない
本ガイドでは、このEdge-side i18n実装を**段階的に解説**します。
## こんな人におすすめ
- Cloudflare Pages/Workersで多言語対応を考えている方
- エッジサイドでのリダイレクト実装に興味のある方
- VitePressで国際化対応に取り組んでいる方
- セキュアなCookie実装やボット検出について学びたい方
- Edge FunctionsとAccept-Languageの統合方法を知りたい方
## 目次
- [背景](#背景)
- [よくある質問(FAQ)](#よくある質問faq)
- [要件](#要件)
- [実装方針](#実装方針)
- [ポイント](#ポイント)
- [Immutable Headers問題の解決](#immutable-headers問題の解決)
- [ボット検出パターン](#ボット検出パターン)
- [Cookie セキュリティ設定](#cookie-セキュリティ設定)
- [学び](#学び)
- [参考情報](#参考情報)
## よくある質問(FAQ)
**Q: Edge Functions を使う理由は何か?**
A: エッジサイドで言語判定を実行することで、オリジンサーバーへのリクエスト前に処理が完了します。結果として、ネットワークレイテンシが削減され、ユーザーにより高速な体験を提供できます。また、不要なオリジンリクエストが減少するため、サーバー負荷も軽減されます。
**Q: Accept-Language ヘッダーだけで十分では?**
A: Accept-Languageヘッダーは、ユーザーのブラウザ設定に基づいています。しかし、ユーザーが一度言語を手動選択した場合、その選択を忘れずに保持する必要があります。**Cookieを併用**することで、ユーザーの明示的な選択を優先しながら、初回訪問時にはAccept-Languageを参照できます。
**Q: SEO的にリダイレクトは大丈夫?**
A: 301(恒久的)リダイレクトではなく、302(一時的)リダイレクトを使用し、かつ**ボット検出**によりGooglebot等のクローラーにはリダイレクトしません。これにより、検索エンジンは各言語版を個別にインデックスでき、SEOへの悪影響を回避できます。
## 要件
- 初回訪問時にAccept-Languageヘッダーから言語を自動判定
- Cookie `pref-lang` による言語選択の永続化(1年間有効)
- Cloudflare `cf.country` による地理位置情報フォールバック
- SEO維持のためクローラー(Googlebot、Bingbot等)にはリダイレクトしない
- クエリパラメータの保持(`?tag=wordpress&page=2` など)
- VitePressの既存言語切り替え機能との互換性維持
## 実装方針
1. **Cloudflare Pages Functions** (`functions/_middleware.ts`) で言語判定ロジックを実装
2. **5段階の優先度**で言語を判定:
- Cookie `pref-lang` → Accept-Language → cf.country → デフォルト(en)
3. **定数管理** (`functions/constants.ts`) で設定を一元化
4. **クライアント側永続化** (`language-persistence.ts`) でVitePressテーマと統合
5. **包括的テスト** (35テストケース) で品質担保
### 言語判定フロー
以下のフローチャートで、5段階の優先度に基づいた言語判定プロセスを図示しています:
```mermaid
flowchart TD
A[リクエスト受信] --> B{Bot/Crawler<br/>か?}
B -->|はい| Z[リダイレクトなし]
B -->|いいえ| C{Cookie<br/>pref-lang<br/>存在?}
C -->|はい| D["lang = Cookie値<br/>を使用"]
C -->|いいえ| E{Accept-Language<br/>ヘッダー<br/>解析可能?}
E -->|はい| F["lang = Accept-Language<br/>から言語を抽出"]
E -->|いいえ| G{cf.country<br/>マップに<br/>存在?}
G -->|はい| H["lang = 地理位置情報<br/>から言語を判定"]
G -->|いいえ| I["lang = デフォルト<br/>en を使用"]
D --> J{現在の言語<br/>と異なる?}
F --> J
H --> J
I --> J
J -->|はい| K["リダイレクト実行<br/>Set-Cookie: pref-lang"]
J -->|いいえ| L[リダイレクトなし]
K --> M[新しい言語ページへ]
L --> M
Z --> M
```
## ポイント
### Immutable Headers問題の解決
Cloudflare Workersでは`Response.redirect()`や`context.next()`から返されるResponseオブジェクトのヘッダーは不変(immutable)。
**問題のあるコード**:
```typescript
const response = Response.redirect(redirectUrl, 302);
response.headers.append('Set-Cookie', ...); // エラー: 不変ヘッダーを変更できない
```
**解決策**: 新しいHeadersオブジェクトを作成してからResponseを構築
```typescript
function createResponseWithCookie(response: Response, lang: Language): Response {
const headers = new Headers(response.headers);
headers.append('Set-Cookie', generateCookieString(lang));
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers
});
}
```
### ボット検出パターン
10以上の主要クローラーを正規表現で検出し、SEOを維持:
```typescript
export const BOT_PATTERNS = {
USER_AGENTS: /bot|crawler|spider|crawling|googlebot|bingbot|slurp|duckduckbot|baiduspider|yandexbot|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator/i,
} as const;
```
### Cookie セキュリティ設定
```typescript
export const COOKIE_OPTIONS = {
path: '/',
httpOnly: true, // XSS攻撃防止:JavaScriptからのアクセスをブロック
secure: true, // HTTPS接続時のみ送信(中間者攻撃防止)
sameSite: 'lax', // CSRF攻撃防止:クロスサイトリクエストでのCookie送信を制限
} as const;
```
**セキュリティ属性の詳細**:
- **`httpOnly`**: Cookie がクライアント側の JavaScript(XSS攻撃)からアクセスされることを防止します
- **`secure`**: HTTPS接続時のみ Cookie を送信し、平文のHTTP通信での盗聴を防ぎます
- **`sameSite: 'lax'`**: クロスサイトリクエストでの Cookie 送信を制限し、CSRF攻撃を防止します
これらの設定により、ユーザーの言語選択情報は高いセキュリティレベルで保護されます。
## 学び
1. **Cloudflare Workers APIの特性**: Immutable Responseの扱いは標準Node.jsと異なる
2. **エッジサイド処理の利点**: オリジンへのリクエスト前に言語判定が完了し、レイテンシが大幅に削減される
3. **サーバー/クライアント連携**: サーバー側httpOnly Cookieとクライアント側オブザーバーの組み合わせで、セキュリティとUXを両立
4. **包括的テストの重要性**: 35件のテストケースにより、エッジケースを含む全検出パスをカバー
5. **SEOとユーザビリティの両立**: ボット検出により、検索エンジンには全言語版を適切にインデックスさせつつ、人間ユーザーには最適な言語を自動提供
## まとめ
本ガイドでは、**Cloudflare Pages Functions を活用したEdge-side i18n(国際化)リダイレクト** の実装方法を解説しました。
### 実装のポイント
1. **Immutable Response の理解**: Cloudflare Workers の `Response` オブジェクトは不変のため、新しい `Headers` を作成してから `Response` を構築する必要があります
2. **5段階の優先度フロー**: Cookie → Accept-Language → cf.country → デフォルト という段階的な言語判定により、ユーザーの意図を最優先しながら初回訪問時には Accept-Language から言語を自動判定できます
3. **SEO 対策とボット検出**: 302リダイレクト(一時的)と BOT検出の組み合わせにより、検索エンジンクローラーには各言語版を個別にインデックスさせながら、一般ユーザーには最適な言語版を自動提供できます
4. **セキュアな Cookie 実装**: `httpOnly`、`secure`、`sameSite` 属性により、XSS攻撃、中間者攻撃、CSRF攻撃を防止しながら、ユーザーの言語選択を安全に保持できます
### 適用可能なシーン
このパターンは、以下のような多言語 Web サイトに適用可能です:
- **国際的な SaaS プロダクト**: ユーザーの地理位置情報や言語設定に基づいた自動リダイレクト
- **オープンソースプロジェクト**: ドキュメントサイトの多言語対応
- **コンテンツメディア**: 複数言語で提供するニュースサイトやブログ
35件のテストケースによる包括的な検証により、エッジケースを含む全検出パスをカバーしているため、実装の信頼性も高く、本番環境への適用も安心です。
## さらに学ぶ
このパターンに関連する技術について、さらに詳しく学びたい場合は以下のトピックを推奨します:
- **Cloudflare Workers**: エッジサイド処理の基礎と応用
- **HTTPヘッダー仕様**: Accept-Language、User-Agent の正規表現マッチング
- **セキュアなCookie実装**: httpOnly、secure、sameSite 属性の組み合わせ
- **多言語SEO**: hreflang タグと言語別ページのインデックス戦略
- **エッジコンピューティング**: CDNレベルでのロジック実装とパフォーマンス最適化

背景
多言語Webサイトの課題は、ユーザーの言語設定を自動判定し、最適な言語バージョンへシームレスにリダイレクトすることです。
VitePressで構築した多言語サイト(英語 / と日本語 /ja/)において、従来はユーザーが手動で言語を切り替える必要がありました。初回訪問時にAccept-Languageヘッダーから自動判定し、Cookieで言語選択を永続化することで、UXを大幅に改善できます。
エッジサイド処理(Cloudflare Pages Functions) を活用することで、以下のメリットが得られます:
- 低レイテンシ: オリジンサーバーへのリクエスト前に言語判定が完了
- 高パフォーマンス: CDNレベルでのリダイレクト処理で不要なオリジンリクエストを削減
- SEO維持: ボット検出により検索エンジンクローラーにはリダイレクトしない
本ガイドでは、このEdge-side i18n実装を段階的に解説します。
こんな人におすすめ
- Cloudflare Pages/Workersで多言語対応を考えている方
- エッジサイドでのリダイレクト実装に興味のある方
- VitePressで国際化対応に取り組んでいる方
- セキュアなCookie実装やボット検出について学びたい方
- Edge FunctionsとAccept-Languageの統合方法を知りたい方
目次
よくある質問(FAQ)
Q: Edge Functions を使う理由は何か?
A: エッジサイドで言語判定を実行することで、オリジンサーバーへのリクエスト前に処理が完了します。結果として、ネットワークレイテンシが削減され、ユーザーにより高速な体験を提供できます。また、不要なオリジンリクエストが減少するため、サーバー負荷も軽減されます。
Q: Accept-Language ヘッダーだけで十分では?
A: Accept-Languageヘッダーは、ユーザーのブラウザ設定に基づいています。しかし、ユーザーが一度言語を手動選択した場合、その選択を忘れずに保持する必要があります。Cookieを併用することで、ユーザーの明示的な選択を優先しながら、初回訪問時にはAccept-Languageを参照できます。
Q: SEO的にリダイレクトは大丈夫?
A: 301(恒久的)リダイレクトではなく、302(一時的)リダイレクトを使用し、かつボット検出によりGooglebot等のクローラーにはリダイレクトしません。これにより、検索エンジンは各言語版を個別にインデックスでき、SEOへの悪影響を回避できます。
要件
- 初回訪問時にAccept-Languageヘッダーから言語を自動判定
- Cookie
pref-lang による言語選択の永続化(1年間有効)
- Cloudflare
cf.country による地理位置情報フォールバック
- SEO維持のためクローラー(Googlebot、Bingbot等)にはリダイレクトしない
- クエリパラメータの保持(
?tag=wordpress&page=2 など)
- VitePressの既存言語切り替え機能との互換性維持
実装方針
- Cloudflare Pages Functions (
functions/_middleware.ts) で言語判定ロジックを実装
- 5段階の優先度で言語を判定:
- Cookie
pref-lang → Accept-Language → cf.country → デフォルト(en)
- 定数管理 (
functions/constants.ts) で設定を一元化
- クライアント側永続化 (
language-persistence.ts) でVitePressテーマと統合
- 包括的テスト (35テストケース) で品質担保
言語判定フロー
以下のフローチャートで、5段階の優先度に基づいた言語判定プロセスを図示しています:
flowchart TD
A[リクエスト受信] --> B{Bot/Crawler<br/>か?}
B -->|はい| Z[リダイレクトなし]
B -->|いいえ| C{Cookie<br/>pref-lang<br/>存在?}
C -->|はい| D["lang = Cookie値<br/>を使用"]
C -->|いいえ| E{Accept-Language<br/>ヘッダー<br/>解析可能?}
E -->|はい| F["lang = Accept-Language<br/>から言語を抽出"]
E -->|いいえ| G{cf.country<br/>マップに<br/>存在?}
G -->|はい| H["lang = 地理位置情報<br/>から言語を判定"]
G -->|いいえ| I["lang = デフォルト<br/>en を使用"]
D --> J{現在の言語<br/>と異なる?}
F --> J
H --> J
I --> J
J -->|はい| K["リダイレクト実行<br/>Set-Cookie: pref-lang"]
J -->|いいえ| L[リダイレクトなし]
K --> M[新しい言語ページへ]
L --> M
Z --> M
ポイント
Immutable Headers問題の解決
Cloudflare WorkersではResponse.redirect()やcontext.next()から返されるResponseオブジェクトのヘッダーは不変(immutable)。
問題のあるコード:
const response = Response.redirect(redirectUrl, 302);
response.headers.append('Set-Cookie', ...); // エラー: 不変ヘッダーを変更できない
解決策: 新しいHeadersオブジェクトを作成してからResponseを構築
function createResponseWithCookie(response: Response, lang: Language): Response {
const headers = new Headers(response.headers);
headers.append('Set-Cookie', generateCookieString(lang));
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers
});
}
ボット検出パターン
10以上の主要クローラーを正規表現で検出し、SEOを維持:
export const BOT_PATTERNS = {
USER_AGENTS: /bot|crawler|spider|crawling|googlebot|bingbot|slurp|duckduckbot|baiduspider|yandexbot|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator/i,
} as const;
Cookie セキュリティ設定
export const COOKIE_OPTIONS = {
path: '/',
httpOnly: true, // XSS攻撃防止:JavaScriptからのアクセスをブロック
secure: true, // HTTPS接続時のみ送信(中間者攻撃防止)
sameSite: 'lax', // CSRF攻撃防止:クロスサイトリクエストでのCookie送信を制限
} as const;
セキュリティ属性の詳細:
httpOnly: Cookie がクライアント側の JavaScript(XSS攻撃)からアクセスされることを防止します
secure: HTTPS接続時のみ Cookie を送信し、平文のHTTP通信での盗聴を防ぎます
sameSite: 'lax': クロスサイトリクエストでの Cookie 送信を制限し、CSRF攻撃を防止します
これらの設定により、ユーザーの言語選択情報は高いセキュリティレベルで保護されます。
学び
- Cloudflare Workers APIの特性: Immutable Responseの扱いは標準Node.jsと異なる
- エッジサイド処理の利点: オリジンへのリクエスト前に言語判定が完了し、レイテンシが大幅に削減される
- サーバー/クライアント連携: サーバー側httpOnly Cookieとクライアント側オブザーバーの組み合わせで、セキュリティとUXを両立
- 包括的テストの重要性: 35件のテストケースにより、エッジケースを含む全検出パスをカバー
- SEOとユーザビリティの両立: ボット検出により、検索エンジンには全言語版を適切にインデックスさせつつ、人間ユーザーには最適な言語を自動提供
まとめ
本ガイドでは、Cloudflare Pages Functions を活用したEdge-side i18n(国際化)リダイレクト の実装方法を解説しました。
実装のポイント
-
Immutable Response の理解: Cloudflare Workers の Response オブジェクトは不変のため、新しい Headers を作成してから Response を構築する必要があります
-
5段階の優先度フロー: Cookie → Accept-Language → cf.country → デフォルト という段階的な言語判定により、ユーザーの意図を最優先しながら初回訪問時には Accept-Language から言語を自動判定できます
-
SEO 対策とボット検出: 302リダイレクト(一時的)と BOT検出の組み合わせにより、検索エンジンクローラーには各言語版を個別にインデックスさせながら、一般ユーザーには最適な言語版を自動提供できます
-
セキュアな Cookie 実装: httpOnly、secure、sameSite 属性により、XSS攻撃、中間者攻撃、CSRF攻撃を防止しながら、ユーザーの言語選択を安全に保持できます
適用可能なシーン
このパターンは、以下のような多言語 Web サイトに適用可能です:
- 国際的な SaaS プロダクト: ユーザーの地理位置情報や言語設定に基づいた自動リダイレクト
- オープンソースプロジェクト: ドキュメントサイトの多言語対応
- コンテンツメディア: 複数言語で提供するニュースサイトやブログ
35件のテストケースによる包括的な検証により、エッジケースを含む全検出パスをカバーしているため、実装の信頼性も高く、本番環境への適用も安心です。
さらに学ぶ
このパターンに関連する技術について、さらに詳しく学びたい場合は以下のトピックを推奨します:
- Cloudflare Workers: エッジサイド処理の基礎と応用
- HTTPヘッダー仕様: Accept-Language、User-Agent の正規表現マッチング
- セキュアなCookie実装: httpOnly、secure、sameSite 属性の組み合わせ
- 多言語SEO: hreflang タグと言語別ページのインデックス戦略
- エッジコンピューティング: CDNレベルでのロジック実装とパフォーマンス最適化