本文目录导读:

在 PHP 项目中实现本地化(i18n),主要有 5 种主流方案,根据项目规模和需求选择:
gettext 扩展(最专业,适合大型项目)
这是 Linux 系统最标准的本地化方案,支持复数、上下文等复杂语法。
// 1. 初始化
putenv('LANG=zh_CN.utf8');
setlocale(LC_ALL, 'zh_CN.utf8');
bindtextdomain('messages', './locale');
textdomain('messages');
// 2. 使用
echo gettext("Hello World");
// 或短函数
echo _("Hello World");
准备翻译文件:
- 需要安装
gettext工具生成.po和.mo文件 - 结构:
./locale/zh_CN/LC_MESSAGES/messages.mo
优点:性能最好,支持复数规则
缺点:需要服务器安装 gettext 扩展,配置文件较复杂
数组/JSON 文件(最简单,适合中小项目)
最常用的轻量级方案,把翻译放在 PHP 数组或 JSON 文件中。
// lang/zh.php
return [
'welcome' => '欢迎光临',
'hello' => '你好,:name',
'items_count' => '{0} 没有项目|{1} 一个项目|[2,*] :count 个项目',
];
// 使用
$translations = require "lang/{$lang}.php";
echo $translations['welcome']; // 欢迎光临
// 动态替换
$name = 'John';
echo str_replace(':name', $name, $translations['hello']);
最优实践:封装成类
class Translator {
private $translations = [];
public function __construct($lang) {
$this->translations = require "lang/{$lang}.php";
}
public function trans($key, $params = []) {
$text = $this->translations[$key] ?? $key;
foreach ($params as $k => $v) {
$text = str_replace(":{$k}", $v, $text);
}
return $text;
}
// 支持复数
public function transChoice($key, $count, $params = []) {
$rules = explode('|', $this->translations[$key]);
// 简单的复数逻辑
$index = $count == 1 ? 1 : 2;
$text = $rules[$index] ?? $rules[0];
return str_replace(':count', $count, $text);
}
}
使用第三方库(省时省力)
Symfony Translation 组件
composer require symfony/translation
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\PhpFileLoader;
$translator = new Translator('zh_CN');
$translator->addLoader('php', new PhpFileLoader());
$translator->addResource('php', __DIR__.'/lang/zh.php', 'zh_CN');
echo $translator->trans('welcome');
echo $translator->trans('items_count', ['%count%' => 5]);
Laravel 风格的简单实现
// 使用框架的 __() 函数
__('messages.welcome');
__('messages.order_count', ['count' => 5]);
数据库存储(适合动态内容)
适合需要在线修改翻译的场景。
CREATE TABLE translations (
id INT PRIMARY KEY AUTO_INCREMENT,
key VARCHAR(255) UNIQUE,
locale VARCHAR(10),
value TEXT
);
class DBTranslator {
private $cache = [];
public function trans($key, $locale = 'zh') {
if (!isset($this->cache[$locale])) {
// 加载该语言的所有翻译到缓存
$this->cache[$locale] = $this->loadFromDB($locale);
}
return $this->cache[$locale][$key] ?? $key;
}
}
现代框架自带方案
如果你在 Laravel / Symfony 等框架中,直接使用内置功能:
Laravel 示例
// 创建语言文件
// resources/lang/zh/messages.php
// 使用
echo __('messages.welcome');
echo trans_choice('messages.items', $count);
Symfony 示例
// translations/messages.zh_CN.yaml
// 使用
echo $this->translator->trans('welcome');
实战建议
✅ 推荐组合方案:
- 小项目:使用
数组/JSON+ 封装类 - 中大型项目:
gettext或Symfony Translation组件 - 框架项目:直接用框架内置 i18n
📁 目录结构建议:
project/
├── lang/
│ ├── zh.php
│ ├── en.php
│ └── fr.php
├── locale/ # gettext 文件
│ ├── zh_CN/LC_MESSAGES/messages.mo
│ └── en_US/LC_MESSAGES/messages.mo
└── src/
└── Translator.php
🎯 最佳实践:
- 语言检测:根据
Accept-Language或用户选择 - 语言包缓存:使用 APCu/Redis 缓存翻译数据
- 翻译键规范:使用
模块.功能.具体操作格式(user.login.success) - 占位符统一:统一使用
param格式
选择适合你项目规模的方案,复杂度越高收益越大,小项目别过度设计!