symfony/intl

PHP access to ICU library localization data — countries, languages, currencies, and timezones

Library
Composer
vv8.1.4
2,628stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
75/100Good
Development Activity72
Maintenance72
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture78
Code Quality82
Innovation55
Learning Curve80

symfony/intl is a Symfony component that provides PHP access to internationalization data derived from the ICU (International Components for Unicode) library — localized country, language, script, currency, locale, and timezone names — without requiring the native PHP intl extension to be installed. It bundles pre-compiled ICU resource-bundle data and exposes it through simple static classes like Countries, Languages, Currencies, Locales, Scripts, and Timezones.

Each class offers lookups such as Countries::getName('GB', 'en') or Currencies::getSymbol('EUR'), backed by a buffered ResourceBundle reader (Intl.php) that lazily loads and caches per-locale data. It’s a core dependency behind Symfony’s own Intl form types and validators, and is commonly pulled in by any PHP application needing localized names without depending on ICU being compiled into the PHP runtime.

What You Get

  • Static data-access classes: Countries, Languages, Scripts, Currencies, Locales, and Timezones, each with locale-aware name lookups
  • A Locale helper for locale-code parsing/canonicalization independent of the PHP intl extension
  • Pre-compiled ICU resource-bundle data bundled under Resources/data, versioned alongside each Symfony release
  • A buffered ResourceBundle/Intl core that lazily loads and caches per-locale data files to limit memory use
  • Exception types for missing locale/resource-bundle data

Common Use Cases

  • Rendering localized country or language names in a user’s selected locale for forms, dropdowns, and address displays
  • Looking up currency symbols, names, or fraction digits for price formatting without relying on the PHP intl extension
  • Populating country/language/timezone select lists in Symfony forms via the companion Symfony Form intl types
  • Building applications that must run in restricted PHP environments where the native intl extension can’t be installed

Under The Hood

Architecture - The component is organized as one PHP class per data domain (Countries.php, Currencies.php, Languages.php, Locales.php, Scripts.php, Timezones.php), each a thin static-method facade delegating to the shared Intl core (Intl.php), which defines constants for each data directory (CURRENCY_DIR, LANGUAGE_DIR, SCRIPT_DIR, etc.) and a BUFFER_SIZE of 10 resource bundles held in memory at once. ResourceBundle.php implements the actual per-locale data reader, sourcing from pre-generated PHP data files under Resources/data rather than requiring the ICU C library or PHP’s intl extension at runtime. Util/ and Exception/ hold supporting helpers and typed exceptions.

Tech Stack - Pure PHP (100%) requiring PHP >= 8.4.1, with symfony/filesystem and symfony/var-exporter as dev-only dependencies (used for regenerating the bundled data files, not for runtime consumption) and a version conflict rule against old symfony/string releases. Data is exported as plain PHP arrays via var-exporter rather than shipped as binary ICU resource bundles, trading some file size for zero-extension-dependency portability.

Code Quality - The Tests/ directory mirrors the source layout one-to-one (CountriesTest.php, CurrenciesTest.php, LanguagesTest.php, LocalesTest.php, LocaleTest.php, plus environment-variable and user-assigned-code edge-case tests), run via PHPUnit per phpunit.xml.dist. As a Symfony core component it follows Symfony’s strict backward-compatibility and deprecation policies, and is released in lockstep with the rest of the framework — visible in its parallel v5/v6/v7/v8 release trains.

API Design - Every data class exposes a small, consistent method set — getName(), getNames(), exists() — following the same shape across Countries, Languages, Scripts, and similar classes, so learning one class transfers directly to the others. Being a read-only mirror of a Symfony monorepo subtree, its README points installers to symfony/symfony for contributions, but the package itself requires zero setup beyond composer require and a locale code.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search