]> granicus.if.org Git - icu/commitdiff
ICU-22017 Fix numbering system resolution in NumberRangeFormatter
authorShane Carr <shane@unicode.org>
Fri, 10 Jun 2022 02:19:29 +0000 (02:19 +0000)
committerFrank Yung-Fong Tang <ftang@google.com>
Wed, 15 Jun 2022 20:08:46 +0000 (13:08 -0700)
See #2085

icu4c/source/i18n/numrange_fluent.cpp
icu4c/source/i18n/numrange_impl.cpp
icu4c/source/test/intltest/numbertest.h
icu4c/source/test/intltest/numbertest_range.cpp
icu4j/main/classes/core/src/com/ibm/icu/number/NumberRangeFormatterImpl.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberRangeFormatterTest.java

index f1060b3c21d45ea9239690daaf5a42ca5f11e86b..c36defa36994d72ee156bd866ddc865c2795b39d 100644 (file)
@@ -354,6 +354,7 @@ LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const {
     // Try computing the formatter on our own
     auto* temp = new NumberRangeFormatterImpl(fMacros, status);
     if (U_FAILURE(status)) {
+        delete temp;
         return nullptr;
     }
     if (temp == nullptr) {
index 3c440c193c7bd535aa700748bfce074efd7cde6f..06efc7b2815e7afe5976744396676896a0ac0e8f 100644 (file)
@@ -130,7 +130,7 @@ NumberRangeFormatterImpl::NumberRangeFormatterImpl(const RangeMacroProps& macros
       fApproximatelyFormatter(status) {
 
     const char* nsName = formatterImpl1.getRawMicroProps().nsName;
-    if (uprv_strcmp(nsName, formatterImpl2.getRawMicroProps().nsName) != 0) {
+    if (!fSameFormatters && uprv_strcmp(nsName, formatterImpl2.getRawMicroProps().nsName) != 0) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
index c0f2e6fd58a5c33d68349343140ef26f652c9f8d..25af549eee60fffa834ad726bbafa90e12734263 100644 (file)
@@ -326,6 +326,7 @@ class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
     void test21684_Performance();
     void test21358_SignPosition();
     void test21683_StateLeak();
+    void testCreateLNRFFromNumberingSystemInSkeleton();
 
     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
 
index a47c675c97489dbde147668266e68d77ec22aa97..1364c860cf59a6f37fdb2c9476519901da6c00f4 100644 (file)
@@ -57,6 +57,7 @@ void NumberRangeFormatterTest::runIndexedTest(int32_t index, UBool exec, const c
         TESTCASE_AUTO(test21684_Performance);
         TESTCASE_AUTO(test21358_SignPosition);
         TESTCASE_AUTO(test21683_StateLeak);
+        TESTCASE_AUTO(testCreateLNRFFromNumberingSystemInSkeleton);
     TESTCASE_AUTO_END;
 }
 
@@ -1031,6 +1032,51 @@ void NumberRangeFormatterTest::test21358_SignPosition() {
     }
 }
 
+void NumberRangeFormatterTest::testCreateLNRFFromNumberingSystemInSkeleton() {
+    IcuTestErrorCode status(*this, "testCreateLNRFFromNumberingSystemInSkeleton");
+    {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter::withLocale("en")
+            .numberFormatterBoth(NumberFormatter::forSkeleton(
+                u".### rounding-mode-half-up", status));
+        UnicodeString actual = lnrf.formatFormattableRange(1, 234, status).toString(status);
+        assertEquals("default numbering system", u"1–234", actual);
+        status.errIfFailureAndReset("default numbering system");
+    }
+    {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter::withLocale("th")
+            .numberFormatterBoth(NumberFormatter::forSkeleton(
+                u".### rounding-mode-half-up numbering-system/thai", status));
+        UnicodeString actual = lnrf.formatFormattableRange(1, 234, status).toString(status);
+        assertEquals("Thai numbering system", u"๑-๒๓๔", actual);
+        status.errIfFailureAndReset("thai numbering system");
+    }
+    {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter::withLocale("en")
+            .numberFormatterBoth(NumberFormatter::forSkeleton(
+                u".### rounding-mode-half-up numbering-system/arab", status));
+        UnicodeString actual = lnrf.formatFormattableRange(1, 234, status).toString(status);
+        assertEquals("Arabic numbering system", u"١–٢٣٤", actual);
+        status.errIfFailureAndReset("arab numbering system");
+    }
+    {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter::withLocale("en")
+            .numberFormatterFirst(NumberFormatter::forSkeleton(u"numbering-system/arab", status))
+            .numberFormatterSecond(NumberFormatter::forSkeleton(u"numbering-system/arab", status));
+        UnicodeString actual = lnrf.formatFormattableRange(1, 234, status).toString(status);
+        assertEquals("Double Arabic numbering system", u"١–٢٣٤", actual);
+        status.errIfFailureAndReset("double arab numbering system");
+    }
+    {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter::withLocale("en")
+            .numberFormatterFirst(NumberFormatter::forSkeleton(u"numbering-system/arab", status))
+            .numberFormatterSecond(NumberFormatter::forSkeleton(u"numbering-system/latn", status));
+        // Note: The error is not set until `formatFormattableRange` because this is where the
+        // formatter object gets built.
+        lnrf.formatFormattableRange(1, 234, status);
+        status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
+    }
+}
+
 void NumberRangeFormatterTest::test21683_StateLeak() {
     IcuTestErrorCode status(*this, "test21683_StateLeak");
     UNumberRangeFormatter* nrf = nullptr;
index 1038959256a03241e3a543b5140f62183e40496b..6d3c0af7d444e4fa837ad2c4642eb5455965143e 100644 (file)
@@ -157,7 +157,7 @@ class NumberRangeFormatterImpl {
                 : NumberRangeFormatter.RangeIdentityFallback.APPROXIMATELY;
 
         String nsName = formatterImpl1.getRawMicroProps().nsName;
-        if (nsName == null || !nsName.equals(formatterImpl2.getRawMicroProps().nsName)) {
+        if (nsName == null || (!fSameFormatters && !nsName.equals(formatterImpl2.getRawMicroProps().nsName))) {
             throw new IllegalArgumentException("Both formatters must have same numbering system");
         }
         getNumberRangeData(macros.loc, nsName, this);
index e6e534199273ff3e6d4c06a7892f319a20910f16..5696f017eadea208d31a7c275523059f81b3dc33 100644 (file)
@@ -966,6 +966,53 @@ public class NumberRangeFormatterTest extends TestFmwk {
         }
     }
 
+    @Test
+    public void testCreateLNRFFromNumberingSystemInSkeleton() {
+        {
+            LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter
+                .withLocale(ULocale.forLanguageTag("en"))
+                .numberFormatterBoth(NumberFormatter.forSkeleton(
+                    ".### rounding-mode-half-up"));
+            String actual = lnrf.formatRange(1, 234).toString();
+            assertEquals("default numbering system", "1–234", actual);
+        }
+        {
+            LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter
+                .withLocale(ULocale.forLanguageTag("th"))
+                .numberFormatterBoth(NumberFormatter.forSkeleton(
+                    ".### rounding-mode-half-up numbering-system/thai"));
+            String actual = lnrf.formatRange(1, 234).toString();
+            assertEquals("Thai numbering system", "๑-๒๓๔", actual);
+        }
+        {
+            LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter
+                .withLocale(ULocale.forLanguageTag("en"))
+                .numberFormatterBoth(NumberFormatter.forSkeleton(
+                    ".### rounding-mode-half-up numbering-system/arab"));
+            String actual = lnrf.formatRange(1, 234).toString();
+            assertEquals("Arabic numbering system", "١–٢٣٤", actual);
+        }
+        {
+            LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter
+                .withLocale(ULocale.forLanguageTag("en"))
+                .numberFormatterFirst(NumberFormatter.forSkeleton("numbering-system/arab"))
+                .numberFormatterSecond(NumberFormatter.forSkeleton("numbering-system/arab"));
+            String actual = lnrf.formatRange(1, 234).toString();
+            assertEquals("Double Arabic numbering system", "١–٢٣٤", actual);
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateLNRFFromNumberingSystemInSkeletonError() {
+        LocalizedNumberRangeFormatter lnrf = NumberRangeFormatter
+            .withLocale(ULocale.forLanguageTag("en"))
+            .numberFormatterFirst(NumberFormatter.forSkeleton("numbering-system/arab"))
+            .numberFormatterSecond(NumberFormatter.forSkeleton("numbering-system/latn"));
+        // Note: The error is not thrown until `formatRange` because this is where the
+        // formatter object gets built.
+        lnrf.formatRange(1, 234);
+    }
+
     static void assertFormatRange(
             String message,
             UnlocalizedNumberRangeFormatter f,