ext/intl: Add NumberFormatter::CURRENCY_ISO, PLURAL, STANDARD and CASH_CURRENCY

ICU 54 and 56 adds the following formatters[^1] for currency formatting:

 - `CURRENCY_ISO`[^2]: ISO currency code, e.g., "USD1.00"
 - `CURRENCY_PLURAL`[^3]: pluralized currency name, e.g., "1.00 US dollar" and "3.00 US dollars"
 - `CASH_CURRENCY`[^4]: currency symbol given CASH usage, e.g., "NT$3" instead of "NT$3.23"
 - `CURRENCY_STANDARD`[^5]: currency symbol, e.g., "$1.00", using non-accounting style for negative values (e.g. minus sign)

Ref: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html

This adds support for all four of them to ext/intl, along with tests.

[^1]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html
[^2]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266daae232c48e579c727525855cd21571033
[^3]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266da3916bb92d0784396ea2331d4f04c03f5
[^4]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266da8da9eba1a27d5734599709c137c3b82f
[^5]: https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/unum_8h.html#a4eb4d3ff13bd506e7078b2be4052266dac57cfff1b245d11774e8b109b98eedc2
This commit is contained in:
Ayesh Karunaratne 2025-03-09 16:12:51 +07:00 committed by Ayesh Karunaratne
parent 2d39c7855a
commit c20b429a90
3 changed files with 224 additions and 1 deletions

View file

