PHP Internationalization and Localization
Localizing Numbers
Problem
You want to display numbers in a locale-specific format.
Solution
Use the number argument type with MessageFormatter:
$message = '{0,number} / {1,number} = {2,number}';
$args = array(5327, 98, 5327/98);
$us = new MessageFormatter('en_US',$message);
$fr = new MessageFormatter('fr_FR',$message);
print $us->format($args) . "\n";
print $fr->format($args) . "\n";
This prints:
5,327 / 98 = 54.357
5 327 / 98 = 54,357
Discussion
Notice in the output that the same message produces different output based on what locale the MessageFormatter is set to use. The characters used as the thousands separator and decimal point are locale-specific. What’s shown is the default number style output. With an additional style parameter added to the type, you can change that.
For example, there are easy shortcuts for displaying numbers as currency amounts and percentage amounts:
$message = '{0,number,currency}, {0,number,percent}';
$us = new MessageFormatter('en_US',$message);
print $us->format(array(3.33333333));
This prints:
$3.33, 333%
Instead of the shortcut words currency or percent, you can also specify a format string as understood by the ICU DecimalFormat class. Many of the characters that can go in this format string are.
Table DecimalFormat pattern characters
Character Meaning
0 Digit
1-9 Digit, with rounding
# Digit, display nothing for zero
@ Significant digit
% Percent sign, multiplies number by 100
¤ Currency symbol
¤¤ Three-letter currency abbreviation
; Separator for positive and negative patterns
______________________________________________________________________
This code runs through several of these patterns for a few different numbers:
$args = array(7,159,-0.3782,6.815574);
$messages = array("0", "00", "1", "11", "222",
"#", "##", "@", "@@@",
"##%", "¤#", "¤1.11",
"¤¤#",
"#.##;(#.## !!!)"
);
foreach ($messages as $message) {
$fmt = new MessageFormatter('en_US',"{0,number,$message}\t{1,number,
$message}\t"."{2,number,$message}\t
{3,number,$message}");
print "$message:\t" . $fmt->format($args) . "\n";
}
And this survey of patterns produces:
0: 7 1590 -0 7
00: 07 159 -00 07
1: 7 159 -0 7
11: 11 154 -00 11
222: 000 222 -000 000
#: 7 159 -0 7
##: 7 159 -0 7
@: 7 200 -0.4 7
@@@: 7.00 159 -0.378 6.82
##%: 700% 15900% -38% 682%
¤#: $7 $159 -$0 $7
¤1.11: $6.66 $158.73 -$0.00 $6.66
¤¤#: USD7 USD159 -USD0 USD7
#.##;(#.## !!!): 7 159 (0.38 !!!) 6.82
More precise control over number formatting is possible with the separate NumberFormatter class. Its constructor accepts a locale, a formatting style, and an optional pattern string. For example:
$args = array(7,159,-0.3782,6.815574);
$sci = new NumberFormatter('en_US', NumberFormatter::SCIENTIFIC);
$dur = new NumberFormatter('en_US', NumberFormatter::DURATION);
$ord = new NumberFormatter('en_US', NumberFormatter::ORDINAL);
$pat = new NumberFormatter('en_US', NumberFormatter::PATTERN_DECIMAL, '@@@@');
print $sci->format(10040) . "\n";
print $dur->format(64) . "\n";
print $ord->format(15) . "\n";
print $pat->format(1.357926) . "\n";
This prints:
1.004E4
1:04
15th
1.358
The first formatter, using the NumberFormatter::SCIENTIFIC style, turns 10040 into appropriate scientific notation: 1.004E4. The second formatter, using NumberFormatter::DURATION, turns 64 seconds into 1:04—one minute and four seconds. The third formatter, using NumberFormatter::ORDINAL, produces “15th” from 15. And the last formatter, using NumberFormatter::PATTERN_DECIMAL, makes use of the same decimal format pattern characters discussed earlier.
The possibilities listed here are only part of what NumberFormatter can do. The PHP manual page for NumberFormatter goes into great detail on additional capabilities.
No comments:
Post a Comment