Skip to content

Commit 345c797

Browse files
authored
Implement long/narrow -> short fallback in babel.units (#1225)
Also implemented fallback from the correct pluralization to "other", which was also missing. Fixes #1217.
1 parent 326c3bf commit 345c797

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

babel/units.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def format_unit(
121121
122122
.. versionadded:: 2.2.0
123123
124-
:param value: the value to format. If this is a string, no number formatting will be attempted.
124+
: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.
125125
:param measurement_unit: the code of a measurement unit.
126126
Known units can be found in the CLDR Unit Validity XML file:
127127
https://unicode.org/repos/cldr/tags/latest/common/validity/unit.xml
@@ -137,7 +137,6 @@ def format_unit(
137137
q_unit = _find_unit_pattern(measurement_unit, locale=locale)
138138
if not q_unit:
139139
raise UnknownUnitError(unit=measurement_unit, locale=locale)
140-
unit_patterns = locale._data["unit_patterns"][q_unit].get(length, {})
141140

142141
if isinstance(value, str): # Assume the value is a preformatted singular.
143142
formatted_value = value
@@ -151,8 +150,21 @@ def format_unit(
151150
)
152151
plural_form = locale.plural_form(value)
153152

154-
if plural_form in unit_patterns:
155-
return unit_patterns[plural_form].format(formatted_value)
153+
unit_patterns = locale._data["unit_patterns"][q_unit]
154+
155+
# We do not support `<alias>` tags at all while ingesting CLDR data,
156+
# so these aliases specified in `root.xml` are hard-coded here:
157+
# <unitLength type="long"><alias source="locale" path="../unitLength[@type='short']"/></unitLength>
158+
# <unitLength type="narrow"><alias source="locale" path="../unitLength[@type='short']"/></unitLength>
159+
lengths_to_check = [length, "short"] if length in ("long", "narrow") else [length]
160+
161+
for real_length in lengths_to_check:
162+
length_patterns = unit_patterns.get(real_length, {})
163+
# Fall back from the correct plural form to "other"
164+
# (this is specified in LDML "Lateral Inheritance")
165+
pat = length_patterns.get(plural_form) or length_patterns.get("other")
166+
if pat:
167+
return pat.format(formatted_value)
156168

157169
# Fall back to a somewhat bad representation.
158170
# nb: This is marked as no-cover, as the current CLDR seemingly has no way for this to happen.

tests/test_units.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,15 @@
1717
])
1818
def test_new_cldr46_units(unit, count, expected):
1919
assert format_unit(count, unit, locale='cs_CZ') == expected
20+
21+
22+
@pytest.mark.parametrize('count, unit, locale, length, expected', [
23+
(1, 'duration-month', 'et', 'long', '1 kuu'),
24+
(1, 'duration-minute', 'et', 'narrow', '1 min'),
25+
(2, 'duration-minute', 'et', 'narrow', '2 min'),
26+
(2, 'digital-byte', 'et', 'long', '2 baiti'),
27+
(1, 'duration-day', 'it', 'long', '1 giorno'),
28+
(1, 'duration-day', 'it', 'short', '1 giorno'),
29+
])
30+
def test_issue_1217(count, unit, locale, length, expected):
31+
assert format_unit(count, unit, length, locale=locale) == expected

0 commit comments

Comments
 (0)