PHP项目语言包如何加载切换语种

wen PHP项目 29

本文目录导读:

PHP项目语言包如何加载切换语种

  1. 基础思路
  2. 简单实现(PHP数组文件)
  3. JSON文件实现
  4. 数据库存储(适合大型项目)
  5. 框架集成(以ThinkPHP为例)
  6. 优化建议

在PHP项目中实现语言包的加载和切换,常见的方式有以下几种,我会从简单到复杂,给出具体实现方案。

基础思路

语言包本质上是键值对存储,常见格式:

  • PHP数组文件
  • JSON文件
  • INI文件
  • 数据库存储

简单实现(PHP数组文件)

目录结构

project/
├── lang/
│   ├── zh_cn.php
│   ├── en.php
│   └── ja.php
├── includes/
│   └── language.php
└── index.php

语言文件示例

lang/zh_cn.php

<?php
return [
    'welcome' => '欢迎光临',
    'login' => '登录',
    'logout' => '退出',
    'hello' => '你好, :name',
    'items_count' => '共有 :count 个项目'
];

lang/en.php

<?php
return [
    'welcome' => 'Welcome',
    'login' => 'Login',
    'logout' => 'Logout',
    'hello' => 'Hello, :name',
    'items_count' => 'Total :count items'
];

语言加载类

includes/language.php

<?php
class Language {
    private static $instance = null;
    private $translations = [];
    private $currentLang = 'zh_cn';
    // 支持的语言列表
    private $supportedLanguages = ['zh_cn', 'en', 'ja'];
    private function __construct() {
        $this->setLanguage($this->getBrowserLanguage());
    }
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    /**
     * 设置当前语言
     */
    public function setLanguage($lang) {
        $lang = $this->sanitizeLanguage($lang);
        $this->currentLang = $lang;
        // 加载语言文件
        $file = __DIR__ . '/../lang/' . $lang . '.php';
        if (file_exists($file)) {
            $this->translations = include $file;
        } else {
            // 默认加载中文
            $this->translations = include __DIR__ . '/../lang/zh_cn.php';
        }
    }
    /**
     * 获取翻译文本
     */
    public function get($key, $params = []) {
        $text = isset($this->translations[$key]) 
               ? $this->translations[$key] 
               : $key; // 找不到返回key本身
        // 替换参数
        if (!empty($params)) {
            foreach ($params as $key => $value) {
                $text = str_replace(':' . $key, $value, $text);
            }
        }
        return $text;
    }
    /**
     * 获取浏览器首选语言
     */
    private function getBrowserLanguage() {
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
            $preferred = substr($langs[0], 0, 5);
            // 将浏览器语言映射到我们的语言代码
            $map = [
                'zh-CN' => 'zh_cn',
                'zh-TW' => 'zh_tw',
                'en-US' => 'en',
                'en-GB' => 'en',
                'ja-JP' => 'ja'
            ];
            foreach ($map as $browser => $our) {
                if (stripos($preferred, substr($browser, 0, 2)) !== false) {
                    return $our;
                }
            }
        }
        return 'zh_cn'; // 默认中文
    }
    /**
     * 清理和验证语言代码
     */
    private function sanitizeLanguage($lang) {
        $lang = strtolower(str_replace('-', '_', $lang));
        if (!in_array($lang, $this->supportedLanguages)) {
            return 'zh_cn';
        }
        return $lang;
    }
    /**
     * 获取当前语言
     */
    public function getCurrentLanguage() {
        return $this->currentLang;
    }
}
// 辅助函数
function __($key, $params = []) {
    return Language::getInstance()->get($key, $params);
}

使用示例

index.php

