]> granicus.if.org Git - icu/commitdiff
ICU-20484 Narrow currency symbol should fall back to short symbol, C and J.
authorShane Carr <shane@unicode.org>
Fri, 8 Mar 2019 08:11:11 +0000 (00:11 -0800)
committerShane F. Carr <shane@unicode.org>
Sat, 9 Mar 2019 01:06:16 +0000 (17:06 -0800)
- Includes fixes to tests.

icu4c/source/common/ucurr.cpp
icu4c/source/test/intltest/numbertest_api.cpp
icu4c/source/test/intltest/numfmtst.cpp
icu4c/source/test/intltest/numfmtst.h
icu4j/main/classes/core/src/com/ibm/icu/text/CurrencyDisplayNames.java
icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyDisplayInfoProvider.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java

index 78716013b1d7089640bc952abc7c3611cb0e3469..802eafba166f6aaf6491f14fc1f8a04dce7a9310 100644 (file)
@@ -690,7 +690,13 @@ ucurr_getName(const UChar* currency,
         key.append("/", ec2);
         key.append(buf, ec2);
         s = ures_getStringByKeyWithFallback(rb.getAlias(), key.data(), len, &ec2);
-    } else {
+        if (ec2 == U_MISSING_RESOURCE_ERROR) {
+            *ec = U_USING_FALLBACK_WARNING;
+            ec2 = U_ZERO_ERROR;
+            choice = UCURR_SYMBOL_NAME;
+        }
+    }
+    if (s == NULL) {
         ures_getByKey(rb.getAlias(), CURRENCIES, rb.getAlias(), &ec2);
         ures_getByKeyWithFallback(rb.getAlias(), buf, rb.getAlias(), &ec2);
         s = ures_getStringByIndex(rb.getAlias(), choice, len, &ec2);
index 2d925eee5be742cf9bb51e111fa0e245776596e9..f27292ff6e887d33b39a36057028b6e2d60a3b8e 100644 (file)
@@ -779,7 +779,7 @@ void NumberFormatterApiTest::unitCurrency() {
             NumberFormatter::with().unit(PTE).unitWidth(UNUM_UNIT_WIDTH_NARROW),
             Locale("pt-PT"),
             444444.55,
-            u"444,444$55 PTE");
+            u"444,444$55 \u200B");
 
     assertFormatSingle(
             u"Currency-dependent symbols (Test ISO Code)",
index 26ae4046459fa4158e860cfea09a2d6819edf43e..4625b130164910001c2e22f9ed97669ab2889f4c 100644 (file)
@@ -123,6 +123,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
   TESTCASE_AUTO(TestCases);
 
   TESTCASE_AUTO(TestCurrencyNames);
+  TESTCASE_AUTO(Test20484_NarrowSymbolFallback);
   TESTCASE_AUTO(TestCurrencyAmount);
   TESTCASE_AUTO(TestCurrencyUnit);
   TESTCASE_AUTO(TestCoverage);
@@ -2097,6 +2098,50 @@ void NumberFormatTest::TestCurrencyNames(void) {
     // TODO add more tests later
 }
 
+void NumberFormatTest::Test20484_NarrowSymbolFallback(){
+    IcuTestErrorCode status(*this, "Test20484_NarrowSymbolFallback");
+
+    struct TestCase {
+        const char* locale;
+        const char16_t* isoCode;
+        const char16_t* expectedShort;
+        const char16_t* expectedNarrow;
+        UErrorCode expectedNarrowError;
+    } cases[] = {
+        {"en-US", u"CAD", u"CA$", u"$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
+        {"en-US", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
+        {"sw-CD", u"CDF", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
+        {"en-US", u"GEL", u"GEL", u"₾", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
+        {"ka-GE", u"GEL", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
+        {"ka", u"GEL", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
+    };
+    for (const auto& cas : cases) {
+        status.setScope(cas.isoCode);
+        UBool choiceFormatIgnored;
+        int32_t lengthIgnored;
+        const UChar* actualShort = ucurr_getName(
+            cas.isoCode,
+            cas.locale,
+            UCURR_SYMBOL_NAME,
+            &choiceFormatIgnored,
+            &lengthIgnored,
+            status);
+        status.errIfFailureAndReset();
+        const UChar* actualNarrow = ucurr_getName(
+            cas.isoCode,
+            cas.locale,
+            UCURR_NARROW_SYMBOL_NAME,
+            &choiceFormatIgnored,
+            &lengthIgnored,
+            status);
+        status.expectErrorAndReset(cas.expectedNarrowError);
+        assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
+                cas.expectedShort, actualShort);
+        assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + ": " + cas.isoCode,
+                cas.expectedNarrow, actualNarrow);
+    }
+}
+
 void NumberFormatTest::TestCurrencyUnit(void){
     UErrorCode ec = U_ZERO_ERROR;
     static const UChar USD[]  = u"USD";
index 0451067eb4202326f671202af28e94b44c760026..b62cde5523f8d8dd61dbec032af56cbac6d16aa6 100644 (file)
@@ -153,6 +153,8 @@ class NumberFormatTest: public CalendarTimeZoneTest {
 
     void TestCurrencyNames(void);
 
+    void Test20484_NarrowSymbolFallback(void);
+
     void TestCurrencyAmount(void);
 
     void TestCurrencyUnit(void);
index 9bdd00dce66153414632d5e9af64553a83833509..21297aaf97ea21ad66c4fdd40e48c363d6cad164 100644 (file)
@@ -122,8 +122,8 @@ public abstract class CurrencyDisplayNames {
 
     /**
      * Returns the narrow symbol for the currency with the provided ISO code.
-     * If there is no data for narrow symbol, substitutes isoCode, or returns
-     * null if noSubstitute was set in the factory method.
+     * If there is no data for narrow symbol, substitutes the default symbol,
+     * or returns null if noSubstitute was set in the factory method.
      *
      * @param isoCode the three-letter ISO code.
      * @return the narrow symbol.
index b0fe8de769455146d182af96d0ffc8bfd1843f89..9fb70c58e0e03b9557918bac1619cb80a5d67623 100644 (file)
@@ -95,7 +95,7 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
         /**
          * Cache for symbolMap() and nameMap().
          */
-        private volatile SoftReference<ParsingData> parsingDataCache = new SoftReference<ParsingData>(null);
+        private volatile SoftReference<ParsingData> parsingDataCache = new SoftReference<>(null);
 
         /**
          * Cache for getUnitPatterns().
@@ -124,8 +124,8 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
         }
 
         static class ParsingData {
-            Map<String, String> symbolToIsoCode = new HashMap<String, String>();
-            Map<String, String> nameToIsoCode = new HashMap<String, String>();
+            Map<String, String> symbolToIsoCode = new HashMap<>();
+            Map<String, String> nameToIsoCode = new HashMap<>();
         }
 
         ////////////////////////
@@ -170,9 +170,8 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
             NarrowSymbol narrowSymbol = fetchNarrowSymbol(isoCode);
 
             // Fall back to ISO Code
-            // TODO: Should this fall back to the regular symbol instead of the ISO code?
             if (narrowSymbol.narrowSymbol == null && fallback) {
-                return isoCode;
+                return getSymbol(isoCode);
             }
             return narrowSymbol.narrowSymbol;
         }
@@ -289,7 +288,7 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
                 CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.TOP);
                 sink.parsingData = result;
                 rb.getAllItemsWithFallback("", sink);
-                parsingDataCache = new SoftReference<ParsingData>(result);
+                parsingDataCache = new SoftReference<>(result);
             }
             return result;
         }
@@ -297,7 +296,7 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
         Map<String, String> fetchUnitPatterns() {
             Map<String, String> result = unitPatternsCache;
             if (result == null) {
-                result = new HashMap<String, String>();
+                result = new HashMap<>();
                 CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCY_UNIT_PATTERNS);
                 sink.unitPatterns = result;
                 rb.getAllItemsWithFallback("CurrencyUnitPatterns", sink);
index 69f3e6b89eae9ba2eaf00d78d9a8909e1a64065c..3d655aff44fc08c9fb6c17bd611b24e8badb79e0 100644 (file)
@@ -741,7 +741,7 @@ public class NumberFormatterApiTest {
                 NumberFormatter.with().unit(PTE).unitWidth(UnitWidth.NARROW),
                 ULocale.forLanguageTag("pt-PT"),
                 444444.55,
-                "444,444$55 PTE");
+                "444,444$55 \u200B");
 
         assertFormatSingle(
                 "Currency-dependent symbols (Test)",
index 0e8de689b57843c4671b44e0f6738aa6fae7c043..7c8a3ccedc95d8530f48841bfcbf56464d00398b 100644 (file)
@@ -238,6 +238,30 @@ public class CurrencyTest extends TestFmwk {
                 USX.getName(en_US, Currency.LONG_NAME, isChoiceFormat));
     }
 
+    @Test
+    public void test20484_NarrowSymbolFallback() {
+        Object[][] cases = new Object[][] {
+            {"en-US", "CAD", "CA$", "$"},
+            {"en-US", "CDF", "CDF", "CDF"},
+            {"sw-CD", "CDF", "FC", "FC"},
+            {"en-US", "GEL", "GEL", "₾"},
+            {"ka-GE", "GEL", "₾", "₾"},
+            {"ka", "GEL", "₾", "₾"},
+        };
+        for (Object[] cas : cases) {
+            ULocale locale = new ULocale((String) cas[0]);
+            String isoCode = (String) cas[1];
+            String expectedShort = (String) cas[2];
+            String expectedNarrow = (String) cas[3];
+
+            CurrencyDisplayNames cdn = CurrencyDisplayNames.getInstance(locale);
+            assertEquals("Short symbol: " + locale + ": " + isoCode,
+                    expectedShort, cdn.getSymbol(isoCode));
+            assertEquals("Narrow symbol: " + locale + ": " + isoCode,
+                    expectedNarrow, cdn.getNarrowSymbol(isoCode));
+        }
+    }
+
     @Test
     public void testGetName_Locale_Int_String_BooleanArray() {
         Currency currency = Currency.getInstance(ULocale.CHINA);