Skip to content

Commit

Permalink
ICU-21952 Add withoutLocale functions to LocalizedNumber[Range]Formatter
Browse files Browse the repository at this point in the history
See #2483
  • Loading branch information
sffc committed Dec 29, 2023
1 parent 0274059 commit 1a60a03
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 4 deletions.
20 changes: 20 additions & 0 deletions icu4c/source/i18n/number_fluent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,14 @@ UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const NFS<UNF>& other)
// No additional fields to assign
}

UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const impl::MacroProps &macros) {
fMacros = macros;
}

UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(impl::MacroProps &&macros) {
fMacros = macros;
}

// Make default copy constructor call the NumberFormatterSettings copy constructor.
UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UNF&& src) noexcept
: UNF(static_cast<NFS<UNF>&&>(src)) {}
Expand Down Expand Up @@ -726,6 +734,18 @@ int32_t LocalizedNumberFormatter::getCallCount() const {

// Note: toFormat defined in number_asformat.cpp

UnlocalizedNumberFormatter LocalizedNumberFormatter::withoutLocale() const & {
MacroProps macros(fMacros);
macros.locale = Locale();
return UnlocalizedNumberFormatter(macros);
}

UnlocalizedNumberFormatter LocalizedNumberFormatter::withoutLocale() && {
MacroProps macros(std::move(fMacros));
macros.locale = Locale();
return UnlocalizedNumberFormatter(std::move(macros));
}

const DecimalFormatSymbols* LocalizedNumberFormatter::getDecimalFormatSymbols() const {
return fMacros.symbols.getDecimalFormatSymbols();
}
Expand Down
21 changes: 21 additions & 0 deletions icu4c/source/i18n/numrange_fluent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(NFS<UNF>&& src)
// No additional fields to assign
}

UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros) {
fMacros = macros;
}

UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros) {
fMacros = macros;
}