<?php
require_once 'includes/language.php';
// 初始化语言
$lang = Language::getInstance();
// 手动切换语言(例如通过URL参数)
if (isset($_GET['lang'])) {
    $_SESSION['lang'] = $_GET['lang'];
    $lang->setLanguage($_GET['lang']);
} elseif (isset($_SESSION['lang'])) {
    $lang->setLanguage($_SESSION['lang']);
}
// 在模板中使用
?>
<!DOCTYPE html>
<html>
<head><?php echo __('welcome'); ?></title>
</head>
<body>
    <h1><?php echo __('welcome'); ?></h1>
    <p><?php echo __('hello', ['name' => '张三']); ?></p>
    <p><?php echo __('items_count', ['count' => 5]); ?></p>
    <!-- 语言切换链接 -->
    <a href="?lang=zh_cn">中文</a>
    <a href="?lang=en">English</a>
    <a href="?lang=ja">日本語</a>
</body>
</html>

JSON文件实现

如果更喜欢JSON格式:

lang/en.json

{
    "welcome": "Welcome",
    "login": "Login",
    "hello": "Hello, :name"
}

修改Language类

public function setLanguage($lang) {
    $lang = $this->sanitizeLanguage($lang);
    $this->currentLang = $lang;
    $file = __DIR__ . '/../lang/' . $lang . '.json';
    if (file_exists($file)) {
        $json = file_get_contents($file);
        $this->translations = json_decode($json, true);
    } else {
        $this->translations = [];
    }
}

数据库存储(适合大型项目)

数据库表结构

CREATE TABLE translations (
    id INT PRIMARY KEY AUTO_INCREMENT,
    lang_code VARCHAR(10) NOT NULL,
    translation_key VARCHAR(100) NOT NULL,
    translation_value TEXT,
    UNIQUE KEY unique_trans (lang_code, translation_key)
);
INSERT INTO translations (lang_code, translation_key, translation_value) VALUES
('zh_cn', 'welcome', '欢迎光临'),
('en', 'welcome', 'Welcome');

数据库加载类

class DatabaseLanguage {
    private $translations = [];
    private $db;
    public function __construct($db, $lang) {
        $this->db = $db;
        $this->loadFromDatabase($lang);
    }
    private function loadFromDatabase($lang) {
        $stmt = $this->db->prepare(
            "SELECT translation_key, translation_value 
             FROM translations 
             WHERE lang_code = ?"
        );
        $stmt->execute([$lang]);
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $this->translations[$row['translation_key']] = $row['translation_value'];
        }
    }
}

框架集成(以ThinkPHP为例)

ThinkPHP自带多语言支持:

config/app.php

'lang_switch_on' => true,
'default_lang' => 'zh-cn',
'list' => ['zh-cn', 'en', 'ja'],

语言文件

  • application/lang/zh-cn.php
  • application/lang/en.php

使用

// 切换语言
session('lang', 'en');
cookie('lang', 'en');
// 获取翻译
lang('welcome');
lang('hello', ['name' => '张三']);

优化建议

  1. 缓存加载:生产环境可以缓存语言文件

    // 使用文件缓存
    $cacheFile = __DIR__ . '/../cache/lang_' . $lang . '.php';
    if (file_exists($cacheFile)) {
     $this->translations = include $cacheFile;
    } else {
     // 加载并缓存
     $this->translations = include $originalFile;
     file_put_contents($cacheFile, '<?php return ' . var_export($this->translations, true) . ';');
    }
  2. 懒加载:只加载需要的模块

    public function get($key, $module = 'common') {
     if (!isset($this->translations[$module])) {
         $this->loadModule($module);
     }
     return $this->translations[$module][$key] ?? $key;
    }
  3. 使用常量:提高性能

    define('LANG_WELCOME', __('welcome'));
  • 小项目:使用PHP数组文件,简单快速
  • 中等项目:JSON文件,便于非技术人员编辑
  • 大型项目:数据库存储,方便管理,支持在线翻译
  • 框架项目:使用框架自带的多语言功能

选择哪种方式取决于项目规模和具体需求,核心思想都是一致的:将文本与代码分离,通过键值对实现动态切换。

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