From 5d1a2fa6bdcacc450d6a9624243341c2108a7bf7 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Thu, 10 Sep 2015 05:40:20 +0000 Subject: [PATCH] ICU-11787 Add support for UNUM_CURRENCY_STANDARD and locale u-ext key -cf- (C) X-SVN-Rev: 37935 --- icu4c/source/i18n/numfmt.cpp | 15 +++++++++- icu4c/source/i18n/unicode/unum.h | 16 ++++++++-- icu4c/source/i18n/unum.cpp | 1 + icu4c/source/test/cintltst/cnumtst.c | 45 ++++++++++++++++++---------- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/icu4c/source/i18n/numfmt.cpp b/icu4c/source/i18n/numfmt.cpp index 5db52a7183..771b12a5c0 100644 --- a/icu4c/source/i18n/numfmt.cpp +++ b/icu4c/source/i18n/numfmt.cpp @@ -122,6 +122,7 @@ static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = gLastResortCurrencyPat, // UNUM_CASH_CURRENCY NULL, // UNUM_DECIMAL_COMPACT_SHORT NULL, // UNUM_DECIMAL_COMPACT_LONG + gLastResortCurrencyPat, // UNUM_CURRENCY_STANDARD }; // Keys used for accessing resource bundles @@ -150,6 +151,7 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = { "currencyFormat", // UNUM_CASH_CURRENCY NULL, // UNUM_DECIMAL_COMPACT_SHORT NULL, // UNUM_DECIMAL_COMPACT_LONG + "currencyFormat", // UNUM_CURRENCY_STANDARD }; // Static hashtable cache of NumberingSystem objects used by NumberFormat @@ -1024,8 +1026,18 @@ NumberFormat::getAvailableLocales(void) #endif /* UCONFIG_NO_SERVICE */ // ------------------------------------- +enum { kKeyValueLenMax = 32 }; + NumberFormat* NumberFormat::internalCreateInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { + if (kind == UNUM_CURRENCY) { + char cfKeyValue[kKeyValueLenMax] = {0}; + UErrorCode kvStatus = U_ZERO_ERROR; + int32_t kLen = loc.getKeywordValue("cf", cfKeyValue, kKeyValueLenMax, kvStatus); + if (U_SUCCESS(kvStatus) && kLen > 0 && uprv_strcmp(cfKeyValue,"account")==0) { + kind = UNUM_CURRENCY_ACCOUNTING; + } + } #if !UCONFIG_NO_SERVICE if (haveService()) { return (NumberFormat*)gService->get(loc, kind, status); @@ -1326,6 +1338,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, case UNUM_CURRENCY_PLURAL: case UNUM_CURRENCY_ACCOUNTING: case UNUM_CASH_CURRENCY: + case UNUM_CURRENCY_STANDARD: f = new Win32NumberFormat(desiredLocale, curr, status); if (U_SUCCESS(status)) { @@ -1410,7 +1423,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, return NULL; } if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO || style == UNUM_CURRENCY_ACCOUNTING - || style == UNUM_CASH_CURRENCY){ + || style == UNUM_CASH_CURRENCY || style == UNUM_CURRENCY_STANDARD){ const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); if(currPattern!=NULL){ pattern.setTo(currPattern, u_strlen(currPattern)); diff --git a/icu4c/source/i18n/unicode/unum.h b/icu4c/source/i18n/unicode/unum.h index a23d4818af..ca256d1c81 100644 --- a/icu4c/source/i18n/unicode/unum.h +++ b/icu4c/source/i18n/unicode/unum.h @@ -148,7 +148,11 @@ typedef enum UNumberFormatStyle { */ UNUM_DECIMAL=1, /** - * Currency format with a currency symbol, e.g., "$1.00". + * Currency format (generic). + * Defaults to UNUM_CURRENCY_STANDARD style + * (using currency symbol, e.g., "$1.00", with non-accounting + * style for negative values e.g. using minus sign). + * The specific style may be specified using the -cf- locale key. * @stable ICU 2.0 */ UNUM_CURRENCY=2, @@ -205,6 +209,7 @@ typedef enum UNumberFormatStyle { /** * Currency format for accounting, e.g., "($3.00)" for * negative currency amount instead of "-$3.00" ({@link #UNUM_CURRENCY}). + * Overrides any style specified using -cf- key in locale. * @stable ICU 53 */ UNUM_CURRENCY_ACCOUNTING=12, @@ -231,13 +236,20 @@ typedef enum UNumberFormatStyle { * @draft ICU 56 */ UNUM_DECIMAL_COMPACT_LONG=15, + /** + * Currency format with a currency symbol, e.g., "$1.00", + * using non-accounting style for negative values (e.g. minus sign). + * Overrides any style specified using -cf- key in locale. + * @draft ICU 56 + */ + UNUM_CURRENCY_STANDARD=16, #endif /* U_HIDE_DRAFT_API */ /** * One more than the highest number format style constant. * @stable ICU 4.8 */ - UNUM_FORMAT_STYLE_COUNT=16, + UNUM_FORMAT_STYLE_COUNT=17, /** * Default format diff --git a/icu4c/source/i18n/unum.cpp b/icu4c/source/i18n/unum.cpp index c5e4c03536..5941675a41 100644 --- a/icu4c/source/i18n/unum.cpp +++ b/icu4c/source/i18n/unum.cpp @@ -57,6 +57,7 @@ unum_open( UNumberFormatStyle style, case UNUM_CURRENCY_PLURAL: case UNUM_CURRENCY_ACCOUNTING: case UNUM_CASH_CURRENCY: + case UNUM_CURRENCY_STANDARD: retVal = NumberFormat::createInstance(Locale(locale), style, *status); break; diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c index 6be2a2f04d..be5a6348b4 100644 --- a/icu4c/source/test/cintltst/cnumtst.c +++ b/icu4c/source/test/cintltst/cnumtst.c @@ -2391,34 +2391,49 @@ static void TestUNumberingSystem(void) { /* plain-C version of test in numfmtst.cpp */ enum { kUBufMax = 64 }; static void TestCurrencyIsoPluralFormat(void) { - static const char* DATA[][6] = { + static const char* DATA[][8] = { // the data are: // locale, // currency amount to be formatted, // currency ISO code to be formatted, // format result using CURRENCYSTYLE, + // format result using CURRENCY_STANDARD, + // format result using CURRENCY_ACCOUNTING, // format result using ISOCURRENCYSTYLE, // format result using PLURALCURRENCYSTYLE, - {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"}, - {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"}, - {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"}, - {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00\\u7F8E\\u5143"}, - {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56\\u7F8E\\u5143"}, - // wrong ISO code {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"}, - // wrong ISO code {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"}, - {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"}, - {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"}, - {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, - {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, - {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, + // locale amount ISOcode CURRENCYSTYLE CURRENCY_STANDARD CURRENCY_ACCOUNTING ISOCURRENCYSTYLE PLURALCURRENCYSTYLE + {"en_US", "1", "USD", "$1.00", "$1.00", "$1.00", "USD1.00", "1.00 US dollars"}, + {"en_US", "1234.56", "USD", "$1,234.56", "$1,234.56", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"}, + {"en_US@cf=account", "1234.56", "USD", "$1,234.56", "$1,234.56", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"}, + {"en_US", "-1234.56", "USD", "-$1,234.56", "-$1,234.56", "($1,234.56)", "-USD1,234.56", "-1,234.56 US dollars"}, + {"en_US@cf=account", "-1234.56", "USD", "($1,234.56)", "-$1,234.56", "($1,234.56)", "-USD1,234.56", "-1,234.56 US dollars"}, + {"en_US@cf=standard", "-1234.56", "USD", "-$1,234.56", "-$1,234.56", "($1,234.56)", "-USD1,234.56", "-1,234.56 US dollars"}, + {"zh_CN", "1", "USD", "US$1.00", "US$1.00", "US$1.00", "USD1.00", "1.00\\u7F8E\\u5143"}, + {"zh_CN", "-1", "USD", "-US$1.00", "-US$1.00", "(US$1.00)", "-USD1.00", "-1.00\\u7F8E\\u5143"}, + {"zh_CN@cf=account", "-1", "USD", "(US$1.00)", "-US$1.00", "(US$1.00)", "-USD1.00", "-1.00\\u7F8E\\u5143"}, + {"zh_CN@cf=standard", "-1", "USD", "-US$1.00", "-US$1.00", "(US$1.00)", "-USD1.00", "-1.00\\u7F8E\\u5143"}, + {"zh_CN", "1234.56", "USD", "US$1,234.56", "US$1,234.56", "US$1,234.56", "USD1,234.56", "1,234.56\\u7F8E\\u5143"}, + // {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "CHY1.00", "CHY1.00", "1.00 CHY"}, // wrong ISO code + // {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"}, // wrong ISO code + {"zh_CN", "1", "CNY", "\\uFFE51.00", "\\uFFE51.00", "\\uFFE51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "\\uFFE51,234.56", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"}, + {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0\\u20BD", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E " + "\\u0440\\u0443\\u0431\\u043B\\u044F"}, + {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0\\u20BD", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E " + "\\u0440\\u0443\\u0431\\u043B\\u044F"}, + {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0\\u20BD", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E " + "\\u0440\\u0443\\u0431\\u043B\\u044F"}, // test locale without currency information - {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"}, + {"root", "-1.23", "USD", "-US$\\u00A01.23", "-US$\\u00A01.23", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"}, + {"root@cf=account", "-1.23", "USD", "-US$\\u00A01.23", "-US$\\u00A01.23", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"}, // test choice format - {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"}, + {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"}, }; static const UNumberFormatStyle currencyStyles[] = { UNUM_CURRENCY, + UNUM_CURRENCY_STANDARD, + UNUM_CURRENCY_ACCOUNTING, UNUM_CURRENCY_ISO, UNUM_CURRENCY_PLURAL };