From d6fc9b828c95f0d8d10a8648b3471459d05fb8c4 Mon Sep 17 00:00:00 2001 From: Younies Mahmoud Date: Thu, 26 May 2022 17:59:10 +0000 Subject: [PATCH] ICU-21935 Add DisplayOptions to NumberFormatterSettings See #2099 --- icu4c/source/i18n/number_fluent.cpp | 28 ++++++++++++ icu4c/source/i18n/unicode/numberformatter.h | 32 +++++++++++--- icu4c/source/test/intltest/numbertest_api.cpp | 44 +++++++++++++++++-- .../icu/number/NumberFormatterSettings.java | 18 ++++++++ .../test/number/NumberFormatterApiTest.java | 28 ++++++++++++ 5 files changed, 141 insertions(+), 9 deletions(-) diff --git a/icu4c/source/i18n/number_fluent.cpp b/icu4c/source/i18n/number_fluent.cpp index fd486afb512..8a968d922c2 100644 --- a/icu4c/source/i18n/number_fluent.cpp +++ b/icu4c/source/i18n/number_fluent.cpp @@ -288,6 +288,34 @@ Derived NumberFormatterSettings::usage(const StringPiece usage)&& { return move; } +template +Derived NumberFormatterSettings::displayOptions(const DisplayOptions &displayOptions) const & { + Derived copy(*this); + // `displayCase` does not recognise the `undefined` + if (displayOptions.getGrammaticalCase() == UDISPOPT_GRAMMATICAL_CASE_UNDEFINED) { + copy.fMacros.unitDisplayCase.set(nullptr); + return copy; + } + + copy.fMacros.unitDisplayCase.set( + udispopt_getGrammaticalCaseIdentifier(displayOptions.getGrammaticalCase())); + return copy; +} + +template +Derived NumberFormatterSettings::displayOptions(const DisplayOptions &displayOptions) && { + Derived move(std::move(*this)); + // `displayCase` does not recognise the `undefined` + if (displayOptions.getGrammaticalCase() == UDISPOPT_GRAMMATICAL_CASE_UNDEFINED) { + move.fMacros.unitDisplayCase.set(nullptr); + return move; + } + + move.fMacros.unitDisplayCase.set( + udispopt_getGrammaticalCaseIdentifier(displayOptions.getGrammaticalCase())); + return move; +} + template Derived NumberFormatterSettings::unitDisplayCase(const StringPiece unitDisplayCase) const& { Derived copy(*this); diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h index 09bbdb8c3b0..339a6098cc6 100644 --- a/icu4c/source/i18n/unicode/numberformatter.h +++ b/icu4c/source/i18n/unicode/numberformatter.h @@ -14,6 +14,7 @@ #include "unicode/bytestream.h" #include "unicode/currunit.h" #include "unicode/dcfmtsym.h" +#include "unicode/displayoptions.h" #include "unicode/fieldpos.h" #include "unicode/formattedvalue.h" #include "unicode/fpositer.h" @@ -2254,23 +2255,44 @@ class U_I18N_API NumberFormatterSettings { Derived usage(StringPiece usage) &&; #ifndef U_HIDE_DRAFT_API -#ifndef U_HIDE_INTERNAL_API /** + * Specifies the DisplayOptions. For example, UDisplayOptionsGrammaticalCase specifies + * the desired case for a unit formatter's output (e.g. accusative, dative, genitive). + * + * @param displayOptions + * @return The fluent chain. + * @draft ICU 72 + */ + Derived displayOptions(const DisplayOptions &displayOptions) const &; + + /** + * Overload of displayOptions() for use on an rvalue reference. + * + * @param displayOptions + * @return The fluent chain. + * @draft ICU 72 + */ + Derived displayOptions(const DisplayOptions &displayOptions) &&; +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_DEPRECATED_API + /** + * NOTE: This function is deprecated, use `displayOptions` instead. + * * Specifies the desired case for a unit formatter's output (e.g. * accusative, dative, genitive). * - * @internal ICU 69 technology preview + * @deprecated ICU 72 */ Derived unitDisplayCase(StringPiece unitDisplayCase) const &; /** * Overload of unitDisplayCase() for use on an rvalue reference. * - * @internal ICU 69 technology preview + * @deprecated ICU 72 */ Derived unitDisplayCase(StringPiece unitDisplayCase) &&; -#endif // U_HIDE_INTERNAL_API -#endif // U_HIDE_DRAFT_API +#endif // U_HIDE_DEPRECATED_API #ifndef U_HIDE_INTERNAL_API diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp index 674250abaeb..3bd993a7453 100644 --- a/icu4c/source/test/intltest/numbertest_api.cpp +++ b/icu4c/source/test/intltest/numbertest_api.cpp @@ -5,19 +5,22 @@ #if !UCONFIG_NO_FORMATTING -#include "charstr.h" -#include #include +#include #include -#include "unicode/unum.h" + +#include "unicode/displayoptions.h" #include "unicode/numberformatter.h" #include "unicode/testlog.h" +#include "unicode/unum.h" #include "unicode/utypes.h" + +#include "charstr.h" #include "number_asformat.h" +#include "number_microprops.h" #include "number_types.h" #include "number_utils.h" #include "number_utypes.h" -#include "number_microprops.h" #include "numbertest.h" using number::impl::UFormattedNumberData; @@ -2312,6 +2315,39 @@ void NumberFormatterApiTest::runUnitInflectionsTestCases(UnlocalizedNumberFormat skel, skel, unf, Locale(t.locale), t.value, t.expected); status.assertSuccess(); } + + for (int32_t i = 0; i < numCases; i++) { + UnitInflectionTestCase t = cases[i]; + status.assertSuccess(); + MeasureUnit mu = MeasureUnit::forIdentifier(t.unitIdentifier, status); + if (status.errIfFailureAndReset("MeasureUnit::forIdentifier(\"%s\", ...) failed", + t.unitIdentifier)) { + continue; + }; + + UnicodeString skelString = UnicodeString("unit/") + t.unitIdentifier + u" " + skeleton; + const UChar *skel; + auto displayOptionsBuilder = DisplayOptions::builder(); + if (t.unitDisplayCase == nullptr || t.unitDisplayCase[0] == 0) { + auto displayoptions = displayOptionsBuilder.build(); + unf = unf.unit(mu).displayOptions(displayoptions); + skel = skelString.getTerminatedBuffer(); + } else { + auto displayoptions = + displayOptionsBuilder + .setGrammaticalCase(udispopt_fromGrammaticalCaseIdentifier(t.unitDisplayCase)) + .build(); + unf = unf.unit(mu).displayOptions(displayoptions); + // No skeleton support for unitDisplayCase yet. + skel = nullptr; + } + assertFormatSingle((UnicodeString("Unit: \"") + t.unitIdentifier + ("\", \"") + skeleton + + u"\", locale=\"" + t.locale + u"\", case=\"" + + (t.unitDisplayCase ? t.unitDisplayCase : "") + u"\", value=" + t.value) + .getTerminatedBuffer(), + skel, skel, unf, Locale(t.locale), t.value, t.expected); + status.assertSuccess(); + } } void NumberFormatterApiTest::unitInflections() { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterSettings.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterSettings.java index 800048792ff..c820a823ea1 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterSettings.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterSettings.java @@ -2,6 +2,8 @@ // License & terms of use: http://www.unicode.org/copyright.html package com.ibm.icu.number; +import com.ibm.icu.text.DisplayOptions; +import com.ibm.icu.text.DisplayOptions.GrammaticalCase; import java.math.RoundingMode; import com.ibm.icu.impl.number.MacroProps; @@ -552,6 +554,22 @@ public abstract class NumberFormatterSettings