本文目录导读:

在 PHP 中进行本地化(L10n,Localization)有几种不同的方式,从简单的内置函数到完整的框架解决方案,以下是详细的指南:
使用 gettext 扩展(最常用)
安装和启用
# Ubuntu/Debian sudo apt-get install php-gettext php-intl # CentOS/RHEL sudo yum install php-gettext php-intl
基本用法
<?php
// 设置语言环境
$locale = 'zh_CN.UTF-8'; // 中文
// $locale = 'en_US.UTF-8'; // 英文
putenv("LC_ALL=$locale");
setlocale(LC_ALL, $locale);
// 指定文本域(domain)
$domain = 'messages';
bindtextdomain($domain, './locale');
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
// 翻译字符串
echo gettext("Hello World");
// 或简写
echo _("Hello World");
// 复数形式
echo ngettext("item", "items", $count);
?>
创建翻译文件
-
创建 POT 文件(模板文件):
xgettext -n -o messages.pot *.php
-
生成 PO 文件(每种语言一个):
msginit -i messages.pot -o locale/zh_CN/LC_MESSAGES/messages.po -l zh_CN.UTF-8
-
翻译 PO 文件,然后编译为 MO 文件:
msgfmt messages.po -o messages.mo
使用数组/JSON 文件(简单方案)
语言文件结构
// lang/en.php
return [
'welcome' => 'Welcome to our site',
'goodbye' => 'Goodbye',
'items' => 'You have {count} items',
];
// lang/zh.php
return [
'welcome' => '欢迎来到我们的网站',
'goodbye' => '再见',
'items' => '您有 {count} 个项目',
];
加载和使用
<?php
class Translator {
private $translations = [];
public function __construct($locale) {
$file = __DIR__ . "/lang/{$locale}.php";
if (file_exists($file)) {
$this->translations = require $file;
}
}
public function translate($key, $params = []) {
$text = $this->translations[$key] ?? $key;
// 替换参数
foreach ($params as $param => $value) {
$text = str_replace("{{$param}}", $value, $text);
}
return $text;
}
}
// 使用
$t = new Translator('zh');
echo $t->translate('welcome');
echo $t->translate('items', ['count' => 5]);
?>
使用国际化框架
Symfony Translation 组件
composer require symfony/translation
<?php
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\Loader\YamlFileLoader;
$translator = new Translator('zh');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', [
'hello' => '你好',
'items' => '%count% 个项目',
], 'zh');
echo $translator->trans('hello');
echo $translator->trans('items', ['%count%' => 3]);
?>
Laravel 的本地化
// resources/lang/zh/messages.php
return [
'welcome' => '欢迎',
];
// 使用
echo trans('messages.welcome');
// 或
echo __('messages.welcome');
// 带参数
echo trans('messages.welcome_user', ['name' => '张三']);
// 复数
echo trans_choice('messages.apples', 10);
自动检测语言
<?php
function detectLocale() {
// 1. 检查 session
if (isset($_SESSION['locale'])) {
return $_SESSION['locale'];
}
// 2. 检查 cookie
if (isset($_COOKIE['locale'])) {
return $_COOKIE['locale'];
}
// 3. 从浏览器头检测
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$languages = array_map('trim', explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']));
foreach ($languages as $lang) {
$lang = substr($lang, 0, 2);
if (in_array($lang, ['zh', 'en', 'ja', 'ko'])) {
return $lang;
}
}
}
// 4. 默认语言
return 'zh';
}
// 切换语言
function setLocale($locale) {
$_SESSION['locale'] = $locale;
setcookie('locale', $locale, time() + 3600 * 24 * 30);
}
?>
最佳实践建议
完整示例类
<?php
class I18n {
private static $instance = null;
private $locale = 'en';
private $translator;
private $translations = [];
private function __construct() {}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
self::$instance->init();
}
return self::$instance;
}
private function init() {
$this->locale = $this->detectLocale();
// 选择翻译方式
if (extension_loaded('gettext')) {
$this->initGettext();
} else {
$this->loadArrays();
}
}
private function detectLocale() {
// 实现语言检测逻辑
return 'zh';
}
private function initGettext() {
$locale = $this->locale . '.UTF-8';
putenv("LC_ALL=$locale");
setlocale(LC_ALL, $locale);
bindtextdomain('messages', __DIR__ . '/locale');
bind_textdomain_codeset('messages', 'UTF-8');
textdomain('messages');
}
private function loadArrays() {
$file = __DIR__ . "/lang/{$this->locale}.php";
if (file_exists($file)) {
$this->translations = require $file;
}
}
public function translate($key, $params = []) {
if (extension_loaded('gettext')) {
$text = gettext($key);
} else {
$text = $this->translations[$key] ?? $key;
}
foreach ($params as $param => $value) {
$text = str_replace("{{$param}}", $value, $text);
}
return $text;
}
public function locale() {
return $this->locale;
}
}
// 使用
I18n::getInstance()->translate('welcome');
?>
目录结构参考
project/
├── lang/
│ ├── en.php
│ ├── zh.php
│ └── ja.php
├── locale/
│ ├── en_US/
│ │ └── LC_MESSAGES/
│ │ └── messages.mo
│ └── zh_CN/
│ └── LC_MESSAGES/
│ └── messages.mo
├── scripts/
│ ├── update-po.sh
│ └── compile-mo.sh
└── src/
└── I18n.php
选择哪种方案取决于:
- 项目规模:大项目推荐 gettext 或框架方案
- 部署环境:检查 gettext 扩展是否可用
- 翻译频率:需要频繁修改时使用数组方案更方便
- 团队工作流:考虑使用 Poedit 或 Weblate 等工具
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播