PHP 怎么PHP i18n

wen PHP项目 1

本文目录导读:

PHP 怎么PHP i18n

  1. 使用 gettext 扩展(推荐)
  2. 使用数组/JSON 文件(简单方案)
  3. 使用 .po 文件解析(无需扩展)
  4. 使用第三方库
  5. 完整的示例(多语言切换)
  6. 最佳实践建议

在 PHP 中实现 i18n(国际化)有多种方法,从简单到复杂,以下是几种主流方案:

使用 gettext 扩展(推荐)

安装和配置

# Ubuntu/Debian
sudo apt-get install php-gettext
# CentOS/RHEL
sudo yum install php-gettext

基础用法

<?php
// 设置语言环境
$locale = 'zh_CN'; // 或 'en_US', 'fr_FR' 等
putenv("LANG=$locale");
setlocale(LC_ALL, $locale);
// 指定文本域(翻译文件目录)
$domain = 'messages';
bindtextdomain($domain, './locale');
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
// 翻译文本
echo gettext("Hello World"); // 或简写 _
echo _("Welcome");
?>
<!-- 在模板中使用 -->
<p><?php echo _("Please enter your name"); ?></p>

生成翻译文件

# 1. 提取字符串到 .po 文件
xgettext -d messages -o messages.po main.php
# 2. 编辑 .po 文件添加翻译
# messages.po 内容示例:
# msgid "Hello World"
# msgstr "你好世界"
# 3. 编译为 .mo 文件
msgfmt messages.po -o messages.mo
# 4. 放置到正确目录结构
# ./locale/zh_CN/LC_MESSAGES/messages.mo
# ./locale/en_US/LC_MESSAGES/messages.mo

使用数组/JSON 文件(简单方案)

<?php
class I18n {
    private $translations = [];
    private $language;
    public function __construct($language = 'en') {
        $this->language = $language;
        $this->loadTranslations();
    }
    private function loadTranslations() {
        $file = __DIR__ . "/lang/{$this->language}.php";
        if (file_exists($file)) {
            $this->translations = require $file;
        }
    }
    public function translate($key) {
        return isset($this->translations[$key]) 
            ? $this->translations[$key] 
            : $key;
    }
    public function get($key) {
        return $this->translate($key);
    }
}
// 语言文件 lang/en.php
return [
    'welcome' => 'Welcome to our website',
    'login' => 'Login',
    'logout' => 'Logout',
];
// 语言文件 lang/zh.php
return [
    'welcome' => '欢迎访问我们的网站',
    'login' => '登录',
    'logout' => '退出',
];
// 使用
$i18n = new I18n('zh');
echo $i18n->translate('welcome'); // 欢迎访问我们的网站

使用 .po 文件解析(无需扩展)

<?php
class POFileParser {
    private $translations = [];
    public function load($file) {
        $content = file_get_contents($file);
        preg_match_all('/msgid "(.+)"\nmsgstr "(.+)"/', $content, $matches);
        foreach ($matches[1] as $i => $english) {
            $this->translations[$english] = $matches[2][$i];
        }
    }
    public function translate($text) {
        return isset($this->translations[$text]) 
            ? $this->translations[$text] 
            : $text;
    }
}
// 使用
$po = new POFileParser();
$po->load('locale/zh_CN/messages.po');
echo $po->translate('Hello');

使用第三方库

Symfony Translation

composer require symfony/translation
<?php
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
$translator = new Translator('zh_CN');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', [
    'Hello' => '你好',
    'welcome' => '欢迎',
], 'zh_CN');
echo $translator->trans('Hello'); // 你好

Laravel 的 i18n

// resources/lang/zh/messages.php
return [
    'welcome' => '欢迎来到 :name',
];
// 使用
echo trans('messages.welcome', ['name' => '张三']);
// 或
echo __('messages.welcome', ['name' => '张三']);

完整的示例(多语言切换)

<?php
// config.php
return [
    'languages' => [
        'en' => 'English',
        'zh' => '中文',
        'fr' => 'Français'
    ],
    'default' => 'en'
];
// i18n.php
class i18n {
    private $language;
    private $translations = [];
    public function __construct($language = null) {
        $config = require 'config.php';
        $this->language = $language ?? $_GET['lang'] ?? $_SESSION['lang'] ?? $config['default'];
        $this->language = in_array($this->language, array_keys($config['languages'])) 
            ? $this->language 
            : $config['default'];
        $_SESSION['lang'] = $this->language;
        $this->loadTranslations();
    }
    private function loadTranslations() {
        $file = __DIR__ . "/lang/{$this->language}.php";
        if (file_exists($file)) {
            $this->translations = require $file;
        }
    }
    public function t($key, $params = []) {
        $text = $this->translations[$key] ?? $key;
        // 处理参数替换
        foreach ($params as $param => $value) {
            $text = str_replace(":{$param}", $value, $text);
        }
        return $text;
    }
}
// 使用
$i18n = new i18n();
echo $i18n->t('welcome', ['name' => 'John']);
// 语言切换
<a href="?lang=en">English</a> | <a href="?lang=zh">中文</a>

最佳实践建议

  1. 选择方案:简单项目用数组方案,大型项目用 gettext 或第三方库
  2. 统一管理:所有可翻译字符串集中管理
  3. 参数化:使用 name 形式的占位符处理动态内容
  4. 缓存:生产环境使用 OpCache 或文件缓存
  5. 复数处理:处理复数形式(如 1 item / 2 items)

选择哪种方案取决于项目规模和团队需求,gettext 是最标准的方案,但需要服务器支持;数组方案最灵活,适合中小型项目。

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