
本文讲解如何正确将 PHP 翻译数组序列化后存入 Cookie,并避免因错误返回值导致的 ERR_INVALID_RESPONSE;同时指出该方案的性能隐患,并提供更合理的替代实践。
本文讲解如何正确将 php 翻译数组序列化后存入 cookie,并避免因错误返回值导致的 `err_invalid_response`;同时指出该方案的性能隐患,并提供更合理的替代实践。
在 Web 多语言支持中,将翻译数据缓存至客户端(如 Cookie)看似能减少服务端文件包含开销,但实现不当极易引发严重问题。你遇到的 ERR_INVALID_RESPONSE 错误,根源在于 en.php 中使用了 return json_encode($translation); —— 这会导致 PHP 脚本直接输出 JSON 字符串并终止执行,而 require_once() 在被调用时若脚本以 return 结束,其返回值为 null 或未定义行为,后续 json_encode(null) 会生成无效内容,最终污染 HTTP 响应头,触发浏览器拒绝解析。
✅ 正确做法是:移除 return 语句,仅定义 $translation 数组,让 require_once() 正常返回数组变量:
// en.php(修正后)
$translation = [
"home" => ["title" => "Home"],
"contact" => ["title" => "Contact"],
];
// 不加 return!也不输出任何内容(无空格、无 BOM、无 echo)然后在 header.php 中统一处理编码与写入:
if (!isset($_COOKIE['translation']) && !isset($_GET['lang'])) {
require_once('en.php'); // 此时 $translation 已被定义
$jsonEncodedTranslation = json_encode($translation, JSON_UNESCAPED_UNICODE);
setcookie('translation', $jsonEncodedTranslation, [
'expires' => time() + 86400,
'path' => '/',
'domain' => '', // 根据需要设置
'secure' => false, // 生产环境建议设为 true(HTTPS)
'httponly'=> true, // 防 XSS,推荐启用
'samesite'=> 'Lax'
]);
$_COOKIE['translation'] = $jsonEncodedTranslation;
} elseif (isset($_GET['lang']) && preg_match('/^[a-z]{2}$/', $_GET['lang'])) {
$langFile = $_GET['lang'] . '.php';
if (file_exists($langFile)) {
require_once($langFile);
$jsonEncodedTranslation = json_encode($translation, JSON_UNESCAPED_UNICODE);
setcookie('translation', $jsonEncodedTranslation, [
'expires' => time() + 86400,
'path' => '/',
'httponly'=> true,
'samesite'=> 'Lax'
]);
$_COOKIE['translation'] = $jsonEncodedTranslation;
}
}
// 安全解码(需校验 Cookie 是否存在且非空)
if (isset($_COOKIE['translation']) && !empty($_COOKIE['translation'])) {
$decoded = json_decode($_COOKIE['translation']);
if (json_last_error() === JSON_ERROR_NONE && is_object($decoded)) {
echo htmlspecialchars($decoded->home->title, ENT_QUOTES, 'UTF-8');
} else {
error_log("Invalid translation cookie JSON");
echo 'Home'; // fallback
}
} else {
echo 'Home';
}⚠️ 重要注意事项:
- Cookie 大小限制:HTTP Cookie 单个值通常限制在 4KB 内。大型翻译文件(如含百条以上词条)极易超限,导致写入失败或截断。
- 安全风险:直接拼接 $_GET['lang'] 构造文件名属典型路径遍历漏洞(如 ?lang=../etc/passwd),必须严格白名单校验(如正则 /^[a-z]{2}$/)或映射到预定义语言列表。
- 性能反模式:每次请求需传输完整翻译 JSON(可能数 KB),显著增加请求头体积;且服务端需反复 json_decode(),不如直接 require 静态 PHP 数组(PHP OPcache 可高效缓存已编译脚本)。
- 缓存与更新问题:Cookie 过期后用户仍可能看到旧翻译,且无法主动刷新所有客户端缓存。
? 更优实践建议:
- 服务端按需加载:保持 require_once('en.php') 方式,配合 OPcache,实际性能远优于 Cookie 方案;
- 前端国际化库:使用 JavaScript 库(如 i18next)+ JSON 翻译资源,通过 AJAX 按需加载,减轻服务端压力;
- 服务端渲染 + CDN 缓存:结合语言路由(如 /en/home)与静态化策略,兼顾 SEO 与性能。
总之,Cookie 存储翻译数据虽可行,但违背 HTTP 缓存设计原则,易引入安全与性能陷阱。除非有极特殊场景(如纯静态页 + 极简后端),否则推荐回归轻量、可靠、可维护的服务端包含方案。


















