PHP 怎么PHP语言包

wen PHP项目 2

本文目录导读:

PHP 怎么PHP语言包

  1. 最简单的数组方式
  2. 使用Gettext扩展
  3. 使用第三方库 - Symfony Translation
  4. 完整的语言包管理系统
  5. 语言切换功能
  6. 数据库存储语言包
  7. 最佳实践建议

我来详细介绍PHP实现语言包(国际化/i18n)的几种常用方法:

最简单的数组方式

基础实现

<?php
// lang/en.php
return [
    'welcome' => 'Welcome to our website',
    'hello' => 'Hello, :name',
    'login' => 'Login',
    'logout' => 'Logout',
];
// lang/zh.php
return [
    'welcome' => '欢迎访问我们的网站',
    'hello' => '你好,:name',
    'login' => '登录',
    'logout' => '退出',
];

使用类封装

<?php
class Translator {
    private static $translations = [];
    private static $defaultLang = 'zh';
    public static function load($lang) {
        $file = __DIR__ . "/lang/{$lang}.php";
        if (file_exists($file)) {
            self::$translations = require $file;
        }
    }
    public static function setLang($lang) {
        self::load($lang);
    }
    public static function t($key, $params = []) {
        $text = self::$translations[$key] ?? $key;
        // 替换参数
        foreach ($params as $name => $value) {
            $text = str_replace(":{$name}", $value, $text);
        }
        return $text;
    }
}
// 使用示例
Translator::setLang($_GET['lang'] ?? 'zh');
echo Translator::t('welcome'); // 欢迎访问我们的网站
echo Translator::t('hello', ['name' => '张三']); // 你好,张三

使用Gettext扩展

安装配置

// php.ini 中开启
extension=gettext
// 创建翻译文件目录
// locale/zh_CN/LC_MESSAGES/messages.po

Gettext使用示例

<?php
// 初始化gettext
function initGettext($lang = 'zh_CN') {
    $locale = $lang . '.UTF-8';
    putenv("LANG={$locale}");
    setlocale(LC_ALL, $locale);
    $domain = 'messages';
    bindtextdomain($domain, __DIR__ . '/locale');
    textdomain($domain);
}
// 使用gettext
initGettext('zh_CN');
echo gettext("Welcome to our website");
echo _("Hello, World!"); // _() 是 gettext() 的简写
// 带变量的翻译
printf(_("Hello, %s"), '张三');

PO文件示例

# locale/zh_CN/LC_MESSAGES/messages.po
msgid "Welcome"
msgstr "欢迎"
msgid "Hello, %s"
msgstr "你好,%s"

使用第三方库 - Symfony Translation

安装

composer require symfony/translation

使用示例

<?php
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\Loader\PhpFileLoader;
$translator = new Translator('zh_CN');
// 添加加载器
$translator->addLoader('php', new PhpFileLoader());
$translator->addLoader('array', new ArrayLoader());
// 加载翻译文件
$translator->addResource('php', __DIR__ . '/lang/zh.php', 'zh_CN');
$translator->addResource('php', __DIR__ . '/lang/en.php', 'en');
// 使用翻译
echo $translator->trans('welcome');
echo $translator->trans('hello', ['%name%' => '张三']);
// 复数形式
echo $translator->trans('apple', ['%count%' => 5], 'messages', 'zh_CN');

完整的语言包管理系统

<?php
class LanguageManager {
    private $langDir;
    private $currentLang;
    private $translations = [];
    private static $instance = null;
    private function __construct() {
        $this->langDir = __DIR__ . '/lang/';
        $this->currentLang = $this->detectLanguage();
        $this->loadLanguage();
    }
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    private function detectLanguage() {
        // 从会话获取
        if (isset($_SESSION['lang'])) {
            return $_SESSION['lang'];
        }
        // 从Cookie获取
        if (isset($_COOKIE['lang'])) {
            return $_COOKIE['lang'];
        }
        // 从浏览器语言自动检测
        $browserLang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '', 0, 2);
        return in_array($browserLang, ['zh', 'en']) ? $browserLang : 'zh';
    }
    public function setLanguage($lang) {
        if (file_exists($this->langDir . $lang . '.php')) {
            $this->currentLang = $lang;
            $_SESSION['lang'] = $lang;
            setcookie('lang', $lang, time() + 3600 * 24 * 365);
            $this->loadLanguage();
        }
    }
    private function loadLanguage() {
        $file = $this->langDir . $this->currentLang . '.php';
        $this->translations = file_exists($file) ? require $file : [];
    }
    public function t($key, $params = []) {
        $text = $this->translations[$key] ?? $key;
        if (!empty($params)) {
            foreach ($params as $name => $value) {
                $text = preg_replace('/\{' . $name . '\}|:' . $name . '/i', $value, $text);
            }
        }
        return $text;
    }
    public function getCurrentLang() {
        return $this->currentLang;
    }
    public function getAllTranslations() {
        return $this->translations;
    }
}
// 使用示例
$lang = LanguageManager::getInstance();
echo $lang->t('welcome'); // 自动检测语言并翻译
echo $lang->t('hello', ['name' => '李四']);

语言切换功能

<?php
// 语言切换链接
$currentLang = LanguageManager::getInstance()->getCurrentLang();
?>
<div class="language-switcher">
    <a href="?lang=zh" <?php echo $currentLang == 'zh' ? 'class="active"' : ''; ?>>中文</a>
    <a href="?lang=en" <?php echo $currentLang == 'en' ? 'class="active"' : ''; ?>>English</a>
</div>
<?php
// 处理切换请求
if (isset($_GET['lang'])) {
    $allowed = ['zh', 'en', 'ja', 'fr'];
    $requested = $_GET['lang'];
    if (in_array($requested, $allowed)) {
        LanguageManager::getInstance()->setLanguage($requested);
        header('Location: ' . str_replace('?lang=' . $requested, '', $_SERVER['REQUEST_URI']));
    }
}

数据库存储语言包

<?php
class DatabaseTranslator {
    private $db;
    private $translations = [];
    public function __construct($pdo) {
        $this->db = $pdo;
        $this->loadTranslations();
    }
    public function loadTranslations($lang) {
        $stmt = $this->db->prepare("
            SELECT t.key, t.value 
            FROM translations t
            WHERE t.language = :lang
        ");
        $stmt->execute(['lang' => $lang]);
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $this->translations[$row['key']] = $row['value'];
        }
    }
    public function t($key) {
        return $this->translations[$key] ?? $key;
    }
    // 缓存翻译到文件
    public function cacheToFile($lang) {
        $cacheFile = __DIR__ . "/cache/{$lang}.php";
        $content = "<?php\nreturn " . var_export($this->translations, true) . ";\n";
        file_put_contents($cacheFile, $content);
    }
}

最佳实践建议

  1. 命名规范:使用点号分隔层级,如 menu.home.title
  2. 参数化:避免拼接字符串,使用占位符
  3. 缓存机制:生产环境可以合并缓存语言文件
  4. 自动检测:根据用户浏览器语言自动选择
  5. 回退机制:找不到翻译时返回原始键名

选择哪种方案取决于项目需求:

  • 简单项目用数组方式
  • 需要系统级支持用Gettext
  • 大型项目用Symfony等成熟库

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