symfony/intl
Symfony Intl component provides access to ICU localization data in PHP: locales, languages, scripts, regions, currencies, and more. Includes tooling to compress bundled data (with zlib) for smaller installs and faster lookups.
Installation:
composer require symfony/intl
Ensure your PHP environment has the ICU extension (php-intl) installed and enabled.
First Use Case: Localize a string with pluralization (e.g., for translations):
use Symfony\Component\Intl\Intl;
$count = 5;
$message = Intl::select(
'The user has {0, plural, one {# message} other {# messages}}.',
$count,
['#' => $count]
);
// Output: "The user has 5 messages."
Where to Look First:
Symfony\Component\Intl\Intl (main class for static utility methods).Symfony\Component\Intl\Locale (for locale-specific operations).Locale Handling:
use Symfony\Component\Intl\Locale;
$locale = Locale::getDefault(); // e.g., 'en_US'
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']); // Parse Accept-Language header
if (Locale::hasLocale($locale)) {
// Proceed with localization
}
Number/Date Formatting:
$formatter = new \NumberFormatter($locale, \NumberFormatter::DECIMAL);
echo $formatter->format(1234.56); // e.g., "1,234.56" (en_US) or "1.234,56" (de_DE)
$date = new \DateTime('2023-12-25');
$formatter = new \IntlDateFormatter(
$locale,
\IntlDateFormatter::LONG,
\IntlDateFormatter::LONG
);
echo $formatter->format($date); // e.g., "December 25, 2023" (en_US)
Pluralization and Gender Rules:
$gender = 'male';
$message = Intl::select(
'{gender, select,
male {Hello, Sir!}
female {Hello, Ma’am!}
other {Hello, Guest!}
}',
['gender' => $gender]
);
Collation (Sorting):
$collator = new \Collator($locale);
$collator->sort($strings); // Array of strings sorted by locale
Integration with Laravel:
Intl utilities to the container:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(\Symfony\Component\Intl\Intl::class);
}
// app/Http/Middleware/SetLocale.php
public function handle($request, Closure $next)
{
$locale = Locale::acceptFromHttp($request->header('Accept-Language'));
app()->setLocale($locale);
return $next($request);
}
ICU Extension Dependency:
php-intl extension. Verify it’s enabled:
php -m | grep intl
pecl install intl
or use a system package manager (e.g., apt-get install php-intl on Ubuntu).Locale Data Compression:
php vendor/symfony/intl/Resources/bin/compress
Performance with Large Datasets:
$formatter = new \NumberFormatter($locale); // Reuse this
foreach ($numbers as $number) {
echo $formatter->format($number);
}
Edge Cases in Pluralization:
$count = 11; // Edge case for some locales
$message = Intl::select('{0, plural, one {#} other {#}}', $count);
Time Zone Handling:
IntlDateFormatter uses the system’s default time zone. Explicitly set it if needed:
$formatter = new \IntlDateFormatter(
$locale,
\IntlDateFormatter::LONG,
\IntlDateFormatter::LONG,
'America/New_York',
\DateTimeZone::PERIOD1,
'en_US'
);
Validate Locales:
Locale::getDisplayName() to debug locale names:
echo Locale::getDisplayName('en_US', 'en_US'); // "English (United States)"
if (!Locale::hasLocale('invalid_locale')) {
throw new \InvalidArgumentException('Invalid locale');
}
Log ICU Errors:
try {
$formatter->format($date);
} catch (\IntlException $e) {
Log::error('ICU Error: ' . $e->getMessage());
}
Fallback Locales:
$locales = ['en_US', 'en', 'en_GB']; // Fallback chain
$locale = Locale::acceptFromHttp($request->header('Accept-Language'), $locales);
Custom ICU Data:
Resources/stubs directory with your own compiled data.Event Listeners for Locale Changes:
// app/Providers/EventServiceProvider.php
public function boot()
{
event(new \Illuminate\Auth\Events\LoggedIn($user));
}
Then handle it in a listener to update the locale.Hybrid Formatting:
// app/Helpers/IntlHelper.php
function pluralize($count, $singular, $plural)
{
return Intl::select(
'{0, plural, one {' . $singular . '} other {' . $plural . '}}',
$count
);
}
Use in Blade:
{{ pluralize($count, 'Item', 'Items') }}
Testing:
Intl for unit tests:
$this->partialMock(Intl::class, ['select'])
->expects('select')
->with('...', $count)
->willReturn('Mocked result');
How can I help you explore Laravel packages today?