PHP项目多语言切换与记忆

wen PHP项目 1

本文目录导读:

PHP项目多语言切换与记忆

  1. 多语言切换实现方案
  2. 多语言记忆功能
  3. 前端实现
  4. 使用示例
  5. 数据库设计
  6. 最佳实践建议

我来为您详细介绍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)
);

最佳实践建议

  1. 缓存机制:对语言文件或数据库查询结果进行缓存
  2. 回退机制:当找不到翻译时回退到默认语言
  3. 安全性:对语言选择参数进行验证,防止注入攻击
  4. 性能优化:使用静态缓存避免重复加载语言文件
  5. SEO考虑:在URL中包含语言参数,如 /zh-cn/about
  6. 兼容性:确保语言切换不破坏现有功能

这个实现方案涵盖了多语言切换的核心功能,并提供了记忆用户偏好的完整解决方案。

抱歉,评论功能暂时关闭!