]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Fix compact singular formats and patterns with no numbers (#932)
authorJonah Lawrence <jonah@freshidea.com>
Fri, 6 Jan 2023 20:21:58 +0000 (13:21 -0700)
committerGitHub <noreply@github.com>
Fri, 6 Jan 2023 20:21:58 +0000 (22:21 +0200)
babel/numbers.py
tests/test_numbers.py

index 2221e95a124c14f12ae03ff3a658d01747ceff4a..da5936dbffdb9c8d63b52feb28bfea3aaf44ec5f 100644 (file)
@@ -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:
index bb6c4e84ee4a16237a884c6d604841390a44e13b..37d2f9ec64808441fcde09a534662d988681943d 100644 (file)
@@ -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):