@ -31,8 +31,16 @@ class NumberFormatter
public const int PATTERN_RULEBASED = UNKNOWN;
/** @cvalue UNUM_IGNORE */
public const int IGNORE = UNKNOWN;
/** @cvalue UNUM_CURRENCY_ISO */
public const int CURRENCY_ISO = UNKNOWN;
/** @cvalue UNUM_CURRENCY_PLURAL */
public const int CURRENCY_PLURAL = UNKNOWN;
/** @cvalue UNUM_CURRENCY_ACCOUNTING */
public const int CURRENCY_ACCOUNTING = UNKNOWN;
/** @cvalue UNUM_CASH_CURRENCY */
public const int CASH_CURRENCY = UNKNOWN;
/** @cvalue UNUM_CURRENCY_STANDARD */
public const int CURRENCY_STANDARD = UNKNOWN;
/** @cvalue UNUM_DEFAULT */
public const int DEFAULT_STYLE = UNKNOWN;

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 05ab9fb3ba33163b2100e2773d70f67e110ecefc */
* Stub hash: d886941aa76837aed1da08845dbaff9442107203 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter___construct, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0)
@ -197,12 +197,36 @@ static zend_class_entry *register_class_NumberFormatter(void)
zend_declare_typed_class_constant(class_entry, const_IGNORE_name, &const_IGNORE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_IGNORE_name);
zval const_CURRENCY_ISO_value;
ZVAL_LONG(&const_CURRENCY_ISO_value, UNUM_CURRENCY_ISO);
zend_string *const_CURRENCY_ISO_name = zend_string_init_interned("CURRENCY_ISO", sizeof("CURRENCY_ISO") - 1, 1);
zend_declare_typed_class_constant(class_entry, const_CURRENCY_ISO_name, &const_CURRENCY_ISO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_CURRENCY_ISO_name);
zval const_CURRENCY_PLURAL_value;
ZVAL_LONG(&const_CURRENCY_PLURAL_value, UNUM_CURRENCY_PLURAL);
zend_string *const_CURRENCY_PLURAL_name = zend_string_init_interned("CURRENCY_PLURAL", sizeof("CURRENCY_PLURAL") - 1, 1);
zend_declare_typed_class_constant(class_entry, const_CURRENCY_PLURAL_name, &const_CURRENCY_PLURAL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_CURRENCY_PLURAL_name);
zval const_CURRENCY_ACCOUNTING_value;
ZVAL_LONG(&const_CURRENCY_ACCOUNTING_value, UNUM_CURRENCY_ACCOUNTING);
zend_string *const_CURRENCY_ACCOUNTING_name = zend_string_init_interned("CURRENCY_ACCOUNTING", sizeof("CURRENCY_ACCOUNTING") - 1, 1);
zend_declare_typed_class_constant(class_entry, const_CURRENCY_ACCOUNTING_name, &const_CURRENCY_ACCOUNTING_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_CURRENCY_ACCOUNTING_name);
zval const_CASH_CURRENCY_value;
ZVAL_LONG(&const_CASH_CURRENCY_value, UNUM_CASH_CURRENCY);
zend_string *const_CASH_CURRENCY_name = zend_string_init_interned("CASH_CURRENCY", sizeof("CASH_CURRENCY") - 1, 1);
zend_declare_typed_class_constant(class_entry, const_CASH_CURRENCY_name, &const_CASH_CURRENCY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_CASH_CURRENCY_name);
zval const_CURRENCY_STANDARD_value;
ZVAL_LONG(&const_CURRENCY_STANDARD_value, UNUM_CURRENCY_STANDARD);
zend_string *const_CURRENCY_STANDARD_name = zend_string_init_interned("CURRENCY_STANDARD", sizeof("CURRENCY_STANDARD") - 1, 1);
zend_declare_typed_class_constant(class_entry, const_CURRENCY_STANDARD_name, &const_CURRENCY_STANDARD_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
zend_string_release(const_CURRENCY_STANDARD_name);
zval const_DEFAULT_STYLE_value;
ZVAL_LONG(&const_DEFAULT_STYLE_value, UNUM_DEFAULT);
zend_string *const_DEFAULT_STYLE_name = zend_string_init_interned("DEFAULT_STYLE", sizeof("DEFAULT_STYLE") - 1, 1);

View file

@ -0,0 +1,191 @@
--TEST--
NumberFormatter: currency formatting
----DESCRIPTION--
Tests NumberFormatter with various currenct-related formatters.
--EXTENSIONS--
intl
--FILE--
<?php
function ut_main() {
$locales = [
'ka-GE',
'hi-IN', // No spaces between sign and the amount, crore number segmenting
'zh-TW', // TWD has fractions, but only used in electronic transactions
];
$formats = [
'CURRENCY' => NumberFormatter::CURRENCY,
'CURRENCY_ACCOUNTING' => NumberFormatter::CURRENCY_ACCOUNTING,
'CURRENCY_ISO' => NumberFormatter::CURRENCY_ISO,
'CURRENCY_PLURAL' => NumberFormatter::CURRENCY_PLURAL,
'CASH_CURRENCY' => NumberFormatter::CASH_CURRENCY,
'CURRENCY_STANDARD' => NumberFormatter::CURRENCY_STANDARD,
];
$numbers = [0, 1, 2, 123456789.42, -123456789.42, 456.789012];
$res_str = '';
foreach($locales as $locale) {
foreach ($formats as $formatLabel => $format) {
$res_str .= "$locale: $formatLabel\n";
foreach ($numbers as $number) {
$fmt = ut_nfmt_create($locale, $format);
$res_str .= "$number => " . ut_nfmt_format_currency($fmt, $number, ut_nfmt_get_symbol($fmt, NumberFormatter::INTL_CURRENCY_SYMBOL)) . "\n";
}
$res_str .= "\n";
}
}
return $res_str;
}
include_once(__DIR__ . '/../ut_common.inc');
ut_run();
?>
--EXPECT--
ka-GE: CURRENCY
0 => 0,00 
1 => 1,00 
2 => 2,00 
123456789.42 => 123 456 789,42 
-123456789.42 => -123 456 789,42 
456.789012 => 456,79 
ka-GE: CURRENCY_ACCOUNTING
0 => 0,00 
1 => 1,00 
2 => 2,00 
123456789.42 => 123 456 789,42 
-123456789.42 => -123 456 789,42 
456.789012 => 456,79 
ka-GE: CURRENCY_ISO
0 => 0,00 GEL
1 => 1,00 GEL
2 => 2,00 GEL
123456789.42 => 123 456 789,42 GEL
-123456789.42 => -123 456 789,42 GEL
456.789012 => 456,79 GEL
ka-GE: CURRENCY_PLURAL
0 => 0,00 ქართული ლარი
1 => 1,00 ქართული ლარი
2 => 2,00 ქართული ლარი
123456789.42 => 123 456 789,42 ქართული ლარი
-123456789.42 => -123 456 789,42 ქართული ლარი
456.789012 => 456,79 ქართული ლარი
ka-GE: CASH_CURRENCY
0 => 0,00 
1 => 1,00 
2 => 2,00 
123456789.42 => 123 456 789,42 
-123456789.42 => -123 456 789,42 
456.789012 => 456,79 
ka-GE: CURRENCY_STANDARD
0 => 0,00 
1 => 1,00 
2 => 2,00 
123456789.42 => 123 456 789,42 
-123456789.42 => -123 456 789,42 
456.789012 => 456,79 
hi-IN: CURRENCY
0 => ₹0.00
1 => ₹1.00
2 => ₹2.00
123456789.42 => ₹12,34,56,789.42
-123456789.42 => -₹12,34,56,789.42
456.789012 => ₹456.79
hi-IN: CURRENCY_ACCOUNTING
0 => ₹0.00
1 => ₹1.00
2 => ₹2.00
123456789.42 => ₹12,34,56,789.42
-123456789.42 => -₹12,34,56,789.42
456.789012 => ₹456.79
hi-IN: CURRENCY_ISO
0 => INR 0.00
1 => INR 1.00
2 => INR 2.00
123456789.42 => INR 12,34,56,789.42
-123456789.42 => -INR 12,34,56,789.42
456.789012 => INR 456.79
hi-IN: CURRENCY_PLURAL
0 => 0.00 भारतीय रुपया
1 => 1.00 भारतीय रुपया
2 => 2.00 भारतीय रुपए
123456789.42 => 12,34,56,789.42 भारतीय रुपए
-123456789.42 => -12,34,56,789.42 भारतीय रुपए
456.789012 => 456.79 भारतीय रुपए
hi-IN: CASH_CURRENCY
0 => ₹0.00
1 => ₹1.00
2 => ₹2.00
123456789.42 => ₹12,34,56,789.42
-123456789.42 => -₹12,34,56,789.42
456.789012 => ₹456.79
hi-IN: CURRENCY_STANDARD
0 => ₹0.00
1 => ₹1.00
2 => ₹2.00
123456789.42 => ₹12,34,56,789.42
-123456789.42 => -₹12,34,56,789.42
456.789012 => ₹456.79
zh-TW: CURRENCY
0 => $0.00
1 => $1.00
2 => $2.00
123456789.42 => $123,456,789.42
-123456789.42 => -$123,456,789.42
456.789012 => $456.79
zh-TW: CURRENCY_ACCOUNTING
0 => $0.00
1 => $1.00
2 => $2.00
123456789.42 => $123,456,789.42
-123456789.42 => ($123,456,789.42)
456.789012 => $456.79
zh-TW: CURRENCY_ISO
0 => TWD 0.00
1 => TWD 1.00
2 => TWD 2.00
123456789.42 => TWD 123,456,789.42
-123456789.42 => -TWD 123,456,789.42
456.789012 => TWD 456.79
zh-TW: CURRENCY_PLURAL
0 => 0.00 新台幣
1 => 1.00 新台幣
2 => 2.00 新台幣
123456789.42 => 123,456,789.42 新台幣
-123456789.42 => -123,456,789.42 新台幣
456.789012 => 456.79 新台幣
zh-TW: CASH_CURRENCY
0 => $0
1 => $1
2 => $2
123456789.42 => $123,456,789
-123456789.42 => -$123,456,789
456.789012 => $457
zh-TW: CURRENCY_STANDARD
0 => $0.00
1 => $1.00
2 => $2.00
123456789.42 => $123,456,789.42
-123456789.42 => -$123,456,789.42
456.789012 => $456.79