php
56 lines · 7 steps
Locale-aware formatting with PHP's intl extension
A small class wraps PHP's intl formatters so currency and dates render correctly for one locale and timezone.
Explained by
highlit
1<?php
2
3namespace App\Support;
4
5use IntlDateFormatter;
6use NumberFormatter;
7
8final class LocaleFormatter
9{
10 private NumberFormatter $currency;
11 private IntlDateFormatter $dateTime;
12 private IntlDateFormatter $shortDate;
13
14 public function __construct(
15 private readonly string $locale,
16 private readonly string $currencyCode,
17 string $timezone = 'UTC',
18 ) {
19 $this->currency = new NumberFormatter($locale, NumberFormatter::CURRENCY);
20
21 $this->dateTime = new IntlDateFormatter(
22 $locale,
23 IntlDateFormatter::LONG,
24 IntlDateFormatter::SHORT,
25 $timezone,
26 );
27
28 $this->shortDate = new IntlDateFormatter(
29 $locale,
30 IntlDateFormatter::MEDIUM,
31 IntlDateFormatter::NONE,
32 $timezone,
33 );
34 }
35
36 public function money(float $amount): string
37 {
38 $formatted = $this->currency->formatCurrency($amount, $this->currencyCode);
39
40 if ($formatted === false) {
41 throw new \RuntimeException($this->currency->getErrorMessage());
42 }
43
44 return $formatted;
45 }
46
47 public function dateTime(\DateTimeInterface $when): string
48 {
49 return $this->dateTime->format($when);
50 }
51
52 public function date(\DateTimeInterface $when): string
53 {
54 return $this->shortDate->format($when);
55 }
56}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Building intl formatters once in the constructor avoids re-creating expensive objects on every format call.
- 2Currency and date locales belong to configuration, so injecting them keeps formatting consistent across an app.
- 3intl methods signal failure by returning false, so check the result before trusting the output.
Related explainers
php
<?php namespace App\Support;
Merging query params onto a URL in PHP
url-parsing
query-strings
immutability
Intermediate
8 steps
php
<?php class ImageUploadService {
Validating file uploads safely in PHP
file-upload
input-validation
security
Intermediate
8 steps
typescript
const DIVISIONS: { amount: number; unit: Intl.RelativeTimeFormatUnit }[] = [ { amount: 60, unit: "seconds" }, { amount: 60, unit: "minutes" }, { amount: 24, unit: "hours" },
Human-readable relative times with Intl
internationalization
date-formatting
lookup-table
Intermediate
7 steps
php
<?php namespace App\View;
Building a safe HTML escaper in PHP
security
xss
escaping
Intermediate
6 steps
php
<?php namespace App\Observers;
How Eloquent observers hook lifecycle events in Laravel
observers
lifecycle-hooks
queues
Intermediate
6 steps
php
<?php namespace App\Rules;
How a custom phone validation rule works in Laravel
validation
custom-rules
dependency
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/locale-aware-formatting-with-php-s-intl-extension-explained-php-4a2d/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.