diff --git a/babel/units.py b/babel/units.py index 7aa8cd3b7..f876263c3 100644 --- a/babel/units.py +++ b/babel/units.py @@ -121,7 +121,7 @@ def format_unit( .. versionadded:: 2.2.0 - :param value: the value to format. If this is a string, no number formatting will be attempted. + :param value: the value to format. If this is a string, no number formatting will be attempted and the number is assumed to be singular for the purposes of unit formatting. :param measurement_unit: the code of a measurement unit. Known units can be found in the CLDR Unit Validity XML file: https://unicode.org/repos/cldr/tags/latest/common/validity/unit.xml @@ -137,7 +137,6 @@ def format_unit( q_unit = _find_unit_pattern(measurement_unit, locale=locale) if not q_unit: raise UnknownUnitError(unit=measurement_unit, locale=locale) - unit_patterns = locale._data["unit_patterns"][q_unit].get(length, {}) if isinstance(value, str): # Assume the value is a preformatted singular. formatted_value = value @@ -146,8 +145,23 @@ def format_unit( formatted_value = format_decimal(value, format, locale, numbering_system=numbering_system) plural_form = locale.plural_form(value) - if plural_form in unit_patterns: - return unit_patterns[plural_form].format(formatted_value) + unit_patterns = locale._data["unit_patterns"][q_unit] + + # We do not support `` tags at all while ingesting CLDR data, + # so these aliases specified in `root.xml` are hard-coded here: + # + # + lengths_to_check = [length] + if length in ("long", "narrow"): + lengths_to_check.append("short") + + for real_length in lengths_to_check: + length_patterns = unit_patterns.get(real_length, {}) + # Fall back from the correct plural form to "other" + # (this is specified in LDML "Lateral Inheritance") + pat = length_patterns.get(plural_form) or length_patterns.get("other") + if pat: + return pat.format(formatted_value) # Fall back to a somewhat bad representation. # nb: This is marked as no-cover, as the current CLDR seemingly has no way for this to happen. diff --git a/tests/test_units.py b/tests/test_units.py index 7c6ad6b4d..27b7535fe 100644 --- a/tests/test_units.py +++ b/tests/test_units.py @@ -17,3 +17,15 @@ ]) def test_new_cldr46_units(unit, count, expected): assert format_unit(count, unit, locale='cs_CZ') == expected + + +@pytest.mark.parametrize('count, unit, locale, length, expected', [ + (1, 'duration-month', 'et', 'long', '1 kuu'), + (1, 'duration-minute', 'et', 'narrow', '1 min'), + (2, 'duration-minute', 'et', 'narrow', '2 min'), + (2, 'digital-byte', 'et', 'long', '2 baiti'), + (1, 'duration-day', 'it', 'long', '1 giorno'), + (1, 'duration-day', 'it', 'short', '1 giorno'), +]) +def test_issue_1217(count, unit, locale, length, expected): + assert format_unit(count, unit, length, locale=locale) == expected