本文目录导读:

在 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>
最佳实践建议
- 选择方案:简单项目用数组方案,大型项目用 gettext 或第三方库
- 统一管理:所有可翻译字符串集中管理
- 参数化:使用
name形式的占位符处理动态内容 - 缓存:生产环境使用 OpCache 或文件缓存
- 复数处理:处理复数形式(如 1 item / 2 items)
选择哪种方案取决于项目规模和团队需求,gettext 是最标准的方案,但需要服务器支持;数组方案最灵活,适合中小型项目。