Skip to content

Commit

Permalink
Fix compact singular formats and patterns with no numbers (#932)
Browse files Browse the repository at this point in the history
  • Loading branch information
DenverCoder1 authored Jan 6, 2023
1 parent d425f86 commit 3594836
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
19 changes: 13 additions & 6 deletions babel/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -960,17 +965,19 @@ def parse_precision(p):
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
Expand Down Expand Up @@ -1115,7 +1122,7 @@ def apply(

retval = ''.join([
self.prefix[is_negative],
number,
number if self.number_pattern != '' else '',
self.suffix[is_negative]])

if u'¤' in retval:
Expand Down
7 changes: 6 additions & 1 deletion tests/test_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ def test_compact(self):
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):

Expand Down

0 comments on commit 3594836

Please sign in to comment.