本文目录导读:

我来为您详细介绍PHP项目中的多语言切换与记忆功能实现方案。
多语言切换实现方案
语言文件配置
// /lang/zh-cn.php
<?php
return [
'welcome' => '欢迎来到我们的网站',
'login' => '登录',
'logout' => '退出',
'hello' => '你好,:name',
'product_count' => '共 :count 件商品',
'date_format' => 'Y年m月d日',
];
?>
// /lang/en.php
<?php
return [
'welcome' => 'Welcome to our website',
'login' => 'Login',
'logout' => 'Logout',
'hello' => 'Hello, :name',
'product_count' => ':count products total',
'date_format' => 'Y-m-d',
];
?>
语言管理类
<?php
class LanguageManager {
private static $instance = null;
private $translations = [];
private $currentLang = 'zh-cn';
private $availableLangs = ['zh-cn', 'en', 'ja', 'ko'];
// 语言名称映射
private $langNames = [
'zh-cn' => '简体中文',
'en' => 'English',
'ja' => '日本語',
'ko' => '한국어'
];
private function __construct() {
$this->loadLanguage();
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 加载语言包
*/
private function loadLanguage() {
$langFile = __DIR__ . '/lang/' . $this->currentLang . '.php';
if (file_exists($langFile)) {
$this->translations = require $langFile;
} else {
// 加载默认语言
$defaultFile = __DIR__ . '/lang/' . $this->getDefaultLang() . '.php';
if (file_exists($defaultFile)) {
$this->translations = require $defaultFile;
}
}
}
/**
* 设置当前语言
*/
public function setLanguage($lang) {
if (in_array($lang, $this->availableLangs)) {
$this->currentLang = $lang;
$this->loadLanguage();
return true;
}
return false;
}
/**
* 获取翻译文本
*/
public function translate($key, $params = []) {
$text = isset($this->translations[$key]) ? $this->translations[$key] : $key;
if (!empty($params)) {
foreach ($params as $placeholder => $value) {
$text = str_replace(':' . $placeholder, $value, $text);
}
}
return $text;
}
/**
* 获取当前语言
*/
public function getCurrentLang() {
return $this->currentLang;
}
/**
* 获取可用语言列表
*/
public function getAvailableLangs() {
return $this->availableLangs;
}
/**
* 获取语言名称
*/
public function getLangName($lang = null) {
$lang = $lang ?: $this->currentLang;
return isset($this->langNames[$lang]) ? $this->langNames[$lang] : $lang;
}
/**
* 获取默认语言
*/
public function getDefaultLang() {
return 'zh-cn'; // 默认中文
}
}
// 辅助函数
function __($key, $params = []) {
return LanguageManager::getInstance()->translate($key, $params);
}
?>
多语言记忆功能
结合Session和Cookie的记忆方案
<?php
class LanguageMemory {
/**
* 从Session或Cookie获取用户语言偏好
*/
public static function getUserLanguage() {
// 1. 首先检查Session
if (isset($_SESSION['user_lang'])) {
return $_SESSION['user_lang'];
}
// 2. 检查Cookie
if (isset($_COOKIE['user_lang'])) {
return $_COOKIE['user_lang'];
}
// 3. 检查浏览器语言
$browserLang = self::detectBrowserLanguage();
if ($browserLang) {
return $browserLang;
}
// 4. 返回默认语言
return 'zh-cn';
}
/**
* 保存用户语言偏好
*/
public static function saveUserLanguage($lang, $remember = false) {
// 保存到Session
$_SESSION['user_lang'] = $lang;
// 如果需要记住,保存到Cookie(30天)
if ($remember) {
setcookie('user_lang', $lang, time() + 30 * 24 * 3600, '/');
}
// 如果用户已登录,保存到数据库
if (isset($_SESSION['user_id'])) {
self::saveToDatabase($_SESSION['user_id'], $lang);
}
}
/**
* 检测浏览器语言
*/
private static function detectBrowserLanguage() {
if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
return null;
}
$langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach ($langs as $lang) {
$lang = substr($lang, 0, 2); // 只取前两位
$langMapping = [
'zh' => 'zh-cn',
'en' => 'en',
'ja' => 'ja',
'ko' => 'ko'
];
if (isset($langMapping[$lang])) {
return $langMapping[$lang];
}
}
return null;
}
/**
* 保存到数据库(用户登录时)
*/
private static function saveToDatabase($userId, $lang) {
try {
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $db->prepare("UPDATE users SET language = ? WHERE id = ?");
$stmt->execute([$lang, $userId]);
} catch (PDOException $e) {
// 记录错误日志
error_log("Failed to save language preference: " . $e->getMessage());
}
}
/**
* 从数据库加载用户语言
*/
public static function loadFromDatabase($userId) {
try {
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $db->prepare("SELECT language FROM users WHERE id = ?");
$stmt->execute([$userId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result && !empty($result['language'])) {
return $result['language'];
}
} catch (PDOException $e) {
error_log("Failed to load language preference: " . $e->getMessage());
}
return null;
}
}
?>
完整的中间件实现
<?php
class LanguageMiddleware {
public function handle($request) {
$langManager = LanguageManager::getInstance();
$langMemory = new LanguageMemory();
// 获取用户语言
$userLang = $langMemory->getUserLanguage();
// 设置语言
if ($langManager->setLanguage($userLang)) {
// 保存到Session(确保一致性)
$_SESSION['user_lang'] = $userLang;
}
// 将语言管理器存储到全局或请求对象
$request->langManager = $langManager;
return true;
}
/**
* 处理语言切换请求
*/
public function handleSwitch($request) {
$lang = $request->get('lang', '');
$remember = $request->get('remember', false);
$redirect = $request->get('redirect', '/');
$langManager = LanguageManager::getInstance();
$langMemory = new LanguageMemory();
if ($langManager->setLanguage($lang)) {
$langMemory->saveUserLanguage($lang, $remember);
// 记录日志
error_log("Language switched to: " . $lang . " by user " . ($_SESSION['user_id'] ?? 'guest'));
}
// 重定向回原页面
header('Location: ' . $redirect);
exit;
}
}
?>
前端实现
语言切换界面
<!-- 语言切换下拉菜单 -->
<div class="language-selector">
<select id="language-select" onchange="changeLanguage(this.value)">
<?php
$langManager = LanguageManager::getInstance();
$currentLang = $langManager->getCurrentLang();
$availableLangs = $langManager->getAvailableLangs();
foreach ($availableLangs as $lang):
?>
<option value="<?php echo $lang; ?>"
<?php echo $lang === $currentLang ? 'selected' : ''; ?>>
<?php echo $langManager->getLangName($lang); ?>
</option>
<?php endforeach; ?>
</select>
<!-- 记住语言选项 -->
<label>
<input type="checkbox" id="remember-lang" checked>
记住语言选择
</label>
</div>
<script>
function changeLanguage(lang) {
var remember = document.getElementById('remember-lang').checked;
var currentUrl = window.location.href;
// 发送AJAX请求切换语言
fetch('/api/switch-language', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
lang: lang,
remember: remember,
redirect: currentUrl
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 刷新页面以应用新语言
window.location.reload();
}
})
.catch(error => {
console.error('Language switch failed:', error);
});
}
// 页面加载时恢复语言设置
document.addEventListener('DOMContentLoaded', function() {
var savedLang = localStorage.getItem('user_lang');
if (savedLang) {
document.getElementById('language-select').value = savedLang;
}
});
</script>
API接口
<?php
// /api/switch-language.php
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Method not allowed']);
exit;
}
$input = json_decode(file_get_contents('php://input'), true);
$lang = $input['lang'] ?? '';
$remember = $input['remember'] ?? false;
$redirect = $input['redirect'] ?? '/';
$middleware = new LanguageMiddleware();
$middleware->handleSwitch(new Request([
'lang' => $lang,
'remember' => $remember,
'redirect' => $redirect
]));
echo json_encode(['success' => true]);
?>
使用示例
配置文件
// config.php
<?php
session_start();
// 自动加载
spl_autoload_register(function ($class) {
$file = __DIR__ . '/classes/' . $class . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化语言管理器
$langManager = LanguageManager::getInstance();
$langMemory = new LanguageMemory();
// 设置用户语言
$userLang = $langMemory->getUserLanguage();
$langManager->setLanguage($userLang);
?>
页面使用
<?php require 'config.php'; ?>
<!DOCTYPE html>
<html>
<head><?php echo __('welcome'); ?></title>
</head>
<body>
<h1><?php echo __('welcome'); ?></h1>
<p><?php echo __('hello', ['name' => '张三']); ?></p>
<p><?php echo __('product_count', ['count' => 5]); ?></p>
<!-- 语言选择器 -->
<?php include 'language_selector.php'; ?>
</body>
</html>
数据库设计
-- 用户语言偏好表
CREATE TABLE user_language_preferences (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
language VARCHAR(10) NOT NULL DEFAULT 'zh-cn',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
UNIQUE KEY unique_user_lang (user_id)
);
-- 语言翻译表(更复杂的实现)
CREATE TABLE translations (
id INT PRIMARY KEY AUTO_INCREMENT,
`key` VARCHAR(255) NOT NULL,
language VARCHAR(10) NOT NULL,
value TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_key_lang (`key`, language),
INDEX idx_language (language)
);
最佳实践建议
- 缓存机制:对语言文件或数据库查询结果进行缓存
- 回退机制:当找不到翻译时回退到默认语言
- 安全性:对语言选择参数进行验证,防止注入攻击
- 性能优化:使用静态缓存避免重复加载语言文件
- SEO考虑:在URL中包含语言参数,如
/zh-cn/about - 兼容性:确保语言切换不破坏现有功能
这个实现方案涵盖了多语言切换的核心功能,并提供了记忆用户偏好的完整解决方案。