From: Peter Edberg Date: Thu, 29 Aug 2019 07:02:17 +0000 (-0700) Subject: ICU-20577 Restore C MeasureFormat ability to adopt non-decimal number formatter ... X-Git-Tag: release-65-rc~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0801dd0bdd918ad7acf543e7a061826ca17163ea;p=icu ICU-20577 Restore C MeasureFormat ability to adopt non-decimal number formatter (#789) --- diff --git a/icu4c/source/i18n/measfmt.cpp b/icu4c/source/i18n/measfmt.cpp index 7d9612d1070..1949f17b137 100644 --- a/icu4c/source/i18n/measfmt.cpp +++ b/icu4c/source/i18n/measfmt.cpp @@ -685,9 +685,19 @@ UnicodeString &MeasureFormat::formatMeasure( } auto* df = dynamic_cast(&nf); if (df == nullptr) { - // Don't know how to handle other types of NumberFormat - status = U_UNSUPPORTED_ERROR; - return appendTo; + // Handle other types of NumberFormat using the ICU 63 code, modified to + // get the unitPattern from LongNameHandler and handle fallback to OTHER. + UnicodeString formattedNumber; + StandardPlural::Form pluralForm = QuantityFormatter::selectPlural( + amtNumber, nf, **pluralRules, formattedNumber, pos, status); + UnicodeString pattern = number::impl::LongNameHandler::getUnitPattern(getLocale(status), + amtUnit, getUnitWidth(fWidth), pluralForm, status); + // The above handles fallback from other widths to short, and from other plural forms to OTHER + if (U_FAILURE(status)) { + return appendTo; + } + SimpleFormatter formatter(pattern, 0, 1, status); + return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status); } number::FormattedNumber result; if (auto* lnf = df->toNumberFormatter(status)) { diff --git a/icu4c/source/i18n/number_longnames.cpp b/icu4c/source/i18n/number_longnames.cpp index b790ffb67e8..817aa0e0d9c 100644 --- a/icu4c/source/i18n/number_longnames.cpp +++ b/icu4c/source/i18n/number_longnames.cpp @@ -264,6 +264,26 @@ UnicodeString LongNameHandler::getUnitDisplayName( return simpleFormats[DNAM_INDEX]; } +UnicodeString LongNameHandler::getUnitPattern( + const Locale& loc, + const MeasureUnit& unit, + UNumberUnitWidth width, + StandardPlural::Form pluralForm, + UErrorCode& status) { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + UnicodeString simpleFormats[ARRAY_LENGTH]; + getMeasureData(loc, unit, width, simpleFormats, status); + // The above already handles fallback from other widths to short + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + // Now handle fallback from other plural forms to OTHER + return (!(simpleFormats[pluralForm]).isBogus())? simpleFormats[pluralForm]: + simpleFormats[StandardPlural::Form::OTHER]; +} + LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, diff --git a/icu4c/source/i18n/number_longnames.h b/icu4c/source/i18n/number_longnames.h index 38aca26f729..a19425aa268 100644 --- a/icu4c/source/i18n/number_longnames.h +++ b/icu4c/source/i18n/number_longnames.h @@ -22,6 +22,13 @@ class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UNumberUnitWidth width, UErrorCode& status); + static UnicodeString getUnitPattern( + const Locale& loc, + const MeasureUnit& unit, + UNumberUnitWidth width, + StandardPlural::Form pluralForm, + UErrorCode& status); + static LongNameHandler* forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status); diff --git a/icu4c/source/test/intltest/measfmttest.cpp b/icu4c/source/test/intltest/measfmttest.cpp index c4d0064e89b..cb53d83e8d2 100644 --- a/icu4c/source/test/intltest/measfmttest.cpp +++ b/icu4c/source/test/intltest/measfmttest.cpp @@ -28,6 +28,7 @@ #include "charstr.h" #include "cstr.h" #include "unicode/reldatefmt.h" +#include "unicode/rbnf.h" struct ExpectedResult { const Measure *measures; @@ -1699,6 +1700,10 @@ void MeasureFormatTest::TestExamplesInDocs() { void MeasureFormatTest::TestFormatPeriodEn() { UErrorCode status = U_ZERO_ERROR; + Measure t_1y[] = {Measure((double)1, MeasureUnit::createYear(status), status)}; + Measure t_5M[] = {Measure((double)5, MeasureUnit::createMonth(status), status)}; + Measure t_4d[] = {Measure((double)4, MeasureUnit::createDay(status), status)}; + Measure t_2h[] = {Measure((double)2, MeasureUnit::createHour(status), status)}; Measure t_19m[] = {Measure((double)19, MeasureUnit::createMinute(status), status)}; Measure t_1h_23_5s[] = { Measure((double)1.0, MeasureUnit::createHour(status), status), @@ -1867,6 +1872,20 @@ void MeasureFormatTest::TestFormatPeriodEn() { {t_6h_56_92m, UPRV_LENGTHOF(t_6h_56_92m), "6:56.92"}, {t_3h_5h, UPRV_LENGTHOF(t_3h_5h), "3 \\u0998\\u0983, 5 \\u0998\\u0983"}}; + ExpectedResult fullDataSpellout[] = { + {t_1y, UPRV_LENGTHOF(t_1y), "one year"}, + {t_5M, UPRV_LENGTHOF(t_5M), "five months"}, + {t_4d, UPRV_LENGTHOF(t_4d), "four days"}, + {t_2h, UPRV_LENGTHOF(t_2h), "two hours"}, + {t_19m, UPRV_LENGTHOF(t_19m), "nineteen minutes"}}; + + ExpectedResult fullDataSpelloutFr[] = { + {t_1y, UPRV_LENGTHOF(t_1y), "un\\u00A0an"}, + {t_5M, UPRV_LENGTHOF(t_5M), "cinq\\u00A0mois"}, + {t_4d, UPRV_LENGTHOF(t_4d), "quatre\\u00A0jours"}, + {t_2h, UPRV_LENGTHOF(t_2h), "deux\\u00A0heures"}, + {t_19m, UPRV_LENGTHOF(t_19m), "dix-neuf minutes"}}; + Locale en(Locale::getEnglish()); LocalPointer nf(NumberFormat::createInstance(en, status)); if (U_FAILURE(status)) { @@ -1947,6 +1966,30 @@ void MeasureFormatTest::TestFormatPeriodEn() { return; } verifyFormat("bn-u-nu-latn NUMERIC", mf, numericDataBnLatn, UPRV_LENGTHOF(numericDataBnLatn)); + + status = U_ZERO_ERROR; + LocalPointer rbnf(new RuleBasedNumberFormat(URBNF_SPELLOUT, en, status)); + if (U_FAILURE(status)) { + dataerrln("Error creating rbnf en object - %s", u_errorName(status)); + return; + } + mf = MeasureFormat(en, UMEASFMT_WIDTH_WIDE, rbnf->clone(), status); + if (!assertSuccess("Error creating measure format en WIDE with rbnf", status)) { + return; + } + verifyFormat("en WIDE rbnf", mf, fullDataSpellout, UPRV_LENGTHOF(fullDataSpellout)); + + Locale fr(Locale::getFrench()); + LocalPointer rbnffr(new RuleBasedNumberFormat(URBNF_SPELLOUT, fr, status)); + if (U_FAILURE(status)) { + dataerrln("Error creating rbnf fr object - %s", u_errorName(status)); + return; + } + mf = MeasureFormat(fr, UMEASFMT_WIDTH_WIDE, rbnffr->clone(), status); + if (!assertSuccess("Error creating measure format fr WIDE with rbnf", status)) { + return; + } + verifyFormat("fr WIDE rbnf", mf, fullDataSpelloutFr, UPRV_LENGTHOF(fullDataSpellout)); } void MeasureFormatTest::Test10219FractionalPlurals() {