用戶訪問多語言站點時,若能根據瀏覽器 Accept-Language 標頭自動導向對應語言版本,將顯著提升轉化率。本文提供一份生產級可用的 PHP 實現,涵蓋語言代碼解析優先級、地區變體處理、回退策略、緩存友好重定向及測試驗證方法。
<?php
/**
* 根據 HTTP_ACCEPT_LANGUAGE 自動重定向到對應語言版本
* 支持:zh-HK/zh-TW → 繁體 | zh-CN/zh-SG → 簡體 | en-* → 英文 | 其他 → 默認英文
*/
function redirectByBrowserLanguage(): never
{
// 1. 獲取並標準化語言標頭
$acceptLang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
$acceptLang = strtolower(trim($acceptLang));
if ($acceptLang === '') {
// 無標頭:直接走默認
gotoDefault();
}
// 2. 解析優先級列表 (按 q-value 排序)
// 格式: "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7"
$langs = [];
foreach (explode(',', $acceptLang) as $part) {
$part = trim($part);
$q = 1.0;
if (strpos($part, ';q=') !== false) {
[$tag, $qv] = explode(';q=', $part, 2);
$q = (float)$qv;
$part = trim($tag);
}
$langs[$part] = $q;
}
arsort($langs); // 按優先級降序
// 3. 定義語言映射規則 (按優先級順序)
$rules = [
// 繁體中文地區
'/^zh[_-](hk|tw|mo)$/i' => 'zh-Hant', // 香港/台灣/澳門
// 簡體中文地區
'/^zh[_-](cn|sg|my)$/i' => 'zh-Hans', // 大陸/新加坡/馬來西亞
// 英文系
'/^en/ i' => 'en',
// 日語/韓語/其他可擴展
'/^ja/ i' => 'ja',
'/^ko/ i' => 'ko',
];
// 4. 匹配最優語言
foreach ($langs as $langTag => $q) {
foreach ($rules as $pattern => $locale) {
if (preg_match($pattern, $langTag)) {
redirectToLocale($locale);
}
}
}
// 5. 都不匹配 → 默認
gotoDefault();
}
function redirectToLocale(string $locale): never
{
// 避免重定向循環:檢查當前已在目標語言路徑
$currentPath = $_SERVER['REQUEST_URI'] ?? '/';
if (str_starts_with($currentPath, "/{$locale}/")) {
return; // 已在正確語言,不再跳轉
}
$targetUrl = "/{$locale}/index.php"; // 或由路由系統生成
// SEO 友好:302 臨時重定向 (語言選擇非永久)
header("Location: {$targetUrl}", true, 302);
exit;
}
function gotoDefault(): never
{
redirectToLocale('en'); // 默認英文
}
// 執行
redirectByBrowserLanguage();
瀏覽器發送示例:zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
zh-CN、en-US、zh-Hant-HKq=0.9 表示偏好度 (0-1),省略默認 1.0上述代碼完整實現了 q-value 排序,而非簡單的 preg_match 順序匹配,確保尊重用戶真實偏好。
| 語言標簽 | 地區 | 目標語系 | 備註 |
|---|---|---|---|
| zh-CN, zh-SG, zh-MY | 中國大陸/新加坡/馬來西亞 | zh-Hans (簡體) | 官方簡體 |
| zh-TW, zh-HK, zh-MO | 台灣/香港/澳門 | zh-Hant (繁體) | 官方繁體 |
| zh (無地區) | 通用中文 | zh-Hans | 回退策略:默認簡體 |
若無此判斷,用戶手動切換語言後再刷新,會被強制拉回瀏覽器語言,體驗極差。
header('Vary: Accept-Language'),告知 CDN/代理按語言緩存不同版本<link rel="alternate" hreflang="..." href="...">,幫助搜索引擎識別多語言版本瀏覽器語言不可靠 (用戶可能設置錯誤、使用 VPN),生產環境建議 GeoIP 為主,Accept-Language 為輔:
| 測試場景 | 模擬方法 | 預期結果 |
|---|---|---|
| 香港用戶 (繁體) | ModHeader 設置 Accept-Language: zh-HK,zh;q=0.9 | 跳轉 /zh-Hant/ |
| 台灣用戶 (繁體) | zh-TW,zh;q=0.9 | 跳轉 /zh-Hant/ |
| 大陸用戶 (簡體) | zh-CN,zh;q=0.9 | 跳轉 /zh-Hans/ |
| 美國用戶 (英文) | en-US,en;q=0.9 | 跳轉 /en/ |
| 多語言偏好 | zh-TW,zh-CN;q=0.8,en;q=0.7 | 按 q 值跳轉 /zh-Hant/ |
| 無標頭 / 爬蟲 | 清空 Header | 跳轉 /en/ (默認) |
| 已在目標語言頁 | 訪問 /zh-Hant/about.php | 不重定向 (避免循環) |
Middleware,綁定 kernel.php 的 web 組,配合 Laravel-Localization 包RequestListener 或使用 JMSI18nRoutingBundleBehavior\CheckLang 或中間件common.php 最頂部,session_start() 之前一個健壯的語言自動跳轉方案,核心在於:完整解析 q-value、精準映射繁簡地區碼、防重定向循環、SEO 友好頭部、GeoIP 雙重校驗。本文代碼開箱即用,可直接集成至項目入口,並建議配合前端語言選擇器 (持久化到 Cookie/LocalStorage) 實現「自動推薦 + 手動覆蓋」的最佳體驗閉環。