Return the ordinal word for n (e.g. 1 → 'first', 5 → 'fifth', 21 → 'twenty-first').
(n: int)
| 201 | # ───────────────────────────────────────────── |
| 202 | |
| 203 | def _ordinal_suffix(n: int) -> str: |
| 204 | """Return the ordinal word for n (e.g. 1 → 'first', 5 → 'fifth', 21 → 'twenty-first').""" |
| 205 | word = number_to_words(n) |
| 206 | # For hyphenated compounds like "twenty-one", convert only the last part |
| 207 | if "-" in word: |
| 208 | prefix, last = word.rsplit("-", 1) |
| 209 | joiner = "-" |
| 210 | else: |
| 211 | parts = word.rsplit(" ", 1) |
| 212 | prefix, last, joiner = (parts[0], parts[1], " ") if len(parts) == 2 else ("", parts[0], "") |
| 213 | |
| 214 | # Check exception table |
| 215 | for base, ordinal in _ORDINAL_EXCEPTIONS.items(): |
| 216 | if last == base: |
| 217 | last_ord = ordinal |
| 218 | break |
| 219 | else: |
| 220 | # General rule |
| 221 | if last.endswith("t"): |
| 222 | last_ord = last + "h" |
| 223 | elif last.endswith("e"): |
| 224 | last_ord = last[:-1] + "th" |
| 225 | else: |
| 226 | last_ord = last + "th" |
| 227 | |
| 228 | return f"{prefix}{joiner}{last_ord}" if prefix else last_ord |
| 229 | |
| 230 | |
| 231 | def expand_ordinals(text: str) -> str: |
no test coverage detected