mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 23:10:40 +00:00
parent
b1269c9121
commit
f30956fc9c
5 changed files with 126 additions and 8 deletions
|
@ -431,13 +431,33 @@ void getMeasureData(const Locale &locale,
|
|||
subKey.append(unit.getType(), status);
|
||||
subKey.append("/", status);
|
||||
|
||||
// Check if unitSubType is an alias or not.
|
||||
LocalUResourceBundlePointer aliasBundle(ures_open(U_ICUDATA_ALIAS, "metadata", &status));
|
||||
|
||||
UErrorCode aliasStatus = status;
|
||||
StackUResourceBundle aliasFillIn;
|
||||
CharString aliasKey;
|
||||
aliasKey.append("alias/unit/", aliasStatus);
|
||||
aliasKey.append(unit.getSubtype(), aliasStatus);
|
||||
aliasKey.append("/replacement", aliasStatus);
|
||||
ures_getByKeyWithFallback(aliasBundle.getAlias(), aliasKey.data(), aliasFillIn.getAlias(),
|
||||
&aliasStatus);
|
||||
CharString unitSubType;
|
||||
if (!U_FAILURE(aliasStatus)) {
|
||||
// This means the subType is an alias. Then, replace unitSubType with the replacement.
|
||||
auto replacement = ures_getUnicodeString(aliasFillIn.getAlias(), &status);
|
||||
unitSubType.appendInvariantChars(replacement, status);
|
||||
} else {
|
||||
unitSubType.append(unit.getSubtype(), status);
|
||||
}
|
||||
|
||||
// Map duration-year-person, duration-week-person, etc. to duration-year, duration-week, ...
|
||||
// TODO(ICU-20400): Get duration-*-person data properly with aliases.
|
||||
int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(unit.getSubtype()));
|
||||
if (subtypeLen > 7 && uprv_strcmp(unit.getSubtype() + subtypeLen - 7, "-person") == 0) {
|
||||
subKey.append({unit.getSubtype(), subtypeLen - 7}, status);
|
||||
int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(unitSubType.data()));
|
||||
if (subtypeLen > 7 && uprv_strcmp(unitSubType.data() + subtypeLen - 7, "-person") == 0) {
|
||||
subKey.append({unitSubType.data(), subtypeLen - 7}, status);
|
||||
} else {
|
||||
subKey.append({unit.getSubtype(), subtypeLen}, status);
|
||||
subKey.append({unitSubType.data(), subtypeLen}, status);
|
||||
}
|
||||
|
||||
if (width != UNUM_UNIT_WIDTH_FULL_NAME) {
|
||||
|
|
|
@ -101,7 +101,8 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
|
|||
void toObject();
|
||||
void toDecimalNumber();
|
||||
void microPropsInternals();
|
||||
|
||||
void formatUnitsAliases();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -129,6 +129,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
|
|||
TESTCASE_AUTO(toObject);
|
||||
TESTCASE_AUTO(toDecimalNumber);
|
||||
TESTCASE_AUTO(microPropsInternals);
|
||||
TESTCASE_AUTO(formatUnitsAliases);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
|
@ -6174,6 +6175,37 @@ void NumberFormatterApiTest::microPropsInternals() {
|
|||
assertEquals("Copy Assigned capacity", 4, copyAssigned.mixedMeasures.getCapacity());
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::formatUnitsAliases() {
|
||||
IcuTestErrorCode status(*this, "formatUnitsAliases");
|
||||
|
||||
struct TestCase {
|
||||
const MeasureUnit measureUnit;
|
||||
const UnicodeString expectedFormat;
|
||||
} testCases[]{
|
||||
// Aliases
|
||||
{MeasureUnit::getMilligramPerDeciliter(), u"2 milligrams per deciliter"},
|
||||
{MeasureUnit::getLiterPer100Kilometers(), u"2 liters per 100 kilometers"},
|
||||
{MeasureUnit::getPartPerMillion(), u"2 parts per million"},
|
||||
{MeasureUnit::getMillimeterOfMercury(), u"2 millimeters of mercury"},
|
||||
|
||||
// Replacements
|
||||
{MeasureUnit::getMilligramOfglucosePerDeciliter(), u"2 milligrams per deciliter"},
|
||||
{MeasureUnit::forIdentifier("millimeter-ofhg", status), u"2 millimeters of mercury"},
|
||||
{MeasureUnit::forIdentifier("liter-per-100-kilometer", status), u"2 liters per 100 kilometers"},
|
||||
{MeasureUnit::forIdentifier("permillion", status), u"2 parts per million"},
|
||||
};
|
||||
|
||||
for (const auto &testCase : testCases) {
|
||||
UnicodeString actualFormat = NumberFormatter::withLocale(icu::Locale::getEnglish())
|
||||
.unit(testCase.measureUnit)
|
||||
.unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME)
|
||||
.formatDouble(2.0, status)
|
||||
.toString(status);
|
||||
|
||||
assertEquals("test unit aliases", testCase.expectedFormat, actualFormat);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
|
|
@ -329,6 +329,21 @@ public class LongNameHandler
|
|||
}
|
||||
}
|
||||
|
||||
private static final class AliasSink extends UResource.Sink {
|
||||
String replacement;
|
||||
|
||||
@Override
|
||||
public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
|
||||
UResource.Table aliasTable = value.getTable();
|
||||
for (int i = 0; aliasTable.getKeyAndValue(i, key, value); ++i) {
|
||||
String keyString = key.toString();
|
||||
if (keyString.equals("replacement")) {
|
||||
this.replacement = value.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: outArray MUST have at least ARRAY_LENGTH entries. No bounds checking is performed.
|
||||
static void getMeasureData(
|
||||
ULocale locale,
|
||||
|
@ -346,12 +361,23 @@ public class LongNameHandler
|
|||
subKey.append(unit.getType());
|
||||
subKey.append("/");
|
||||
|
||||
// If the unit is an alias, replace it is identifier with the replacement.
|
||||
String unitSubType = unit.getSubtype();
|
||||
ICUResourceBundle metadataResource = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "metadata");
|
||||
AliasSink aliasSink = new AliasSink();
|
||||
|
||||
metadataResource.getAllItemsWithFallbackNoFail("alias/unit/" + unitSubType, aliasSink);
|
||||
if (aliasSink.replacement != null) {
|
||||
unitSubType = aliasSink.replacement;
|
||||
}
|
||||
|
||||
|
||||
// Map duration-year-person, duration-week-person, etc. to duration-year, duration-week, ...
|
||||
// TODO(ICU-20400): Get duration-*-person data properly with aliases.
|
||||
if (unit.getSubtype() != null && unit.getSubtype().endsWith("-person")) {
|
||||
subKey.append(unit.getSubtype(), 0, unit.getSubtype().length() - 7);
|
||||
if (unitSubType != null && unitSubType.endsWith("-person")) {
|
||||
subKey.append(unitSubType, 0, unitSubType.length() - 7);
|
||||
} else {
|
||||
subKey.append(unit.getSubtype());
|
||||
subKey.append(unitSubType);
|
||||
}
|
||||
|
||||
if (width != UnitWidth.FULL_NAME) {
|
||||
|
|
|
@ -5857,6 +5857,45 @@ public class NumberFormatterApiTest extends TestFmwk {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatUnitsAliases() {
|
||||
|
||||
class TestCase {
|
||||
final MeasureUnit measureUnit;
|
||||
final String expectedFormat;
|
||||
|
||||
TestCase(MeasureUnit measureUnit, String expectedFormat) {
|
||||
this.measureUnit = measureUnit;
|
||||
this.expectedFormat = expectedFormat;
|
||||
}
|
||||
}
|
||||
|
||||
TestCase[] testCases = {
|
||||
// Aliases
|
||||
new TestCase(MeasureUnit.MILLIGRAM_PER_DECILITER, "2 milligrams per deciliter"),
|
||||
new TestCase(MeasureUnit.LITER_PER_100KILOMETERS, "2 liters per 100 kilometers"),
|
||||
new TestCase(MeasureUnit.PART_PER_MILLION, "2 parts per million"),
|
||||
new TestCase(MeasureUnit.MILLIMETER_OF_MERCURY, "2 millimeters of mercury"),
|
||||
|
||||
// Replacements
|
||||
new TestCase(MeasureUnit.MILLIGRAM_OFGLUCOSE_PER_DECILITER, "2 milligrams per deciliter"),
|
||||
new TestCase(MeasureUnit.forIdentifier("millimeter-ofhg"), "2 millimeters of mercury"),
|
||||
new TestCase(MeasureUnit.forIdentifier("liter-per-100-kilometer"), "2 liters per 100 kilometers"),
|
||||
new TestCase(MeasureUnit.forIdentifier("permillion"), "2 parts per million"),
|
||||
};
|
||||
|
||||
for (TestCase testCase : testCases) {
|
||||
String actualFormat = NumberFormatter
|
||||
.withLocale(ULocale.ENGLISH)
|
||||
.unit(testCase.measureUnit)
|
||||
.unitWidth(UnitWidth.FULL_NAME)
|
||||
.format(2.0)
|
||||
.toString();
|
||||
|
||||
assertEquals("test unit aliases", testCase.expectedFormat, actualFormat);
|
||||
}
|
||||
}
|
||||
|
||||
static void assertFormatDescending(
|
||||
String message,
|
||||
String skeleton,
|
||||
|
|
Loading…
Add table
Reference in a new issue