From: Jonah Lawrence Date: Fri, 6 Jan 2023 20:21:58 +0000 (-0700) Subject: Fix compact singular formats and patterns with no numbers (#932) X-Git-Tag: v2.12.0~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3594836cd9e64b6c98f008ee7e25614de7d9db68;p=thirdparty%2Fbabel.git Fix compact singular formats and patterns with no numbers (#932) --- diff --git a/babel/numbers.py b/babel/numbers.py index 2221e95a..da5936db 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -17,6 +17,7 @@ # TODO: # Padding and rounding increments in pattern: # - https://www.unicode.org/reports/tr35/ (Appendix G.6) +from __future__ import annotations import decimal import re from datetime import date as date_, datetime as datetime_ @@ -431,7 +432,7 @@ def format_compact_decimal(number, *, format_type="short", locale=LC_NUMERIC, fr u'123万' >>> format_compact_decimal(2345678, format_type="long", locale="mk") u'2 милиони' - >>> format_compact_decimal(21098765, format_type="long", locale="mk") + >>> format_compact_decimal(21000000, format_type="long", locale="mk") u'21 милион' :param number: the number to format @@ -469,11 +470,15 @@ def _get_compact_format(number, compact_format, locale, fraction_digits=0): # equal to the number of 0's in the pattern minus 1 number = number / (magnitude // (10 ** (pattern.count("0") - 1))) # round to the number of fraction digits requested - number = round(number, fraction_digits) + rounded = round(number, fraction_digits) # if the remaining number is singular, use the singular format plural_form = locale.plural_form(abs(number)) - plural_form = plural_form if plural_form in compact_format else "other" + if plural_form not in compact_format: + plural_form = "other" + if number == 1 and "1" in compact_format: + plural_form = "1" format = compact_format[plural_form][str(magnitude)] + number = rounded break return number, format @@ -960,17 +965,19 @@ def parse_pattern(pattern): return NumberPattern(pattern, (pos_prefix, neg_prefix), (pos_suffix, neg_suffix), grouping, int_prec, frac_prec, - exp_prec, exp_plus) + exp_prec, exp_plus, number) class NumberPattern: def __init__(self, pattern, prefix, suffix, grouping, - int_prec, frac_prec, exp_prec, exp_plus): + int_prec, frac_prec, exp_prec, exp_plus, + number_pattern: str | None = None): # Metadata of the decomposed parsed pattern. self.pattern = pattern self.prefix = prefix self.suffix = suffix + self.number_pattern = number_pattern self.grouping = grouping self.int_prec = int_prec self.frac_prec = frac_prec @@ -1115,7 +1122,7 @@ class NumberPattern: retval = ''.join([ self.prefix[is_negative], - number, + number if self.number_pattern != '' else '', self.suffix[is_negative]]) if u'¤' in retval: diff --git a/tests/test_numbers.py b/tests/test_numbers.py index bb6c4e84..37d2f9ec 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -153,7 +153,12 @@ class FormatDecimalTestCase(unittest.TestCase): assert numbers.format_compact_decimal(-123456789, format_type='short', locale='en_US') == u'-123M' assert numbers.format_compact_decimal(-123456789, format_type='long', locale='en_US') == u'-123 million' assert numbers.format_compact_decimal(2345678, locale='mk', format_type='long') == u'2 милиони' - assert numbers.format_compact_decimal(21098765, locale='mk', format_type='long') == u'21 милион' + assert numbers.format_compact_decimal(21000000, locale='mk', format_type='long') == u'21 милион' + assert numbers.format_compact_decimal(21345, locale="gv", format_type="short") == u'21K' + assert numbers.format_compact_decimal(1000, locale='it', format_type='long') == u'mille' + assert numbers.format_compact_decimal(1234, locale='it', format_type='long') == u'1 mila' + assert numbers.format_compact_decimal(1000, locale='fr', format_type='long') == u'mille' + assert numbers.format_compact_decimal(1234, locale='fr', format_type='long') == u'1 millier' class NumberParsingTestCase(unittest.TestCase):