mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 17:01:16 +00:00
ICU-22378 Fix temperature format ignoring -u-mu-fahrenhe
This commit is contained in:
parent
6c05042cbc
commit
0e4b10b112
5 changed files with 131 additions and 4 deletions
|
@ -409,14 +409,19 @@ MaybeStackVector<UnitPreference>
|
|||
MaybeStackVector<UnitPreference> result;
|
||||
|
||||
// TODO: remove this once all the categories are allowed.
|
||||
// WARNING: when this is removed please make sure to keep the "fahrenhe" => "fahrenheit" mapping
|
||||
UErrorCode internalMuStatus = U_ZERO_ERROR;
|
||||
if (category.compare("temperature") == 0) {
|
||||
CharString localeUnitCharString = getKeyWordValue(locale, "mu", internalMuStatus);
|
||||
if (U_SUCCESS(internalMuStatus)) {
|
||||
// The value for -u-mu- is `fahrenhe`, but CLDR and everything else uses `fahrenheit`
|
||||
if (localeUnitCharString == "fahrenhe") {
|
||||
localeUnitCharString = CharString("fahrenheit", status);
|
||||
}
|
||||
// TODO: use the unit category as Java especially when all the categories are allowed..
|
||||
if (localeUnitCharString == "celsius" //
|
||||
|| localeUnitCharString == "fahrenheit" //
|
||||
|| localeUnitCharString == "kelvin" //
|
||||
if (localeUnitCharString == "celsius"
|
||||
|| localeUnitCharString == "fahrenheit"
|
||||
|| localeUnitCharString == "kelvin"
|
||||
) {
|
||||
UnitPreference unitPref;
|
||||
unitPref.unit.append(localeUnitCharString, status);
|
||||
|
|
|
@ -103,6 +103,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
|
|||
void toDecimalNumber();
|
||||
void microPropsInternals();
|
||||
void formatUnitsAliases();
|
||||
void testIssue22378();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
|
|||
TESTCASE_AUTO(toDecimalNumber);
|
||||
TESTCASE_AUTO(microPropsInternals);
|
||||
TESTCASE_AUTO(formatUnitsAliases);
|
||||
TESTCASE_AUTO(testIssue22378);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
|
@ -6051,6 +6052,63 @@ void NumberFormatterApiTest::formatUnitsAliases() {
|
|||
}
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::testIssue22378() {
|
||||
IcuTestErrorCode status(*this, "testIssue22378");
|
||||
|
||||
// I checked the results before the fix and everything works the same except
|
||||
// "fr-FR-u-mu-fahrenhe" and "fr_FR@mu=fahrenhe"
|
||||
struct TestCase {
|
||||
const std::string localeId;
|
||||
const UnicodeString expectedFormat;
|
||||
} testCases[]{
|
||||
{"en-US", u"73\u00B0F"},
|
||||
{"en-US-u-mu-fahrenhe", u"73\u00B0F"},
|
||||
// Unlike ULocale, forLanguageTag fails wih U_ILLEGAL_ARGUMENT_ERROR
|
||||
// because fahrenheit is not valid value for -u-mu-
|
||||
// {"en-US-u-mu-fahrenheit", u"73\u00B0F"},
|
||||
{"en-US-u-mu-celsius", u"23\u00B0C"},
|
||||
{"en-US-u-mu-badvalue", u"73\u00B0F"},
|
||||
{"en_US@mu=fahrenhe", u"73\u00B0F"},
|
||||
{"en_US@mu=fahrenheit", u"73\u00B0F"},
|
||||
{"en_US@mu=celsius", u"23\u00B0C"},
|
||||
{"en_US@mu=badvalue", u"73\u00B0F"},
|
||||
|
||||
{"fr-FR", u"23\u202F\u00B0C"},
|
||||
{"fr-FR-u-mu-fahrenhe", u"73\u202F\u00B0F"},
|
||||
// Unlike ULocale, forLanguageTag fails wih U_ILLEGAL_ARGUMENT_ERROR
|
||||
// because fahrenheit is not valid value for -u-mu-
|
||||
// {"fr-FR-u-mu-fahrenheit", u"23\u202F\u00B0C"},
|
||||
{"fr-FR-u-mu-celsius", u"23\u202F\u00B0C"},
|
||||
{"fr-FR-u-mu-badvalue", u"23\u202F\u00B0C"},
|
||||
{"fr_FR@mu=fahrenhe", u"73\u202F\u00B0F"},
|
||||
{"fr_FR@mu=fahrenheit", u"73\u202F\u00B0F"},
|
||||
{"fr_FR@mu=celsius", u"23\u202F\u00B0C"},
|
||||
{"fr_FR@mu=badvalue", u"23\u202F\u00B0C"},
|
||||
};
|
||||
|
||||
UnlocalizedNumberFormatter formatter = NumberFormatter::with()
|
||||
.usage("weather")
|
||||
.unit(MeasureUnit::getCelsius());
|
||||
double value = 23.0;
|
||||
|
||||
for (const auto &testCase : testCases) {
|
||||
std::string localeId = testCase.localeId;
|
||||
const Locale locale = (localeId.find("@") != std::string::npos)
|
||||
? Locale(localeId.c_str())
|
||||
: Locale::forLanguageTag(localeId, status);
|
||||
UnicodeString actualFormat = formatter.locale(locale)
|
||||
.formatDouble(value, status)
|
||||
.toString(status);
|
||||
assertEquals(u"-u-mu- honored (" + UnicodeString(localeId.c_str()) + u")",
|
||||
testCase.expectedFormat, actualFormat);
|
||||
}
|
||||
|
||||
UnicodeString result = formatter.locale("en-US").formatDouble(value, status).getOutputUnit(status).getIdentifier();
|
||||
assertEquals("Testing default -u-mu- for en-US", MeasureUnit::getFahrenheit().getIdentifier(), result);
|
||||
result = formatter.locale("fr-FR").formatDouble(value, status).getOutputUnit(status).getIdentifier();
|
||||
assertEquals("Testing default -u-mu- for fr-FR", MeasureUnit::getCelsius().getIdentifier(), result);
|
||||
}
|
||||
|
||||
/* For skeleton comparisons: this checks the toSkeleton output for `f` and for
|
||||
* `conciseSkeleton` against the normalized version of `uskeleton` - this does
|
||||
* not round-trip uskeleton itself.
|
||||
|
|
|
@ -72,8 +72,13 @@ public class UnitPreferences {
|
|||
|
||||
public UnitPreference[] getPreferencesFor(String category, String usage, ULocale locale, UnitsData data) {
|
||||
// TODO: remove this condition when all the categories are allowed.
|
||||
if (category.equals("temperature")) {
|
||||
// WARNING: when this is removed please make sure to keep the "fahrenhe" => "fahrenheit" mapping
|
||||
if ("temperature".equals(category)) {
|
||||
String localeUnit = locale.getKeywordValue("mu");
|
||||
// The value for -u-mu- is `fahrenhe`, but CLDR and everything else uses `fahrenheit`
|
||||
if ("fahrenhe".equals(localeUnit)) {
|
||||
localeUnit = "fahrenheit";
|
||||
}
|
||||
String localeUnitCategory;
|
||||
try {
|
||||
localeUnitCategory = localeUnit == null ? null : data.getCategory(MeasureUnitImpl.forIdentifier(localeUnit));
|
||||
|
|
|
@ -5995,6 +5995,64 @@ public class NumberFormatterApiTest extends TestFmwk {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue22378() {
|
||||
class TestCase {
|
||||
final String localeId;
|
||||
final String expectedFormat;
|
||||
|
||||
TestCase(String localeId, String expectedFormat) {
|
||||
this.localeId = localeId;
|
||||
this.expectedFormat = expectedFormat;
|
||||
}
|
||||
}
|
||||
|
||||
// I checked the results before the fix and everything works the same except
|
||||
// "fr-FR-u-mu-fahrenhe" and "fr_FR@mu=fahrenhe"
|
||||
final TestCase [] testCases = {
|
||||
new TestCase("en-US", "73\u00B0F"),
|
||||
new TestCase("en-US-u-mu-fahrenhe", "73\u00B0F"),
|
||||
// WAI. "fahrenheit" is an invalid -u-mu- value, we get the default for en-US
|
||||
new TestCase("en-US-u-mu-fahrenheit", "73\u00B0F"),
|
||||
new TestCase("en-US-u-mu-celsius", "23\u00B0C"),
|
||||
new TestCase("en-US-u-mu-badvalue", "73\u00B0F"),
|
||||
new TestCase("en_US@mu=fahrenhe", "73\u00B0F"),
|
||||
new TestCase("en_US@mu=fahrenheit", "73\u00B0F"),
|
||||
new TestCase("en_US@mu=celsius", "23\u00B0C"),
|
||||
new TestCase("en_US@mu=badvalue", "73\u00B0F"),
|
||||
|
||||
new TestCase("fr-FR", "23\u202F\u00B0C"),
|
||||
new TestCase("fr-FR-u-mu-fahrenhe", "73\u202F\u00B0F"),
|
||||
// WAI. Celsius because "fahrenheit" is an invalid -u-mu- value, we get the default for fr-FR
|
||||
new TestCase("fr-FR-u-mu-fahrenheit", "23\u202F\u00B0C"),
|
||||
new TestCase("fr-FR-u-mu-celsius", "23\u202F\u00B0C"),
|
||||
new TestCase("fr-FR-u-mu-badvalue", "23\u202F\u00B0C"),
|
||||
new TestCase("fr_FR@mu=fahrenhe", "73\u202F\u00B0F"),
|
||||
new TestCase("fr_FR@mu=fahrenheit", "73\u202F\u00B0F"),
|
||||
new TestCase("fr_FR@mu=celsius", "23\u202F\u00B0C"),
|
||||
new TestCase("fr_FR@mu=badvalue", "23\u202F\u00B0C"),
|
||||
};
|
||||
|
||||
final UnlocalizedNumberFormatter formatter = NumberFormatter.with()
|
||||
.usage("weather")
|
||||
.unit(MeasureUnit.CELSIUS);
|
||||
final double value = 23.0;
|
||||
|
||||
for (TestCase testCase : testCases) {
|
||||
String localeId = testCase.localeId;
|
||||
ULocale locale = localeId.contains("@")
|
||||
? new ULocale(localeId)
|
||||
: ULocale.forLanguageTag(localeId);
|
||||
String actualFormat = formatter.locale(locale).format(value).toString();
|
||||
assertEquals("-u-mu- honored (" + localeId + ")", testCase.expectedFormat, actualFormat);
|
||||
}
|
||||
|
||||
String result = formatter.locale(Locale.US).format(value).getOutputUnit().getIdentifier();
|
||||
assertEquals("Testing default -u-mu- for en-US", MeasureUnit.FAHRENHEIT.getIdentifier(), result);
|
||||
result = formatter.locale(Locale.FRANCE).format(value).getOutputUnit().getIdentifier();
|
||||
assertEquals("Testing default -u-mu- for fr-FR", MeasureUnit.CELSIUS.getIdentifier(), result);
|
||||
}
|
||||
|
||||
static void assertFormatDescending(
|
||||
String message,
|
||||
String skeleton,
|
||||
|
|
Loading…
Add table
Reference in a new issue