Skip to content

Fix English number normalizer: 'ninth' never normalized (generated 'nineth') - #2897

Open
PratikDhanave wants to merge 1 commit into
openai:mainfrom
PratikDhanave:fix/english-ordinal-ninth
Open

PratikDhanave wants to merge 1 commit into
openai:mainfrom
PratikDhanave:fix/english-ordinal-ninth

Conversation

@PratikDhanave

@PratikDhanave PratikDhanave commented Oct 26, 2026 •

Copy link
Copy Markdown

Summary

The English number normalizer never normalizes the ordinal "ninth", and breaks every compound ordinal ending in nine.

Problem

EnglishNumberNormalizer.ones_ordinal (whisper/normalizers/english.py) is generated by appending "th" to each cardinal, special-casing only words ending in "t":

name + ("h" if name.endswith("t") else "th")   # eight -> eighth

"nine" does not end in "t", so this produces the non-word key "nineth". The real ordinal "ninth" is therefore absent from the map, so it is left un-normalized:

input current expected
ninth ninth 9th
the ninth of may the ninth of may the 9th of may
twenty ninth 20 ninth 29th
ninety ninth 90 ninth 99th
one hundred ninth 100 ninth 109th

("nineth" — a string that never appears in real text — is present in the map, which confirms the generator simply targeted the wrong key.)

Fix

Special-case "ninth" explicitly, exactly like the other irregular ordinals (first/second/third/fifth/twelfth), and exclude 9 from the generated set:

             "fifth": (5, "th"),
+            "ninth": (9, "th"),
             "twelfth": (12, "th"),
             **{
                 name + ("h" if name.endswith("t") else "th"): (value, "th")
                 for name, value in self.ones.items()
-                if value > 3 and value != 5 and value != 12
+                if value > 3 and value not in (5, 9, 12)
             },

Validation

Added ordinal assertions to tests/test_normalizer.py (ninth, twenty ninth, ninety ninth, one hundred ninth).

  • Before the fix: assert std("ninth") == "9th" fails ('ninth' != '9th').
  • After the fix: all pass.
  • Full tests/test_normalizer.py passes (4 passed) with the change; the existing suite had no ordinal-ending-in-nine coverage, which is why this shipped.

Developed with AI assistance: the bug was located, the fix applied, and tests written and run locally (pytest). I have reviewed and verified the change and take responsibility for it.

…ineth')

EnglishNumberNormalizer.ones_ordinal is built by appending 'th' to each
cardinal (special-casing only words ending in 't', e.g. eight -> eighth).
'nine' does not end in 't', so the generated key is the non-word 'nineth',
and the real ordinal 'ninth' is absent from the map. As a result 'ninth' is
left un-normalized and any compound ordinal ending in nine is broken:

  'ninth'            -> 'ninth'   (expected '9th')
  'twenty ninth'     -> '20 ninth' (expected '29th')
  'ninety ninth'     -> '90 ninth' (expected '99th')
  'one hundred ninth'-> '100 ninth' (expected '109th')

Special-case 'ninth' explicitly (like first/second/third/fifth/twelfth) and
exclude 9 from the generated set. Add ordinal regression assertions.

@koksalenes koksalenes left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctly handles ordinal numbers and plural forms now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants