为什么PHP国际化不仅仅是“翻译单词”
想象一下:您编写了一个很棒的PHP项目。它运行良好,让用户满意,并带来利润。但有一天,您在统计数据中发现,30%的流量来自德国,15%来自日本,10%来自阿联酋。而您的网站只支持俄语。用户因为找不到自己语言的“购买”按钮而离开。
熟悉这种情况吗?PHP应用程序的国际化(i18n)不仅仅是替换模板中的单词。它是一种架构方法,使您的代码能够“理解”文化、货币、日期甚至文本方向(从左到右或从右到左)。
在本文中,我们将探讨如何使用原生工具和最佳实践将普通的PHP网站转变为多语言平台。您将了解PHP中的gettext如何工作,本地化与国际化的区别,以及如何避免在复数形式处理上犯错。
i18n 与 l10n:区别何在(以及为何重要)
在编写代码之前,让我们先统一术语。国际化(i18n)是为翻译准备代码:提取字符串,处理数字、日期、货币的格式。本地化(l10n)是翻译本身以及针对特定区域进行适配的过程。
一个简单的类比:国际化就像建造一栋带有空房间的房子,可以放置任何家具。本地化则是根据特定住户的品味来摆放家具。
对于PHP开发者来说,这意味着:不要硬编码字符串!永远不要。即使网站目前只有俄语版本。每个短语都应该被包裹在翻译函数中。
PHP i18n 的技术栈
在PHP生态系统中,有几种强大的工具。我们将讨论两种主要方法:经典的gettext和通过intl扩展实现的现代ICU MessageFormat。
1. Gettext — 多语言的老前辈
PHP中的Gettext是许多CMS(WordPress、Drupal)的事实标准。它使用.po和.mo文件来存储翻译。优点:简单、支持复数形式、与Poedit集成。
2. ICU MessageFormat — 用于复杂逻辑
PHP intl(国际化)扩展提供了MessageFormatter和NumberFormatter类。这是需要处理复杂模板(包括格、性和数的选择)的项目的选择。
3. 封装库
- symfony/translation — Symfony组件,支持YAML/XLIFF和gettext。
- laravel-localization — 用于Laravel(mcamara/laravel-localization包)。
- zend-i18n — 用于Laminas(原Zend Framework)。
实践:从零开始在PHP中配置gettext
假设我们有一个简单的脚本index.php,用于输出问候语。让我们让它支持多语言。
步骤 1. 准备代码
将所有字符串包裹在_()函数中(gettext()的别名):
<?php// index.phpecho _("欢迎来到我们的网站!");
$items = 5;// 对于复数形式,使用 ngettextecho ngettext("%d 件商品", "%d 件商品", $items);?>步骤 2. 生成 .pot 文件
在服务器上安装gettext或使用xgettext:
xgettext -o locales/messages.pot index.php --from-code=UTF-8步骤 3. 创建翻译
将messages.pot复制到locales/zh_CN/LC_MESSAGES/messages.po并进行编辑:
msgid "欢迎来到我们的网站!"msgstr "Welcome to our site!"
msgid "%d 件商品"msgid_plural "%d 件商品"msgstr[0] "%d item"msgstr[1] "%d items"