UnlocalizedNumberRangeFormatter& UnlocalizedNumberRangeFormatter::operator=(const UNF& other) {
NFS<UNF>::operator=(static_cast<const NFS<UNF>&>(other));
// No additional fields to assign
Expand Down Expand Up @@ -286,6 +294,19 @@ LocalizedNumberRangeFormatter UnlocalizedNumberRangeFormatter::locale(const Loca
}


UnlocalizedNumberRangeFormatter LocalizedNumberRangeFormatter::withoutLocale() const & {
RangeMacroProps macros(fMacros);
macros.locale = Locale();
return UnlocalizedNumberRangeFormatter(macros);
}

UnlocalizedNumberRangeFormatter LocalizedNumberRangeFormatter::withoutLocale() && {
RangeMacroProps macros(std::move(fMacros));
macros.locale = Locale();
return UnlocalizedNumberRangeFormatter(std::move(macros));
}


FormattedNumberRange LocalizedNumberRangeFormatter::formatFormattableRange(
const Formattable& first, const Formattable& second, UErrorCode& status) const {
if (U_FAILURE(status)) {
Expand Down
26 changes: 26 additions & 0 deletions icu4c/source/i18n/unicode/numberformatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2497,11 +2497,18 @@ class U_I18N_API UnlocalizedNumberFormatter
explicit UnlocalizedNumberFormatter(
NumberFormatterSettings<UnlocalizedNumberFormatter>&& src) noexcept;

explicit UnlocalizedNumberFormatter(const impl::MacroProps &macros);

explicit UnlocalizedNumberFormatter(impl::MacroProps &&macros);

// To give the fluent setters access to this class's constructor:
friend class NumberFormatterSettings<UnlocalizedNumberFormatter>;

// To give NumberFormatter::with() access to this class's constructor:
friend class NumberFormatter;

// To give LNF::withoutLocale() access to this class's constructor:
friend class LocalizedNumberFormatter;
};

/**
Expand Down Expand Up @@ -2604,6 +2611,25 @@ class U_I18N_API LocalizedNumberFormatter
*/
Format* toFormat(UErrorCode& status) const;

#ifndef U_HIDE_DRAFT_API
/**
* Disassociate the locale from this formatter.
*
* @return The fluent chain.
* @draft ICU 74
*/
UnlocalizedNumberFormatter withoutLocale() const &;

/**
* Overload of withoutLocale() for use on an rvalue reference.
*
* @return The fluent chain.
* @see #withoutLocale
* @draft ICU 74
*/
UnlocalizedNumberFormatter withoutLocale() &&;
#endif // U_HIDE_DRAFT_API

/**
* Default constructor: puts the formatter into a valid but undefined state.
*
Expand Down
26 changes: 26 additions & 0 deletions icu4c/source/i18n/unicode/numberrangeformatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,18 @@ class U_I18N_API UnlocalizedNumberRangeFormatter
explicit UnlocalizedNumberRangeFormatter(
NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) noexcept;

explicit UnlocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros);

explicit UnlocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros);

// To give the fluent setters access to this class's constructor:
friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;

// To give NumberRangeFormatter::with() access to this class's constructor:
friend class NumberRangeFormatter;

// To give LNRF::withoutLocale() access to this class's constructor:
friend class LocalizedNumberRangeFormatter;
};

/**
Expand Down Expand Up @@ -496,6 +503,25 @@ class U_I18N_API LocalizedNumberRangeFormatter
FormattedNumberRange formatFormattableRange(
const Formattable& first, const Formattable& second, UErrorCode& status) const;

#ifndef U_HIDE_DRAFT_API
/**
* Disassociate the locale from this formatter.
*
* @return The fluent chain.
* @draft ICU 74
*/
UnlocalizedNumberRangeFormatter withoutLocale() const &;

/**
* Overload of withoutLocale() for use on an rvalue reference.
*
* @return The fluent chain.
* @see #withoutLocale
* @draft ICU 74
*/
UnlocalizedNumberRangeFormatter withoutLocale() &&;
#endif // U_HIDE_DRAFT_API

/**
* Default constructor: puts the formatter into a valid but undefined state.
*
Expand Down
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/numbertest.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
void testFieldPositions();
void testCopyMove();
void toObject();
void locale();
void testGetDecimalNumbers();
void test21684_Performance();
void test21358_SignPosition();
Expand Down
25 changes: 25 additions & 0 deletions icu4c/source/test/intltest/numbertest_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5186,6 +5186,31 @@ void NumberFormatterApiTest::locale() {
UnicodeString actual = NumberFormatter::withLocale(Locale::getFrench()).formatInt(1234, status)
.toString(status);
assertEquals("Locale withLocale()", u"1\u202f234", actual);

LocalizedNumberFormatter lnf1 = NumberFormatter::withLocale("en").unitWidth(UNUM_UNIT_WIDTH_FULL_NAME)
.scale(Scale::powerOfTen(2));
LocalizedNumberFormatter lnf2 = NumberFormatter::with()
.notation(Notation::compactLong()).locale("fr").unitWidth(UNUM_UNIT_WIDTH_FULL_NAME);
UnlocalizedNumberFormatter unf1 = lnf1.withoutLocale();
UnlocalizedNumberFormatter unf2 = std::move(lnf2).withoutLocale();

assertFormatSingle(
u"Formatter after withoutLocale A",
u"unit/meter unit-width-full-name scale/100",
u"unit/meter unit-width-full-name scale/100",
unf1.unit(METER),
"it-IT",
2,
u"200 metri");

assertFormatSingle(
u"Formatter after withoutLocale B",
u"compact-long unit/meter unit-width-full-name",
u"compact-long unit/meter unit-width-full-name",
unf2.unit(METER),
"ja-JP",
2,
u"2 メートル");
}

void NumberFormatterApiTest::skeletonUserGuideExamples() {
Expand Down
18 changes: 18 additions & 0 deletions icu4c/source/test/intltest/numbertest_range.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void NumberRangeFormatterTest::runIndexedTest(int32_t index, UBool exec, const c
TESTCASE_AUTO(testFieldPositions);
TESTCASE_AUTO(testCopyMove);
TESTCASE_AUTO(toObject);
TESTCASE_AUTO(locale);
TESTCASE_AUTO(testGetDecimalNumbers);
TESTCASE_AUTO(test21684_Performance);
TESTCASE_AUTO(test21358_SignPosition);
Expand Down Expand Up @@ -917,6 +918,23 @@ void NumberRangeFormatterTest::toObject() {
}
}

void NumberRangeFormatterTest::locale() {
IcuTestErrorCode status(*this, "locale");

LocalizedNumberRangeFormatter lnf = NumberRangeFormatter::withLocale("en")
.identityFallback(UNUM_IDENTITY_FALLBACK_RANGE);
UnlocalizedNumberRangeFormatter unf1 = lnf.withoutLocale();
UnlocalizedNumberRangeFormatter unf2 = NumberRangeFormatter::with()
.identityFallback(UNUM_IDENTITY_FALLBACK_RANGE)
.locale("ar-EG")
.withoutLocale();

FormattedNumberRange res1 = unf1.locale("bn").formatFormattableRange(5, 5, status);
assertEquals(u"res1", u"\u09EB\u2013\u09EB", res1.toTempString(status));
FormattedNumberRange res2 = unf2.locale("ja-JP").formatFormattableRange(5, 5, status);
assertEquals(u"res2", u"5\uFF5E5", res2.toTempString(status));
}

void NumberRangeFormatterTest::testGetDecimalNumbers() {
IcuTestErrorCode status(*this, "testGetDecimalNumbers");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5395,10 +5395,39 @@ public void scale() {
@Test
public void locale() {
// Coverage for the locale setters.
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH), NumberFormatter.with().locale(Locale.ENGLISH));
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH), NumberFormatter.withLocale(ULocale.ENGLISH));
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH), NumberFormatter.withLocale(Locale.ENGLISH));
Assert.assertNotEquals(NumberFormatter.with().locale(ULocale.ENGLISH), NumberFormatter.with().locale(Locale.FRENCH));
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH),
NumberFormatter.with().locale(Locale.ENGLISH));
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH),
NumberFormatter.withLocale(ULocale.ENGLISH));
Assert.assertEquals(NumberFormatter.with().locale(ULocale.ENGLISH),
NumberFormatter.withLocale(Locale.ENGLISH));
Assert.assertNotEquals(NumberFormatter.with().locale(ULocale.ENGLISH),
NumberFormatter.with().locale(Locale.FRENCH));

LocalizedNumberFormatter lnf1 = NumberFormatter.withLocale(ULocale.ENGLISH).unitWidth(UnitWidth.FULL_NAME)
.scale(Scale.powerOfTen(2));
LocalizedNumberFormatter lnf2 = NumberFormatter.with()
.notation(Notation.compactLong()).locale(ULocale.FRENCH).unitWidth(UnitWidth.FULL_NAME);
UnlocalizedNumberFormatter unf1 = lnf1.withoutLocale();
UnlocalizedNumberFormatter unf2 = lnf2.withoutLocale();

assertFormatSingle(
"Formatter after withoutLocale A",
"unit/meter unit-width-full-name scale/100",
"unit/meter unit-width-full-name scale/100",
unf1.unit(MeasureUnit.METER),
ULocale.ITALY,
2,
"200 metri");

assertFormatSingle(
"Formatter after withoutLocale B",
"compact-long unit/meter unit-width-full-name",
"compact-long unit/meter unit-width-full-name",
unf2.unit(MeasureUnit.METER),
ULocale.JAPAN,
2,
"2 メートル");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,22 @@ public void testFieldPositions() {
}
}

@Test
public void locale() {
LocalizedNumberRangeFormatter lnf = NumberRangeFormatter.withLocale(ULocale.ENGLISH)
.identityFallback(RangeIdentityFallback.RANGE);
UnlocalizedNumberRangeFormatter unf1 = lnf.withoutLocale();
UnlocalizedNumberRangeFormatter unf2 = NumberRangeFormatter.with()
.identityFallback(RangeIdentityFallback.RANGE)
.locale(ULocale.forLanguageTag("ar-EG"))
.withoutLocale();

FormattedNumberRange res1 = unf1.locale(ULocale.forLanguageTag("bn")).formatRange(5, 5);
assertEquals("res1", "\u09EB\u2013\u09EB", res1.toString());
FormattedNumberRange res2 = unf2.locale(ULocale.forLanguageTag("ja-JP")).formatRange(5, 5);
assertEquals("res2", "5\uFF5E5", res2.toString());
}

static final String[] allNSNames = NumberingSystem.getAvailableNames();

private class RangePatternSink extends UResource.Sink {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ public Format toFormat() {
return new LocalizedNumberFormatterAsFormat(this, resolve().loc);
}

/**
* Disassociate the locale from this formatter.
*
* @return The fluent chain.
* @draft ICU 74
*/
public UnlocalizedNumberFormatter withoutLocale() {
return new UnlocalizedNumberFormatter(this, KEY_LOCALE, null);
}

/**
* Helper method that creates a FormattedStringBuilder and formats.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ public FormattedNumberRange formatRange(Number first, Number second) {
return formatImpl(dq1, dq2, first.equals(second));
}

/**
* Disassociate the locale from this formatter.
*
* @return The fluent chain.
* @draft ICU 74
*/
public UnlocalizedNumberRangeFormatter withoutLocale() {
return new UnlocalizedNumberRangeFormatter(this, KEY_LOCALE, null);
}

FormattedNumberRange formatImpl(DecimalQuantity first, DecimalQuantity second, boolean equalBeforeRounding) {
if (fImpl == null) {
fImpl = new NumberRangeFormatterImpl(resolve());
Expand Down

0 comments on commit 1a60a03

Please sign in to comment.