@@ -60,28 +60,171 @@ use FormatPHP\MessageCollection;
6060
6161// Translated messages in Spanish with matching IDs to what you declared.
6262$messagesInSpanish = new MessageCollection([
63- new Message('hello', '¡Hola {name}! Hoy es {ts, date, ::yyyyMMdd }.'),
63+ new Message('hello', '¡Hola {name}! Hoy es {today }.'),
6464]);
6565
6666$config = new Config(
6767 // Locale of the application (or of the user using the application).
68- locale: new Intl\Locale('es'),
68+ new Intl\Locale('es-ES '),
6969);
7070
71- $formatphp = new FormatPHP(
72- config: $config,
73- messages: $messagesInSpanish,
74- );
71+ $formatphp = new FormatPHP($config, $messagesInSpanish);
7572
7673echo $formatphp->formatMessage([
7774 'id' => 'hello',
78- 'defaultMessage' => 'Hello, {name}! Today is {ts, date, ::yyyyMMdd }.',
75+ 'defaultMessage' => 'Hello, {name}! Today is {today }.',
7976], [
8077 'name' => 'Arwen',
81- 'ts' => time(),
82- ]);
78+ 'today' => $formatphp->formatDate(time()),
79+ ]); // e.g., ¡Hola Arwen! Hoy es 31/1/22.
80+ ```
81+
82+ ### Formatting Numbers and Currency
83+
84+ You may use the methods ` formatNumber() ` and ` formatCurrency() ` for format
85+ numbers and currency, according to the locale.
86+
87+ ``` php
88+ use FormatPHP\Config;
89+ use FormatPHP\FormatPHP;
90+ use FormatPHP\Intl;
91+
92+ $config = new Config(new Intl\Locale('es-ES'));
93+ $formatphp = new FormatPHP($config);
94+
95+ $number = -12_345.678;
96+
97+ echo $formatphp->formatNumber($number); // e.g., "-12.345,678"
98+ echo $formatphp->formatCurrency($number, 'USD'); // e.g., "-12.345,68 $"
8399```
84100
101+ #### Using Intl\NumberFormatOptions with formatNumber() and formatCurrency()
102+
103+ Fine-tune number and currency formatting with ` Intl\NumberFormatOptions ` .
104+
105+ ``` php
106+ echo $formatphp->formatNumber($number, new Intl\NumberFormatOptions([
107+ 'style' => 'unit',
108+ 'unit' => 'meter',
109+ 'unitDisplay' => 'long',
110+ ])); // e.g., "-12.345,678 metros"
111+
112+ echo $formatphp->formatCurrency($number, 'USD', new Intl\NumberFormatOptions([
113+ 'currencySign' => 'accounting',
114+ 'currencyDisplay' => 'long',
115+ ])); // e.g., "-12.345,68 US$"
116+ ```
117+
118+ ` NumberFormatOptions ` accepts the following options to specify the style and
119+ type of notation desired:
120+
121+ * ` notation ` : The number formatting to use. Possible values include: ` standard ` ,
122+ ` scientific ` , ` engineering ` , and ` compact ` . The default is ` standard ` .
123+ * ` style ` : The number formatting style to use. Possible values include:
124+ ` decimal ` , ` currency ` , ` percent ` , and ` unit ` . The default is ` decimal ` when
125+ using ` formatNumber() ` . When using ` formatCurrency() ` , this value will always
126+ be ` currency ` no matter what value is set on the ` NumberFormatOptions ` instance.
127+
128+ All notations support the following properties to provide more granular control
129+ over the formatting of numbers:
130+
131+ * ` signDisplay ` : Controls when to display the sign for the number. Defaults to
132+ ` auto ` . Possible values include:
133+ * ` always ` : Always display the sign.
134+ * ` auto ` : Use the locale to determine when to display the sign.
135+ * ` exceptZero ` : Display the sign for positive and negative numbers, but never
136+ display the size for zero.
137+ * ` never ` : Never display the sign.
138+ * ` roundingMode ` : Controls rounding rules for the number. The default is
139+ ` halfEven ` . Possible values include:
140+ * ` ceil ` : All values are rounded towards positive infinity (+∞).
141+ * ` floor ` : All values are rounded towards negative infinity (-∞).
142+ * ` expand ` : All values are rounded away from zero.
143+ * ` trunc ` : All values are rounded towards zero.
144+ * ` halfCeil ` : Values exactly on the 0.5 (half) mark are rounded towards
145+ positive infinity (+∞).
146+ * ` halfFloor ` : Values exactly on the 0.5 (half) mark are rounded towards
147+ negative infinity (-∞).
148+ * ` halfExpand ` : Values exactly on the 0.5 (half) mark are rounded away from zero.
149+ * ` halfTrunc ` : Values exactly on the 0.5 (half) mark are rounded towards zero.
150+ * ` halfEven ` : Values exactly on the 0.5 (half) mark are rounded to the nearest
151+ even digit. This is often called Banker’s Rounding because it is, on average,
152+ free of bias.
153+ * ` halfOdd ` : Similar to ` halfEven ` , but rounds ties to the nearest odd number
154+ instead of even number.
155+ * ` unnecessary ` : This mode doesn't perform any rounding but will throw an
156+ exception if the value cannot be represented exactly without rounding.
157+ * ` useGrouping ` : Controls display of grouping separators, such as thousand
158+ separators or thousand/lakh/crore separators. The default is ` auto ` . Possible
159+ values include:
160+ * ` always ` : Always display grouping separators, even if the locale prefers otherwise.
161+ * ` auto ` : Use the locale's preference for grouping separators.
162+ * ` false ` : Do not display grouping separators. Please note this is a string
163+ value and not a boolean ` false ` value.
164+ * ` min2 ` : Display grouping separators when there are at least two digits in a group.
165+ * ` true ` : This is an alias for ` always ` . Please note this is a string value
166+ and not a boolean ` true ` value.
167+ * ` scale ` : A scale by which to multiply the number before formatting it. For
168+ example, a scale value of 100 will multiply the number by 100 first, then
169+ apply other formatting options.
170+ * ` minimumIntegerDigits ` : Specifies the minimum number of integer digits to use.
171+ The default is 1.
172+ * ` minimumFractionDigits ` and ` maximumFractionDigits ` : Specifies the minimum and
173+ maximum number of fraction digits to use.
174+ * ` minimumSignificantDigits ` and ` maximumSignificantDigits ` : Specifies the
175+ minimum and maximum number of significant digits to use.
176+ * ` numberingSystem ` : Specifies a [ numbering system] ( https://cldr.unicode.org/translation/core-data/numbering-systems )
177+ to use when representing numeric values. You may specify any [ numbering system
178+ defined within Unicode CLDR] ( https://github.com/unicode-org/cldr/blob/main/common/bcp47/number.xml )
179+ and bundled in the ICU library version that is available on your platform.
180+ However, numbering systems featuring algorithmic numbers do not yet work.
181+ Possible values include (but are not limited to): ` adlm ` , ` ahom ` , ` arab ` ,
182+ ` arabext ` , ` bali ` , ` beng ` , ` bhks ` , ` brah ` , ` cakm ` , ` cham ` , ` deva ` , ` fullwide ` ,
183+ ` gong ` , ` gonm ` , ` gujr ` , ` guru ` , ` hanidec ` , ` hmng ` , ` java ` , ` kali ` , ` khmr ` ,
184+ ` knda ` , ` lana ` , ` lanatham ` , ` laoo ` , ` latn ` , ` lepc ` , ` limb ` , ` mathbold ` ,
185+ ` mathdbl ` , ` mathmono ` , ` mathsanb ` , ` mathsans ` , ` mlym ` , ` modi ` , ` mong ` , ` mroo ` ,
186+ ` mtei ` , ` mymr ` , ` mymrshan ` , ` mymrtlng ` , ` newa ` , ` nkoo ` , ` olck ` , ` orya ` , ` osma ` ,
187+ ` rohg ` , ` saur ` , ` shrd ` , ` sind ` , ` sora ` , ` sund ` , ` takr ` , ` talu ` , ` tamldec ` ,
188+ ` telu ` , ` thai ` , ` tibt ` , ` tirh ` , ` vaii ` , ` wara ` , and ` wcho ` .
189+
190+ #### Formatting Fractions
191+
192+ The following properties affect the formatting of fractional digits (e.g., when
193+ using ` minimumFractionDigits ` or ` maximumFractionDigits ` ).
194+
195+ * ` trailingZeroDisplay ` : Controls the display of trailing zeros when formatting
196+ numbers. The default is ` auto ` .
197+ * ` auto ` : Keep the trailing zeros according to the rules defined in
198+ ` minimumFractionDigits ` and ` maximumFractionDigits ` .
199+ * ` stripIfInteger ` : If the formatted number is a whole integer, do not display
200+ trailing zeros.
201+ * ` roundingPriority ` : Specifies how to resolve conflicts between maximum fraction
202+ digits and maximum significant digits. The default is ` auto ` .
203+ * ` auto ` : The significant digits always win a conflict.
204+ * ` morePrecision ` : The result with more precision wins the conflict.
205+ * ` lessPrecision ` : The result with less precision wins the conflict.
206+
207+ #### Formatting Currency
208+
209+ When formatting currency, you may use the following properties.
210+
211+ * ` currencySign ` : In accounting, many locales format negative currency values
212+ using parentheses rather than the minus sign. You may enable this behavior by
213+ setting this property to ` accounting ` . The default value is ` standard ` .
214+ * ` currencyDisplay ` : How to display the currency. Possible values include:
215+ * ` symbol ` : Use a localized currency symbol when formatting the currency. This
216+ is the default.
217+ * ` narrowSymbol ` : Use a narrow format for the currency symbol. For example, in
218+ some locales (e.g., en-GB), USD currency will default to display as "US$100."
219+ When using ` narrowSymbol ` , it will display as "$100."
220+ * ` code ` : Use the ISO currency code when formatting currency (e.g., "USD 100").
221+ * ` name ` : Use a localized name for the currency (e.g., "100 US dollars").
222+
223+ #### Compact Notation
224+
225+ If ` notation ` is ` compact ` , then you may specify the ` compactDisplay ` property
226+ with the value ` short ` or ` long ` . The default is ` short ` .
227+
85228### Formatting Dates and Times
86229
87230You may use the methods ` formatDate() ` and ` formatTime() ` to format dates and
@@ -92,13 +235,13 @@ use FormatPHP\Config;
92235use FormatPHP\FormatPHP;
93236use FormatPHP\Intl;
94237
95- $config = new Config(new Intl\Locale('es'));
238+ $config = new Config(new Intl\Locale('es-ES '));
96239$formatphp = new FormatPHP($config);
97240
98241$date = new DateTimeImmutable();
99242
100- echo $formatphp->formatDate($date); // e.g. "21 /1/22"
101- echo $formatphp->formatTime($date); // e.g. "16:58"
243+ echo $formatphp->formatDate($date); // e.g., "31 /1/22"
244+ echo $formatphp->formatTime($date); // e.g., "16:58"
102245```
103246
104247#### Using Intl\DateTimeFormatOptions with formatDate() and formatTime()
@@ -107,11 +250,12 @@ Fine-tune date and time formatting with `Intl\DateTimeFormatOptions`.
107250
108251``` php
109252echo $formatphp->formatDate($date, new Intl\DateTimeFormatOptions([
110- 'dateStyle' => 'medium',
111- ])); // e.g. "21 ene 2022"
253+ 'dateStyle' => 'medium',
254+ ])); // e.g., "31 ene 2022"
255+
112256echo $formatphp->formatTime($date, new Intl\DateTimeFormatOptions([
113- 'timeStyle' => 'long',
114- ])); // e.g. "16:58:31 UTC"
257+ 'timeStyle' => 'long',
258+ ])); // e.g., "16:58:31 UTC"
115259```
116260
117261` DateTimeFormatOptions ` accepts the following general options for formatting
@@ -193,15 +337,20 @@ be broken up into chunks. These are not HTML or XML tags, and attributes are
193337not supported.
194338
195339``` php
196- $formatphp->formatMessage([
340+ echo $formatphp->formatMessage([
197341 'id' => 'priceMessage',
198342 'defaultMessage' => <<<'EOD'
199- Our price is <boldThis >{price, number, ::currency/USD precision-integer }</boldThis >
200- with <link >{pct, number, ::percent } discount</link >
343+ Our price is <boldThis >{price}</boldThis >
344+ with <link >{discount } discount</link >
201345 EOD,
202346], [
203- 'price' => 29.99,
204- 'pct' => 2.5,
347+ 'price' => $formatphp->formatCurrency(29.99, 'USD', new Intl\NumberFormatOptions([
348+ 'maximumFractionDigits' => 0,
349+ ])),
350+ 'discount' => $formatphp->formatNumber(.025, new Intl\NumberFormatOptions([
351+ 'style' => 'percent',
352+ 'minimumFractionDigits' => 1,
353+ ])),
205354 'boldThis' => fn ($text) => "<strong >$text</strong >",
206355 'link' => fn ($text) => "<a href =\ " /discounts/1234\" >$text</a >",
207356]);
@@ -216,8 +365,9 @@ of tag names to rich text formatting functions, when configuring FormatPHP.
216365
217366``` php
218367$config = new Config(
219- locale: new Intl\Locale('en-US'),
220- defaultRichTextElements: [
368+ new Intl\Locale('en-US'),
369+ null,
370+ [
221371 'em' => fn ($text) => "<em class =\ " myClass\" >$text</em >",
222372 'strong' => fn ($text) => "<strong class =\ " myClass\" >$text</strong >",
223373 ],
@@ -249,9 +399,9 @@ use FormatPHP\MessageLoader;
249399
250400$messageLoader = new MessageLoader(
251401 // The path to your locale JSON files (i.e., en.json, es.json, etc.).
252- messagesDirectory: '/path/to/app/locales',
402+ '/path/to/app/locales',
253403 // The configuration object created earlier.
254- config: $config,
404+ $config,
255405);
256406
257407$messagesInSpanish = $messageLoader->loadMessages();
@@ -264,7 +414,7 @@ contents:
264414``` json
265415{
266416 "hello" : {
267- "defaultMessage" : " Hello, {name}! Today is {ts, date, ::yyyyMMdd }."
417+ "defaultMessage" : " Hello, {name}! Today is {today }."
268418 }
269419}
270420```
@@ -274,7 +424,7 @@ and an `es.json` file with these contents:
274424``` json
275425{
276426 "hello" : {
277- "defaultMessage" : " ¡Hola {name}! Hoy es {ts, date, ::yyyyMMdd }."
427+ "defaultMessage" : " ¡Hola {name}! Hoy es {today }."
278428 }
279429}
280430```
@@ -380,7 +530,7 @@ particular TMS.
380530| [ SimpleLocalize] ( https://simplelocalize.io/docs/integrations/format-js-cli/ ) | ` simple ` |
381531| [ Smartling ICU JSON] ( https://help.smartling.com/hc/en-us/articles/360008000733-JSON ) | ` smartling ` |
382532
383- Our default formatter is ` formatphp ` , which mirrors the output of default
533+ Our default formatter is ` formatphp ` , which mirrors the output of the default
384534formatter for FormatJS.
385535
386536### Custom Formatters
@@ -431,11 +581,11 @@ To use a custom reader with the message loader:
431581``` php
432582$messageLoader = new MessageLoader(
433583 // The path to your locale JSON files (i.e., en.json, es.json, etc.).
434- messagesDirectory: '/path/to/app/locales',
584+ '/path/to/app/locales',
435585 // The configuration object created earlier.
436- config: $config,
586+ $config,
437587 // Pass your custom reader through the formatReader parameter.
438- formatReader: MyCustomReader::class,
588+ MyCustomReader::class,
439589);
440590```
441591
0 commit comments