为什么您的PHP网站应该使用不同语言?
\n\n想象一下:您创建了一个完美的产品——快速、便捷、能解决问题。但有一个障碍:您的界面只支持俄语。来自德国、日本或巴西的潜在客户因为看不懂按钮而直接关闭了标签页。这不仅仅是利润损失——这是整个市场的损失。
\n\n国际化(i18n——来自“internationalization”,其中i和n之间有18个字母)和本地化(l10n)不是创业公司的“勾选框”,而是一种战略工具。许多开发人员害怕这个词,认为必须重写所有代码。实际上,在PHP中组织翻译是一个优雅的过程,它使代码更清晰,业务更全球化。
\n\n在本文中,我们将探讨PHP应用程序国际化的三种实际方法:从简单的数组到强大的intl扩展和经典的gettext。您将学习如何不仅仅是翻译文本,还能正确处理日期、数字和复数形式——因为阿拉伯语、波兰语或俄语有各自的变格规则。
PHP中i18n的主要方法
\n\n在编写代码之前,需要选择架构。所有方法大致可分为三类。选择哪一种取决于项目规模和性能要求。
\n\n1. 数组和ini文件(DIY方法)
\n\n最简单的方法——将翻译存储在关联数组或.ini文件中。非常适合小型项目或MVP。
// lang/ru.php\nreturn [\n 'welcome' => '欢迎来到网站!',\n 'logout' => '退出',\n 'cart_empty' => '购物车为空'\n];\n\n// lang/en.php\nreturn [\n 'welcome' => 'Welcome to the website!',\n 'logout' => 'Logout',\n 'cart_empty' => 'Cart is empty'\n];\n\n使用起来很简单:根据用户的会话或cookie加载相应的文件。
\n\nfunction __($key) {\n static $lang = null;\n if ($lang === null) {\n $locale = $_SESSION['lang'] ?? 'ru';\n $lang = include "lang/{$locale}.php";\n }\n return $lang[$key] ?? $key;\n}\n\necho __('welcome'); // 欢迎来到网站!\n\n优点:简单,不需要扩展,易于缓存(甚至可以保存在Redis中)。
\n缺点:不支持复数形式(需要自己实现),不适合大型项目(一个文件中有成千上万个键)。
2. Gettext——经典之作
\n\nGettext是Unix世界中国际化的实际标准。在PHP中,它通过gettext扩展提供。这是一个强大的工具,用于WordPress、Drupal和Symfony。
首先创建.po文件(例如,用于俄语):
# ru_RU/LC_MESSAGES/messages.po\nmsgid "Hello, %s!"\nmsgstr "您好,%s!"\n\nmsgid "You have %d new message"\nmsgid_plural "You have %d new messages"\nmsgstr[0] "您有 %d 条新消息"\nmsgstr[1] "您有 %d 条新消息"\nmsgstr[2] "您有 %d 条新消息"\n\n然后使用msgfmt工具编译成.mo文件。在PHP代码中如下所示:
putenv('LC_ALL=ru_RU.UTF-8');\nsetlocale(LC_ALL, 'ru_RU.UTF-8');\nbindtextdomain('messages', './locale');\ntextdomain('messages');\n\necho gettext('Hello, %s!', '阿列克谢'); // 您好,阿列克谢!\n\n// 复数形式——神奇:\necho ngettext('%d message', '%d messages', 3); // 3 条消息\n\n顺便说一下,为了加快开发速度,可以使用Poedit——它会高亮显示未翻译的字符串。
\n\n3. Intl扩展(PHP 5.3+)
\n\n如果您不仅需要翻译文本,还需要根据国家标准正确格式化数字、日期或货币——请使用Intl。它是ICU(International Components for Unicode)库的扩展。
// 数字格式化