Skip to content

intl 扩展

PHP 的 intl 扩展基于 ICU(International Components for Unicode)库,提供了强大的国际化(i18n)和本地化(l10n)功能。包括数字格式化、货币转换、日期时间本地化、消息格式化和文本排序等。

前置知识

阅读本节前,建议先了解:DateTime 类字符串处理

基础概念

安装

bash
# 编译安装
./configure --enable-intl

# Ubuntu/Debian
sudo apt-get install php-intl

# 需要安装 ICU 库
sudo apt-get install libicu-dev

数字格式化

NumberFormatter

php
<?php
declare(strict_types=1);

use NumberFormatter;

// 创建格式化器
$fmt = new NumberFormatter('zh_CN', NumberFormatter::DECIMAL);
echo $fmt->format(1234567.89) . PHP_EOL; // 1,234,567.89

$fmt = new NumberFormatter('en_US', NumberFormatter::DECIMAL);
echo $fmt->format(1234567.89) . PHP_EOL; // 1,234,567.89

$fmt = new NumberFormatter('de_DE', NumberFormatter::DECIMAL);
echo $fmt->format(1234567.89) . PHP_EOL; // 1.234.567,89

// 解析数字
$fmt = new NumberFormatter('en_US', NumberFormatter::DECIMAL);
echo $fmt->parse('1,234,567.89') . PHP_EOL; // 1234567.89

// 百分比
$pct = new NumberFormatter('en_US', NumberFormatter::PERCENT);
echo $pct->format(0.75) . PHP_EOL; // 75%

// 货币格式化
$curr = new NumberFormatter('zh_CN', NumberFormatter::CURRENCY);
echo $curr->format(1234.56) . PHP_EOL; // ¥1,234.56

$curr = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $curr->format(1234.56) . PHP_EOL; // $1,234.56

$curr = new NumberFormatter('ja_JP', NumberFormatter::CURRENCY);
echo $curr->format(1234.56) . PHP_EOL; // ¥1,235

// 指定货币符号
$curr = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$curr->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'EUR');
echo $curr->format(1234.56) . PHP_EOL; // EUR1,234.56

日期时间本地化

IntlDateFormatter

php
<?php
declare(strict_types=1);

use IntlDateFormatter;

$dt = new DateTimeImmutable('2024-01-15 14:30:00');

// 不同locale的日期格式
$locales = ['zh_CN', 'en_US', 'ja_JP', 'fr_FR', 'de_DE'];

foreach ($locales as $locale) {
    $fmt = new IntlDateFormatter(
        $locale,
        IntlDateFormatter::FULL,
        IntlDateFormatter::SHORT
    );
    echo "{$locale}: " . $fmt->format($dt) . PHP_EOL;
}
// zh_CN: 2024年1月15日星期一下午2:30
// en_US: Monday, January 15, 2024 at 2:30 PM
// ja_JP: 2024年1月15日(月曜日) 14:30

// 日期格式类型
// IntlDateFormatter::NONE    - 不显示
// IntlDateFormatter::FULL    - 完整
// IntlDateFormatter::LONG    - 长
// IntlDateFormatter::MEDIUM  - 中
// IntlDateFormatter::SHORT   - 短

// 自定义模式
$fmt = new IntlDateFormatter('zh_CN', IntlDateFormatter::FULL, IntlDateFormatter::FULL);
echo $fmt->format($dt) . PHP_EOL;

// 解析日期字符串
$fmt = new IntlDateFormatter('zh_CN', IntlDateFormatter::FULL, IntlDateFormatter::FULL);
$parsed = $fmt->parse('2024年1月15日星期一下午2时30分00秒');
echo "解析结果: " . $parsed->format('Y-m-d H:i:s') . PHP_EOL;

消息格式化

MessageFormatter

php
<?php
declare(strict_types=1);

use MessageFormatter;

// 简单替换
$fmt = new MessageFormatter('zh_CN', '你好,{0}!欢迎来到{1}。');
echo $fmt->format(['张三', 'PHP 世界']) . PHP_EOL;
// 你好,张三!欢迎来到 PHP 世界。

// 复数形式
$fmt = new MessageFormatter('en_US', '{0, plural, =0 {no items} =1 {one item} other {# items}}');
echo $fmt->format([0]) . PHP_EOL; // no items
echo $fmt->format([1]) . PHP_EOL; // one item
echo $fmt->format([5]) . PHP_EOL; // 5 items

// 选择形式
$fmt = new MessageFormatter('en_US', '{gender, select, female {She} male {He} other {They}} likes this.');
echo $fmt->format(['gender' => 'female']) . PHP_EOL; // She likes this.
echo $fmt->format(['gender' => 'male']) . PHP_EOL;   // He likes this.

文本排序

Collator

php
<?php
declare(strict_types=1);

use Collator;

$words = ['北京', '上海', '广州', '深圳', '杭州', '南京'];

// 中文排序
$collator = new Collator('zh_CN');
$collator->asort($words);
print_r($words);

// 英文排序
$english = ['banana', 'Apple', 'cherry', 'avocado'];
$collator = new Collator('en_US');
$collator->asort($english);
print_r($english);

注意事项

  • intl 扩展依赖 ICU 库版本
  • locale 标识符格式为 语言_地区(如 zh_CN
  • MessageFormatter 使用 ICU MessageFormat 语法

下一节

继续学习:iconv 字符编码转换

参考链接