From cdf6870094ede4256148526b4ba00d8623360e01 Mon Sep 17 00:00:00 2001 From: 0718lol <218699424+0718lol@users.noreply.github.com> Date: Wed, 4 Nov 2026 20:04:07 +0800 Subject: [PATCH] Fix compact decimal plural selection after rounding --- babel/numbers.py | 6 ++++-- tests/test_numbers.py | 19 +++++++++++++++++++ tests/test_numbers_format_decimal.py | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/babel/numbers.py b/babel/numbers.py index 09e7a767f..2182b1356 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -692,8 +692,10 @@ def _get_compact_format( if index > 0 and abs(rounded) * divisor >= magnitudes[index - 1]: bumped = decimal.Decimal(magnitudes[index - 1]).copy_sign(number) return _get_compact_format(bumped, compact_format, locale, fraction_digits) - # if the remaining number is singular, use the singular format - plural_form = locale.plural_form(abs(scaled)) + # Select the plural form from the displayed number. Optional trailing + # fractional zeros are not rendered by the compact pattern. + plural_number = abs(rounded).normalize() + plural_form = locale.plural_form(plural_number) if plural_form not in compact_format: plural_form = "other" if scaled == 1 and "1" in compact_format: diff --git a/tests/test_numbers.py b/tests/test_numbers.py index d20a18315..dac1b00e1 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -695,3 +695,22 @@ def test_issue_1076_fixes(): assert numbers.format_compact_decimal(2345678, format_type="long", locale="ja") == "235万" # Swahili does not define an accounting currency format; root aliases it to the standard format. assert numbers.format_currency(-2, "USD", format_type="accounting", locale="sw") == "-US$\xa02.00" + + +@pytest.mark.parametrize(('locale', 'value', 'digits', 'expected'), [ + ('ru', 1100, 0, '1 тысяча'), + ('ru', -1100, 0, '-1 тысяча'), + ('ru', 1900, 0, '2 тысячи'), + ('ru', 1010, 1, '1 тысяча'), + ('ru', 1100, 1, '1,1 тысячи'), + ('pl', 1100, 0, '1 tysiąc'), + ('pl', 1900, 0, '2 tysiące'), + ('cs', 1100, 0, '1 tisíc'), + ('cs', 1900, 0, '2 tisíce'), + ('fr', 1900, 0, '2 mille'), + ('it', 1100, 0, 'mille'), +]) +def test_compact_plural_uses_displayed_number(locale, value, digits, expected): + assert numbers.format_compact_decimal( + value, format_type='long', fraction_digits=digits, locale=locale, + ) == expected diff --git a/tests/test_numbers_format_decimal.py b/tests/test_numbers_format_decimal.py index 124c5b96d..798eb1c87 100644 --- a/tests/test_numbers_format_decimal.py +++ b/tests/test_numbers_format_decimal.py @@ -166,7 +166,7 @@ def test_compact(): assert numbers.format_compact_decimal(21000000, locale='mk', format_type='long') == '21 милион' assert numbers.format_compact_decimal(21345, locale="gv", format_type="short") == '21K' assert numbers.format_compact_decimal(1000, locale='it', format_type='long') == 'mille' - assert numbers.format_compact_decimal(1234, locale='it', format_type='long') == '1 mila' + assert numbers.format_compact_decimal(1234, locale='it', format_type='long') == 'mille' assert numbers.format_compact_decimal(1000, locale='fr', format_type='long') == 'mille' assert numbers.format_compact_decimal(1234, locale='fr', format_type='long') == '1 millier' assert numbers.format_compact_decimal(