PHP Intl Extension
debt(d5/e3/b5/t7)
Closest to 'specialist tool catches' (d5). PHPStan and Psalm (cited in detection_hints.tools) can detect patterns like number_format() instead of NumberFormatter or sorting without Collator, but these require static analysis configuration and aren't default linter rules — they need intentional setup to catch i18n anti-patterns.
Closest to 'simple parameterised fix' (e3). The quick_fix indicates replacing native functions with Intl equivalents: number_format() → NumberFormatter, sort() → Collator::sort(), date format → IntlDateFormatter. Each is a localised swap within components handling formatting/sorting, not a one-liner but not cross-cutting either.
Closest to 'persistent productivity tax' (b5). The applies_to shows this affects all PHP contexts (web, cli), and i18n choices tend to be pervasive — once you've chosen to use native sort() and number_format() throughout, every new feature involving sorting or number display must remember to use Intl classes instead. It's not architectural but creates ongoing friction.
Closest to 'serious trap' (t7). The misconception states explicitly that PHP's native sort() appears to work but silently produces wrong results for accented characters — this contradicts expectations from ASCII-centric development where sort() 'just works'. A competent developer unfamiliar with Unicode collation will assume native functions handle strings correctly, only to discover French users see mangled alphabetical order.
Also Known As
TL;DR
Explanation
The PHP Intl extension wraps ICU (International Components for Unicode). Key classes: MessageFormatter (ICU message format with plurals, selects, number formatting), Collator (locale-aware string sorting — essential for accented characters), NumberFormatter (currency, percentage, decimal with locale-specific formatting), IntlDateFormatter (locale-aware date/time formatting), and Normalizer (Unicode normalisation — NFC, NFD, NFKC). Required for: sorting strings with accented characters correctly, formatting numbers and dates for different locales, and complex plural rules. Install: typically included with PHP; may need php-intl package.
Common Misconception
Why It Matters
Common Mistakes
- sort() for locale-aware string sorting — use Collator.
- number_format() for currency — use NumberFormatter which handles locale-specific symbols and formatting.
- DateTimeImmutable::format() for user-facing dates — use IntlDateFormatter for locale-aware output.
- Not normalising Unicode input — the same character can have multiple representations (é as one code point or e + combining accent).
Code Examples
// PHP native — locale-unaware:
sort($frenchWords); // 'é' sorts after 'z' — wrong for French
number_format(1234567.89, 2, '.', ','); // '1,234,567.89' wrong for German (needs '1.234.567,89')
echo $date->format('d/m/Y'); // UK format served to US user — ambiguous
// PHP Intl — locale-aware:
$collator = new Collator('fr_FR');
$collator->sort($frenchWords); // Correct French alphabetical order
$numFmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $numFmt->formatCurrency(1234567.89, 'EUR'); // '1.234.567,89 €'
$dateFmt = new IntlDateFormatter(
'en_US',
IntlDateFormatter::LONG,
IntlDateFormatter::NONE,
'America/New_York'
);
echo $dateFmt->format(new DateTime('2026-03-16')); // 'March 16, 2026'
// Normalize unicode:
$normalised = Normalizer::normalize($input, Normalizer::NFC);