ICU-21330 Use =0 and =1 plural forms in compact notation

See #1632
diff --git a/icu4c/source/i18n/number_compact.cpp b/icu4c/source/i18n/number_compact.cpp
index d781b6f..8f898e7 100644
--- a/icu4c/source/i18n/number_compact.cpp
+++ b/icu4c/source/i18n/number_compact.cpp
@@ -55,7 +55,7 @@
 } // namespace
 
 // NOTE: patterns and multipliers both get zero-initialized.
-CompactData::CompactData() : patterns(), multipliers(), largestMagnitude(0), isEmpty(TRUE) {
+CompactData::CompactData() : patterns(), multipliers(), largestMagnitude(0), isEmpty(true) {
 }
 
 void CompactData::populate(const Locale &locale, const char *nsName, CompactStyle compactStyle,
@@ -104,14 +104,30 @@
     return multipliers[magnitude];
 }
 
-const UChar *CompactData::getPattern(int32_t magnitude, StandardPlural::Form plural) const {
+const UChar *CompactData::getPattern(
+        int32_t magnitude,
+        const PluralRules *rules,
+        const DecimalQuantity &dq) const {
     if (magnitude < 0) {
         return nullptr;
     }
     if (magnitude > largestMagnitude) {
         magnitude = largestMagnitude;
     }
-    const UChar *patternString = patterns[getIndex(magnitude, plural)];
+    const UChar *patternString = nullptr;
+    if (dq.hasIntegerValue()) {
+        int64_t i = dq.toLong(true);
+        if (i == 0) {
+            patternString = patterns[getIndex(magnitude, StandardPlural::Form::EQ_0)];
+        } else if (i == 1) {
+            patternString = patterns[getIndex(magnitude, StandardPlural::Form::EQ_1)];
+        }
+        if (patternString != nullptr) {
+            return patternString;
+        }
+    }
+    StandardPlural::Form plural = utils::getStandardPlural(rules, dq);
+    patternString = patterns[getIndex(magnitude, plural)];
     if (patternString == nullptr && plural != StandardPlural::OTHER) {
         // Fall back to "other" plural variant
         patternString = patterns[getIndex(magnitude, StandardPlural::OTHER)];
@@ -166,12 +182,6 @@
         ResourceTable pluralVariantsTable = value.getTable(status);
         if (U_FAILURE(status)) { return; }
         for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) {
-
-            if (uprv_strcmp(key, "0") == 0 || uprv_strcmp(key, "1") == 0) {
-                // TODO(ICU-21258): Handle this case. For now, skip.
-                continue;
-            }
-
             // Skip this magnitude/plural if we already have it from a child locale.
             // Note: This also skips USE_FALLBACK entries.
             StandardPlural::Form plural = StandardPlural::fromString(key, status);
@@ -296,8 +306,7 @@
         magnitude -= multiplier;
     }
 
-    StandardPlural::Form plural = utils::getStandardPlural(rules, quantity);
-    const UChar *patternString = data.getPattern(magnitude, plural);
+    const UChar *patternString = data.getPattern(magnitude, rules, quantity);
     if (patternString == nullptr) {
         // Use the default (non-compact) modifier.
         // No need to take any action.
diff --git a/icu4c/source/i18n/number_compact.h b/icu4c/source/i18n/number_compact.h
index 199d39f..9802b9f 100644
--- a/icu4c/source/i18n/number_compact.h
+++ b/icu4c/source/i18n/number_compact.h
@@ -28,7 +28,10 @@
 
     int32_t getMultiplier(int32_t magnitude) const U_OVERRIDE;
 
-    const UChar *getPattern(int32_t magnitude, StandardPlural::Form plural) const;
+    const UChar *getPattern(
+        int32_t magnitude,
+        const PluralRules *rules,
+        const DecimalQuantity &dq) const;
 
     void getUniquePatterns(UVector &output, UErrorCode &status) const;
 
diff --git a/icu4c/source/i18n/standardplural.cpp b/icu4c/source/i18n/standardplural.cpp
index 0391034..5a6069b 100644
--- a/icu4c/source/i18n/standardplural.cpp
+++ b/icu4c/source/i18n/standardplural.cpp
@@ -23,7 +23,7 @@
 U_NAMESPACE_BEGIN
 
 static const char *gKeywords[StandardPlural::COUNT] = {
-    "zero", "one", "two", "few", "many", "other"
+    "zero", "one", "two", "few", "many", "other", "=0", "=1"
 };
 
 const char *StandardPlural::getKeyword(Form p) {
@@ -60,21 +60,55 @@
             return ZERO;
         }
         break;
+    case '=':
+        if (uprv_strcmp(keyword, "0") == 0) {
+            return EQ_0;
+        } else if (uprv_strcmp(keyword, "1") == 0) {
+            return EQ_1;
+        }
+        break;
+    // Also allow "0" and "1"
+    case '0':
+        if (*keyword == 0) {
+            return EQ_0;
+        }
+        break;
+    case '1':
+        if (*keyword == 0) {
+            return EQ_1;
+        }
+        break;
     default:
         break;
     }
     return -1;
 }
 
-static const UChar gZero[] = { 0x7A, 0x65, 0x72, 0x6F };
-static const UChar gOne[] = { 0x6F, 0x6E, 0x65 };
-static const UChar gTwo[] = { 0x74, 0x77, 0x6F };
-static const UChar gFew[] = { 0x66, 0x65, 0x77 };
-static const UChar gMany[] = { 0x6D, 0x61, 0x6E, 0x79 };
-static const UChar gOther[] = { 0x6F, 0x74, 0x68, 0x65, 0x72 };
+static const UChar gZero[] = u"zero";
+static const UChar gOne[] = u"one";
+static const UChar gTwo[] = u"two";
+static const UChar gFew[] = u"few";
+static const UChar gMany[] = u"many";
+static const UChar gOther[] = u"other";
+static const UChar gEq0[] = u"=0";
+static const UChar gEq1[] = u"=1";
 
 int32_t StandardPlural::indexOrNegativeFromString(const UnicodeString &keyword) {
     switch (keyword.length()) {
+    case 1:
+        if (keyword.charAt(0) == '0') {
+            return EQ_0;
+        } else if (keyword.charAt(0) == '1') {
+            return EQ_1;
+        }
+        break;
+    case 2:
+        if (keyword.compare(gEq0, 2) == 0) {
+            return EQ_0;
+        } else if (keyword.compare(gEq1, 2) == 0) {
+            return EQ_1;
+        }
+        break;
     case 3:
         if (keyword.compare(gOne, 3) == 0) {
             return ONE;
diff --git a/icu4c/source/i18n/standardplural.h b/icu4c/source/i18n/standardplural.h
index 33e1d60..1659306 100644
--- a/icu4c/source/i18n/standardplural.h
+++ b/icu4c/source/i18n/standardplural.h
@@ -35,6 +35,8 @@
         FEW,
         MANY,
         OTHER,
+        EQ_0,
+        EQ_1,
         COUNT
     };
 
diff --git a/icu4c/source/test/intltest/numbertest.h b/icu4c/source/test/intltest/numbertest.h
index 39e8885..49f9b12 100644
--- a/icu4c/source/test/intltest/numbertest.h
+++ b/icu4c/source/test/intltest/numbertest.h
@@ -198,6 +198,7 @@
     void testConvertToAccurateDouble();
     void testUseApproximateDoubleWhenAble();
     void testHardDoubleConversion();
+    void testFitsInLong();
     void testToDouble();
     void testMaxDigits();
     void testNickelRounding();
diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp
index 4d74a558..689af5c 100644
--- a/icu4c/source/test/intltest/numbertest_api.cpp
+++ b/icu4c/source/test/intltest/numbertest_api.cpp
@@ -498,16 +498,14 @@
             1e7,
             u"1000\u842C");
 
-    if (!logKnownIssue("21258", "StandardPlural cannot handle keywords 1, 0")) {
-        assertFormatSingle(
-                u"Compact with plural form =1 (ICU-21258)",
-                u"compact-long",
-                u"K",
-                NumberFormatter::with().notation(Notation::compactLong()),
-                Locale("fr-FR"),
-                1e3,
-                u"mille");
-    }
+    assertFormatSingle(
+            u"Compact with plural form =1 (ICU-21258)",
+            u"compact-long",
+            u"KK",
+            NumberFormatter::with().notation(Notation::compactLong()),
+            Locale("fr-FR"),
+            1e3,
+            u"mille");
 
     assertFormatSingle(
             u"Compact Infinity",
diff --git a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
index 610df96..7403dda 100644
--- a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
+++ b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
@@ -27,6 +27,7 @@
         }
         TESTCASE_AUTO(testUseApproximateDoubleWhenAble);
         TESTCASE_AUTO(testHardDoubleConversion);
+        TESTCASE_AUTO(testFitsInLong);
         TESTCASE_AUTO(testToDouble);
         TESTCASE_AUTO(testMaxDigits);
         TESTCASE_AUTO(testNickelRounding);
@@ -357,6 +358,44 @@
     }
 }
 
+void DecimalQuantityTest::testFitsInLong() {
+    IcuTestErrorCode status(*this, "testFitsInLong");
+    DecimalQuantity quantity;
+    quantity.setToInt(0);
+    assertTrue("Zero should fit", quantity.fitsInLong());
+    quantity.setToInt(42);
+    assertTrue("Small int should fit", quantity.fitsInLong());
+    quantity.setToDouble(0.1);
+    assertFalse("Fraction should not fit", quantity.fitsInLong());
+    quantity.setToDouble(42.1);
+    assertFalse("Fraction should not fit", quantity.fitsInLong());
+    quantity.setToLong(1000000);
+    assertTrue("Large low-precision int should fit", quantity.fitsInLong());
+    quantity.setToLong(1000000000000000000L);
+    assertTrue("10^19 should fit", quantity.fitsInLong());
+    quantity.setToLong(1234567890123456789L);
+    assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong());
+    quantity.setToLong(1234567890000000000L);
+    assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong());
+    quantity.setToLong(9223372026854775808L);
+    assertTrue("A number less than max long but with similar digits should fit",
+            quantity.fitsInLong());
+    quantity.setToLong(9223372036854775806L);
+    assertTrue("One less than max long should fit", quantity.fitsInLong());
+    quantity.setToLong(9223372036854775807L);
+    assertTrue("Max long should fit", quantity.fitsInLong());
+    assertEquals("Max long should equal toLong", 9223372036854775807L, quantity.toLong(false));
+    quantity.setToDecNumber("9223372036854775808", status);
+    assertFalse("One greater than max long should not fit", quantity.fitsInLong());
+    assertEquals("toLong(true) should truncate", 223372036854775808L, quantity.toLong(true));
+    quantity.setToDecNumber("9223372046854775806", status);
+    assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
+    quantity.setToDecNumber("9223372046800000000", status);
+    assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong());
+    quantity.setToDecNumber("10000000000000000000", status);
+    assertFalse("10^20 should not fit", quantity.fitsInLong());
+}
+
 void DecimalQuantityTest::testToDouble() {
     IcuTestErrorCode status(*this, "testToDouble");
     static const struct TestCase {
@@ -531,12 +570,12 @@
         {u"scientific",    0.012, u"1,2E-2",  0L, 0.012, u"0.012", -2, -2},
 
         {u"",              999.9, u"999,9",     999L,  999.9,  u"999.9", 0, 0},
-        {u"compact-long",  999.9, u"1 millier", 1000L, 1000.0, u"1000",  3, 3},
+        {u"compact-long",  999.9, u"mille",     1000L, 1000.0, u"1000",  3, 3},
         {u"compact-short", 999.9, u"1 k",       1000L, 1000.0, u"1000",  3, 3},
         {u"scientific",    999.9, u"9,999E2",   999L,  999.9,  u"999.9", 2, 2},
 
         {u"",              1000.0, u"1 000",     1000L, 1000.0, u"1000", 0, 0},
-        {u"compact-long",  1000.0, u"1 millier", 1000L, 1000.0, u"1000", 3, 3},
+        {u"compact-long",  1000.0, u"mille",     1000L, 1000.0, u"1000", 3, 3},
         {u"compact-short", 1000.0, u"1 k",       1000L, 1000.0, u"1000", 3, 3},
         {u"scientific",    1000.0, u"1E3",       1000L, 1000.0, u"1000", 3, 3},
     };
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java
index d77a7ff..ff9fc7d 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java
@@ -22,7 +22,9 @@
     TWO("two"),
     FEW("few"),
     MANY("many"),
-    OTHER("other");
+    OTHER("other"),
+    EQ_0("=0"),
+    EQ_1("=1");
 
     /**
      * Numeric index of OTHER, same as OTHER.ordinal().
@@ -60,6 +62,20 @@
      */
     public static final StandardPlural orNullFromString(CharSequence keyword) {
         switch (keyword.length()) {
+        case 1:
+            if (keyword.charAt(0) == '0') {
+                return EQ_0;
+            } else if (keyword.charAt(0) == '1') {
+                return EQ_1;
+            }
+            break;
+        case 2:
+            if ("=0".contentEquals(keyword)) {
+                return EQ_0;
+            } else if ("=1".contentEquals(keyword)) {
+                return EQ_1;
+            }
+            break;    
         case 3:
             if ("one".contentEquals(keyword)) {
                 return ONE;
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java
index b3e536a..1cc2899 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java
@@ -10,6 +10,7 @@
 import com.ibm.icu.impl.ICUResourceBundle;
 import com.ibm.icu.impl.StandardPlural;
 import com.ibm.icu.impl.UResource;
+import com.ibm.icu.text.PluralRules;
 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
 import com.ibm.icu.util.ICUException;
 import com.ibm.icu.util.ULocale;
@@ -99,10 +100,6 @@
             byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1);
             for (Map.Entry<String, String> pluralEntry : magnitudeEntry.getValue().entrySet()) {
                 String pluralString = pluralEntry.getKey().toString();
-                if ("0".equals(pluralString) || "1".equals(pluralString)) {
-                    // TODO(ICU-21258): Handle this case. For now, skip.
-                    continue;
-                }
                 StandardPlural plural = StandardPlural.fromString(pluralString);
                 String patternString = pluralEntry.getValue().toString();
                 patterns[getIndex(magnitude, plural)] = patternString;
@@ -130,14 +127,27 @@
         return multipliers[magnitude];
     }
 
-    public String getPattern(int magnitude, StandardPlural plural) {
+    public String getPattern(int magnitude, PluralRules rules, DecimalQuantity dq) {
         if (magnitude < 0) {
             return null;
         }
         if (magnitude > largestMagnitude) {
             magnitude = largestMagnitude;
         }
-        String patternString = patterns[getIndex(magnitude, plural)];
+        String patternString = null;
+        if (dq.isHasIntegerValue()) {
+            long i = dq.toLong(true);
+            if (i == 0) {
+                patternString = patterns[getIndex(magnitude, StandardPlural.EQ_0)];
+            } else if (i == 1) {
+                patternString = patterns[getIndex(magnitude, StandardPlural.EQ_1)];
+            }
+            if (patternString != null) {
+                return patternString;
+            }
+        }
+        StandardPlural plural = dq.getStandardPlural(rules);
+        patternString = patterns[getIndex(magnitude, plural)];
         if (patternString == null && plural != StandardPlural.OTHER) {
             // Fall back to "other" plural variant
             patternString = patterns[getIndex(magnitude, StandardPlural.OTHER)];
@@ -181,12 +191,6 @@
                 // Iterate over the plural variants ("one", "other", etc)
                 UResource.Table pluralVariantsTable = value.getTable();
                 for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) {
-
-                    if ("0".equals(key.toString()) || "1".equals(key.toString())) {
-                        // TODO(ICU-21258): Handle this case. For now, skip.
-                        continue;
-                    }
-
                     // Skip this magnitude/plural if we already have it from a child locale.
                     // Note: This also skips USE_FALLBACK entries.
                     StandardPlural plural = StandardPlural.fromString(key.toString());
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
index d33f407..a571b65 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java
@@ -167,6 +167,18 @@
 
     public BigDecimal toBigDecimal();
 
+    /**
+     * Returns a long approximating the decimal quantity. A long can only represent the
+     * integral part of the number.  Note: this method incorporates the value of
+     * {@code getExponent} (for cases such as compact notation) to return the proper long
+     * value represented by the result.
+     *
+     * @param truncateIfOverflow if false and the number does NOT fit, fails with an error.
+     *        See comment about call site guards in DecimalQuantity_AbstractBCD.java
+     * @return A 64-bit integer representation of the internal number.
+     */
+    public long toLong(boolean truncateIfOverflow);
+
     public void setToBigDecimal(BigDecimal input);
 
     public int maxRepresentableDigits();
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
index 2d98cc2..510177d 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
@@ -234,6 +234,11 @@
     }
 
     @Override
+    public boolean isHasIntegerValue() {
+        return scale >= 0;
+    }
+
+    @Override
     public StandardPlural getStandardPlural(PluralRules rules) {
         if (rules == null) {
             // Fail gracefully if the user didn't provide a PluralRules
@@ -603,15 +608,7 @@
         scale -= fracLength;
     }
 
-    /**
-     * Returns a long approximating the internal BCD. A long can only represent the integral part of the
-     * number.  Note: this method incorporates the value of {@code exponent}
-     * (for cases such as compact notation) to return the proper long value
-     * represented by the result.
-     *
-     * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error.
-     * @return A 64-bit integer representation of the internal BCD.
-     */
+    @Override
     public long toLong(boolean truncateIfOverflow) {
         // NOTE: Call sites should be guarded by fitsInLong(), like this:
         // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
index 3801143..0b56937 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java
@@ -138,8 +138,7 @@
                 magnitude -= multiplier;
             }
 
-            StandardPlural plural = quantity.getStandardPlural(rules);
-            String patternString = data.getPattern(magnitude, plural);
+            String patternString = data.getPattern(magnitude, rules, quantity);
             if (patternString == null) {
                 // Use the default (non-compact) modifier.
                 // No need to take any action.
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java
index 870b947..8ebc31b 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java
@@ -550,6 +550,14 @@
          */
         @Deprecated
         public boolean isInfinite();
+
+        /**
+         * Whether the number has no nonzero fraction digits.
+         * @internal CLDR
+         * @deprecated This API is ICU internal only.
+         */
+        @Deprecated
+        public boolean isHasIntegerValue();
     }
 
     /**
@@ -639,6 +647,7 @@
          * @deprecated This API is ICU internal only.
          */
         @Deprecated
+        @Override
         public boolean isHasIntegerValue() {
             return hasIntegerValue;
         }
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
index afc73dc..24aedab 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java
@@ -326,6 +326,16 @@
   }
 
   @Override
+  public long toLong(boolean truncateIfOverflow) {
+    BigDecimal temp = toBigDecimal().setScale(0, RoundingMode.FLOOR);
+    if (truncateIfOverflow) {
+      return temp.longValue();
+    } else {
+      return temp.longValueExact();
+    }
+  }
+
+  @Override
   public void setMinInteger(int minInt) {
     // Graceful failures for bogus input
     minInt = Math.max(0, minInt);
@@ -940,4 +950,9 @@
   public void adjustExponent(int delta) {
       origPrimaryScale = origPrimaryScale + delta;
   }
+
+  @Override
+  public boolean isHasIntegerValue() {
+    return scaleBigDecimal(toBigDecimal()) >= 0;
+  }
 }
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java
index ec2d598..f8d961d 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java
@@ -269,6 +269,10 @@
                 q0.toBigDecimal(),
                 q1.toBigDecimal());
 
+        assertEquals("Different long values (" + q0 + ", " + q1 + ")",
+                q0.toLong(true),
+                q1.toLong(true));
+
         q0.roundToInfinity();
         q1.roundToInfinity();
 
@@ -456,8 +460,16 @@
         assertTrue("One less than max long should fit", quantity.fitsInLong());
         quantity.setToLong(9223372036854775807L);
         assertTrue("Max long should fit", quantity.fitsInLong());
+        assertEquals("Max long should equal toLong", 9223372036854775807L, quantity.toLong(false));
         quantity.setToBigInteger(new BigInteger("9223372036854775808"));
-        assertFalse("One greater than max long long should not fit", quantity.fitsInLong());
+        assertFalse("One greater than max long should not fit", quantity.fitsInLong());
+        assertEquals("toLong(true) should truncate", 223372036854775808L, quantity.toLong(true));
+        try {
+            quantity.toLong(false);
+            fail("One greater than max long is not convertible to long");
+        } catch (ArithmeticException | AssertionError e) {
+            // expected
+        }
         quantity.setToBigInteger(new BigInteger("9223372046854775806"));
         assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
         quantity.setToBigInteger(new BigInteger("9223372046800000000"));
@@ -652,12 +664,12 @@
                 {"scientific",    0.012, "1,2E-2",  0L, 0.012, new BigDecimal("0.012"), "0.012", -2, -2},
 
                 {"",              999.9, "999,9",     999L,  999.9,  new BigDecimal("999.9"), "999.9", 0, 0},
-                {"compact-long",  999.9, "1 millier", 1000L, 1000.0, new BigDecimal("1000"),  "1000",  3, 3},
+                {"compact-long",  999.9, "mille",     1000L, 1000.0, new BigDecimal("1000"),  "1000",  3, 3},
                 {"compact-short", 999.9, "1 k",       1000L, 1000.0, new BigDecimal("1000"),  "1000",  3, 3},
                 {"scientific",    999.9, "9,999E2",   999L,  999.9,  new BigDecimal("999.9"), "999.9", 2, 2},
 
                 {"",              1000.0, "1 000",     1000L, 1000.0, new BigDecimal("1000"), "1000", 0, 0},
-                {"compact-long",  1000.0, "1 millier", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3},
+                {"compact-long",  1000.0, "mille",     1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3},
                 {"compact-short", 1000.0, "1 k",       1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3},
                 {"scientific",    1000.0, "1E3",       1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3},
         };
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
index 66a6880..cb57092 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
@@ -443,16 +443,14 @@
                 1e7,
                 "1000\u842C");
 
-        if (!logKnownIssue("21258", "StandardPlural cannot handle keywords 1, 0")) {
-            assertFormatSingle(
-                    "Compact with plural form =1 (ICU-21258)",
-                    "compact-long",
-                    "K",
-                    NumberFormatter.with().notation(Notation.compactLong()),
-                    ULocale.FRANCE,
-                    1e3,
-                    "mille");
-        }
+        assertFormatSingle(
+                "Compact with plural form =1 (ICU-21258)",
+                "compact-long",
+                "KK",
+                NumberFormatter.with().notation(Notation.compactLong()),
+                ULocale.FRANCE,
+                1e3,
+                "mille");
 
         assertFormatSingle(
                 "Compact Infinity",