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",