mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #25920 -- Added support for non-uniform NUMBER_GROUPING.
This commit is contained in:
		| @@ -15,12 +15,15 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', | ||||
|  | ||||
|     * decimal_sep: Decimal separator symbol (for example ".") | ||||
|     * decimal_pos: Number of decimal positions | ||||
|     * grouping: Number of digits in every group limited by thousand separator | ||||
|     * grouping: Number of digits in every group limited by thousand separator. | ||||
|         For non-uniform digit grouping, it can be a sequence with the number | ||||
|         of digit group sizes following the format used by the Python locale | ||||
|         module in locale.localeconv() LC_NUMERIC grouping (e.g. (3, 2, 0)). | ||||
|     * thousand_sep: Thousand separator symbol (for example ",") | ||||
|     """ | ||||
|     use_grouping = settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR | ||||
|     use_grouping = use_grouping or force_grouping | ||||
|     use_grouping = use_grouping and grouping > 0 | ||||
|     use_grouping = use_grouping and grouping != 0 | ||||
|     # Make the common case fast | ||||
|     if isinstance(number, int) and not use_grouping and not decimal_pos: | ||||
|         return mark_safe(six.text_type(number)) | ||||
| @@ -46,10 +49,22 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', | ||||
|         dec_part = decimal_sep + dec_part | ||||
|     # grouping | ||||
|     if use_grouping: | ||||
|         try: | ||||
|             # if grouping is a sequence | ||||
|             intervals = list(grouping) | ||||
|         except TypeError: | ||||
|             # grouping is a single value | ||||
|             intervals = [grouping, 0] | ||||
|         active_interval = intervals.pop(0) | ||||
|         int_part_gd = '' | ||||
|         for cnt, digit in enumerate(int_part[::-1]): | ||||
|             if cnt and not cnt % grouping: | ||||
|         cnt = 0 | ||||
|         for digit in int_part[::-1]: | ||||
|             if cnt and cnt == active_interval: | ||||
|                 if intervals: | ||||
|                     active_interval = intervals.pop(0) or active_interval | ||||
|                 int_part_gd += thousand_sep[::-1] | ||||
|                 cnt = 0 | ||||
|             int_part_gd += digit | ||||
|             cnt += 1 | ||||
|         int_part = int_part_gd[::-1] | ||||
|     return sign + int_part + dec_part | ||||
|   | ||||
| @@ -1943,12 +1943,28 @@ no grouping will be applied to the number. If this setting is greater than | ||||
| ``0``, then :setting:`THOUSAND_SEPARATOR` will be used as the separator between | ||||
| those groups. | ||||
|  | ||||
| Some locales use non-uniform digit grouping, e.g. ``10,00,00,000`` in | ||||
| ``en_IN``. For this case, you can provide a sequence with the number of digit | ||||
| group sizes to be applied. The first number defines the size of the group | ||||
| preceding the decimal delimiter, and each number that follows defines the size | ||||
| of preceding groups. If the sequence is terminated with ``-1``, no further | ||||
| grouping is performed. If the sequence terminates with a ``0``, the last group | ||||
| size is used for the remainder of the number. | ||||
|  | ||||
| Example tuple for ``en_IN``:: | ||||
|  | ||||
|     NUMBER_GROUPING = (3, 2, 0) | ||||
|  | ||||
| Note that if :setting:`USE_L10N` is set to ``True``, then the locale-dictated | ||||
| format has higher precedence and will be applied instead. | ||||
|  | ||||
| See also :setting:`DECIMAL_SEPARATOR`, :setting:`THOUSAND_SEPARATOR` and | ||||
| :setting:`USE_THOUSAND_SEPARATOR`. | ||||
|  | ||||
| .. versionchanged:: 1.11 | ||||
|  | ||||
|     Support for non-uniform digit grouping was added. | ||||
|  | ||||
| .. setting:: PREPEND_WWW | ||||
|  | ||||
| ``PREPEND_WWW`` | ||||
|   | ||||
| @@ -166,7 +166,8 @@ Generic Views | ||||
| Internationalization | ||||
| ~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| * ... | ||||
| * Number formatting and the :setting:`NUMBER_GROUPING` setting support | ||||
|   non-uniform digit grouping. | ||||
|  | ||||
| Management Commands | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|   | ||||
| @@ -576,6 +576,18 @@ class FormattingTests(SimpleTestCase): | ||||
|             self.assertEqual('-66666.6', nformat(-66666.666, decimal_sep='.', decimal_pos=1)) | ||||
|             self.assertEqual('-66666.0', nformat(int('-66666'), decimal_sep='.', decimal_pos=1)) | ||||
|             self.assertEqual('10000.0', nformat(self.l, decimal_sep='.', decimal_pos=1)) | ||||
|             self.assertEqual( | ||||
|                 '10,00,00,000.00', | ||||
|                 nformat(100000000.00, decimal_sep='.', decimal_pos=2, grouping=(3, 2, 0), thousand_sep=',') | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 '1,0,00,000,0000.00', | ||||
|                 nformat(10000000000.00, decimal_sep='.', decimal_pos=2, grouping=(4, 3, 2, 1, 0), thousand_sep=',') | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 '10000,00,000.00', | ||||
|                 nformat(1000000000.00, decimal_sep='.', decimal_pos=2, grouping=(3, 2, -1), thousand_sep=',') | ||||
|             ) | ||||
|             # This unusual grouping/force_grouping combination may be triggered by the intcomma filter (#17414) | ||||
|             self.assertEqual('10000', nformat(self.l, decimal_sep='.', decimal_pos=0, grouping=0, force_grouping=True)) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user