Skip to content
SpeakSay

Your AI Voice Reads "$1,499" as "One Four Nine Nine": The Numbers, Dates and Units Pass Nobody Runs (2026)

There are two kinds of text-to-speech pronunciation failure and almost everyone applies the wrong fix to one of them. A pronunciation dictionary will never fix a price, because there is no dictionary entry for "$1,499" — the model never sees a word there at all. This is the normalisation pass: what breaks, what to write instead, and the sixty-second test that grades any voice before you commit.

Admin5 min read
Your AI Voice Reads "$1,499" as "One Four Nine Nine": The Numbers, Dates and Units Pass Nobody Runs (2026)

1. Two failures wearing the same name

Everything called "TTS mispronunciation" is really two unrelated problems happening in two different places, and the fix for one does nothing for the other. This distinction is the whole article.

Lexicon problemsNormalisation problems
What breaksBrand names, surnames, place names, acronymsNumbers, currency, dates, times, ranges, units, ordinals, codes
WhereInside the model — it sees a word, predicts the wrong soundsBefore the model — the step converting written form to spoken form is wrong, or never runs
The fixA pronunciation dictionary entry or phonetic respellingRewriting the text so it is already spoken form
How oftenOnce, then it applies everywhere that word appearsEvery instance — unless you change how you write
Why the other fix failsRespelling a surname in the visible script is ugly and inconsistentThere is no dictionary entry for "$1,499". There is no word there to look up.

Read that last cell again, because it is where the hours go. People open the pronunciation dictionary, type in a price, nothing changes, so they try a different voice, then a different platform. It was never going to work: a lexicon maps words to sounds, and "$1,499" is not a word. Something has to decide, before any acoustic work happens, that this string means "one thousand four hundred and ninety-nine dollars" — and that something is a text normalisation step, upstream of everything a voice setting can touch.

When it is missing, incomplete, disabled or wrong for your locale, the model receives characters with no word-level interpretation and does the only thing it can: reads the characters. The voice is fine. The model is fine. The audio is clean, confident and completely wrong.

SpeakSay's companion piece — "AI Voiceover Mispronouncing Names, Acronyms & Numbers? 7 Fixes for Perfect Pronunciation" — is the lexicon post, for brand names and dictionaries. This is the normalisation post. From here we only discuss things made of digits and symbols.

2. Why nothing in your workflow catches it

An April 2026 benchmark of commercial text-to-speech systems tested how widely used engines handle non-standard text — dates, currencies, phone numbers, identifiers and around twenty-seven other categories — with no preprocessing applied. More than sixty per cent of test sentences came back handled incorrectly by some of the most popular systems. Mispronunciation of numbers, brand names and proper nouns is separately the most frequently reported concrete TTS complaint across issue trackers, review sites and forums.

The sixty per cent is alarming. What makes it dangerous is the finding attached to it: nothing in a standard monitoring stack flags the error.

  • Did the render complete? Yes — normalisation failures never throw errors.
  • Is the file the expected length? Roughly. "One four nine nine" takes about as long to say as "fourteen ninety-nine".
  • Is the audio clean? Perfectly. No clipping, no artefacts, confident delivery.
  • Does an auto-transcript match? Often yes — the transcriber normalises in the other direction and hands "1499" back.
  • Did someone proofread the script? Yes, and that is the trap: the script is correct. The error does not exist in the text. It exists only in the audio.

So it ships — and it ships specifically in your highest-stakes sentences, because those are the ones made of non-standard text.

SentenceContainsCost of getting it wrong
The priceCurrency, separators, decimalsListener mishears the offer, or distrusts it
The deadlineNumeric date, ordinal, timeMissed conversions, support tickets
The discount codeAlphanumeric identifierCode unusable; the campaign leaks
The phone numberDigit groups, punctuationNobody can call you
The dosage or specUnits, decimals, rangesReal-world harm in regulated verticals
The model or versionVersion stringsYou sound like you do not know the product
"Here's why it matters"Ordinary wordsRenders perfectly, every time

Your filler renders flawlessly. Your call to action is the coin flip.

Two structural facts before you assume your platform handles it. Some platforms implement normalisation for only a minority of the languages they support — one documented case covers twelve of ninety-four — so outside a short list of major languages you are doing the preprocessing yourself whether you know it or not. And on some platforms, number normalisation ships switched off by default on the fastest model tiers, because it costs latency. Moving to a faster model can silently disable the thing that was reading your prices correctly.

Test this on your own price, right now, for free

Do not take a benchmark's word for it. Paste the actual sentence containing your actual price into SpeakSay's free tools and listen to what comes back. Sixty seconds, and you will know whether you have this problem.

Try the free tools →

3. The reference table: what to write instead

The middle column is the failure pattern to expect when normalisation is absent, partial or locale-mismatched. The right column is plain English with no markup, deliberately — it works on every engine, voice, tier and model version, because it depends on no normalisation step running at all.

CategoryYou wroteWhat you often getWrite this instead
Currency, thousands separator$1,499"one four nine nine"; "one comma four nine nine"; the figure with no "dollars"one thousand four hundred and ninety-nine dollars
Currency with decimals£24.99"pound twenty four point nine nine"twenty-four pounds ninety-nine
Abbreviated large currency$2.5M"two point five em"two point five million dollars
Percentages17.5%"seventeen point five percent sign"seventeen point five per cent
Ranges (en-dash, hyphen)20–30 minutes / 2-5 days"twenty dash thirty"; "two hyphen five"; "twenty minus thirty"twenty to thirty minutes / two to five days
Numeric date, either order03/04/2026"zero three slash zero four slash…" — or it resolves to the wrong one of 3 April / March 4the third of April twenty twenty-six
Times, 12-hour4:30pm"four colon thirty pm"half past four in the afternoon
Times, 24-hour14:05"fourteen colon zero five"; "fourteen five"two oh five in the afternoon
Phone numbers+44 20 7123 4567"plus forty-four twenty seven thousand one hundred twenty three…"plus four four, two zero, seven one two three, four five six seven
Large round numbers1,000,000"one comma zero zero zero comma zero zero zero"one million
Version stringsv2.5 / iOS 26.1"vee twenty-five"; "iOS twenty-six one"version two point five / iOS twenty-six point one
Measurements and units12km / 4.5kg / 22°C"twelve kay em"; "four point five kay gee"; "twenty two degree see"twelve kilometres / four and a half kilograms / twenty-two degrees Celsius
Compound units1,200 ft² / 5000mAh"twelve hundred ef tee two"; "five thousand em ay aitch"twelve hundred square feet / a five thousand milliamp-hour battery
Ordinals1st, 3rd, 21st"one st"; "three rd"; "twenty-one st"first, third, twenty-first
Fractions, mixed numbers1/2, 3/4, 2½"one slash two"; "three over four"; "two", the glyph droppeda half, three quarters, two and a half
Negative temperatures-5°C"dash five degrees" — or the sign dropped, inverting your meaningminus five degrees Celsius
URLsspeaksay.com/toolsOften right; sometimes the domain as one unparsable tokenspeaksay dot com slash tools
Email addresseshello@speaksay.comOften right; sometimes "hello a speaksay", symbol droppedhello at speaksay dot com
Alphanumeric codesSAVE20 / A1B2C3"save twenty" — or was it two zero? Digits run together too fast to write downS-A-V-E, two zero / A one, B two, C three
Serial identifiersOrder #10024"order hash ten thousand twenty four" — plausible, and not what you meantorder number one zero zero two four

Three patterns generalise beyond the table. Symbols are the weak link, not digits — most engines handle a bare integer; what breaks them is the currency sign, the separator, the dash, the degree mark, the colon, each an instruction the normaliser must interpret, and each uninterpreted symbol is either spoken as a word or dropped. Dropped symbols are worse than mispronounced ones: "dash five degrees" is merely odd, while "five degrees" for -5°C has reversed your meaning and sounds perfect doing it. And digit strings need comma pacing — when you do want digits read individually, commas create the pauses a listener needs to capture the sequence.

4. Language is not locale: the date-order trap

Normalisation on many platforms is implemented per language, not per locale. English is English, so en-US and en-GB normalise identically — fine for almost all text, quietly catastrophic for the two categories where they flatly disagree: date order and currency phrasing.

You select a British voice. You write "03/04/2026". The voice is unmistakably British and reads it as March fourth. You meant the third of April. Nobody catches it, because the British voice sounded British and the date sounded like a date.

ConventionUSUKGermanyFranceIndia
Numeric date orderMM/DD/YYYYDD/MM/YYYYDD.MM.YYYYDD/MM/YYYYDD/MM/YYYY
Decimal markpoint (1.5)point (1.5)comma (1,5)comma (1,5)point (1.5)
Thousands separatorcomma (1,000)comma (1,000)point (1.000)space (1 000)lakh/crore (1,00,000)
Currency word order"twenty-four ninety-nine""twenty-four pounds ninety-nine"amount then unitamount then unit"…rupees fifty paise"
Symbol positionbefore ($10)before (£10)after (10 €)after (10 €)before (₹10)
109 is calledbillionbillionMilliarde (billion = 1012)milliard (billion = 1012)billion; 100 crore
24-hour defaultnomixedyesyesmixed
  1. Never write a bare numeric date in a script. Not for any audience, in any language. "The third of April" costs four syllables and cannot be misread by any engine in any locale. This single rule eliminates the highest-consequence normalisation error there is.
  2. Watch the billion/milliard row if you localise financial content. A German or French "billion" is a thousand times larger than the English one — a factual error in your copy, not a pronunciation problem.
  3. Do not trust a locale tag to carry the decimal comma. Write "1.5 kg" in a German script and a normaliser reading the point as a thousands separator has you saying fifteen hundred kilograms.

Picking a voice picks an accent. It does not pick a set of numeric conventions. Those two things feel like they should travel together and they do not.

5. The real fix: write it spoken from the start

Everything above is a patch list, and patching is what you will do to your existing catalogue. But it is not the real fix, because patching is per-instance and forever.

The real fix is a change in how you write, and it is free. Your script is not a document. It is an interface. Nobody reads it; its only job is to be converted into speech, so the correct form for every character in it is the spoken form. Written form exists for readers who benefit from the compression, and there is no reader — only a machine that has to expand it again, and the expansion is the unreliable step.

Before (written for a reader):

The Pro model starts at $1,499 — that's 17.5% off the RRP until 03/04/2026. It ships with a 5000mAh battery, weighs 1.2kg, and runs for 20–30 hours. Firmware v2.5 arrives in Q1. Pre-order before 4:30pm ET on the 1st and use code SAVE20, or call +44 20 7123 4567.

After (written for a voice):

The Pro model starts at one thousand four hundred and ninety-nine dollars — that's seventeen and a half per cent off the recommended price, until the third of April twenty twenty-six. It ships with a five thousand milliamp-hour battery, weighs one point two kilograms, and runs for twenty to thirty hours. Firmware version two point five arrives in the first quarter. Pre-order before half past four in the afternoon, Eastern time, on the first — and use code S-A-V-E, two zero. Or call us on plus four four, two zero, seven one two three, four five six seven.

The second version is longer on the page and identical in duration when spoken, because "one thousand four hundred and ninety-nine dollars" takes exactly as long to say whichever way you typed it. You added no runtime and removed nine opportunities for silent failure, at the writing stage where it costs nothing rather than the QA stage where it costs a re-render. It also reads better: "seventeen and a half per cent" is how a person talks, "17.5%" is how a spreadsheet talks.

Some voices handle figures far better than others

Normalisation quality varies enormously between voices and model tiers, and the only way to know is to hear your own numbers read back. Run the benchmark below across a few voices and cast the one that gets your prices right — that is a real casting criterion.

Browse the voice library →

6. The sixty-second benchmark paragraph

Before committing a series or a client project to a voice or tier, grade it. Paste these twelve lines exactly as written — numerals, not spoken forms — into the text-to-speech tool and listen.

1.  The Pro plan costs $1,499, or £24.99 a month.
2.  That is 17.5% off, and margins rose 2.5M dollars.
3.  Delivery takes 20-30 days, or 2–5 days express.
4.  The deadline is 03/04/2026, before 4:30pm.
5.  Doors open at 14:05 and close at 09:00.
6.  Call +44 20 7123 4567 or 1-800-555-0199.
7.  We passed 1,000,000 users and 1,250 partners.
8.  Update to v2.5 on iOS 26.1 or Android 17.
9.  It weighs 4.5kg, covers 12km, and holds 5000mAh.
10. The room is 1,200 ft² and sits at 22°C, or -5°C outside.
11. Our 1st, 3rd and 21st attempts used 1/2 and 2½ units.
12. Email hello@speaksay.com or use code SAVE20 at speaksay.com/tools.

The scoring rule. Listen once and mark each line pass or fail. A line fails if any value in it would be misunderstood by a listener who cannot see the text. That is the whole standard, and it is deliberately strict: a price is either the price or it is not.

ScoreWhat it meansWhat to do
11–12 passStrong normalisation for this language and tierWrite naturally, spot-check the digits pass, keep the control render
8–10 passTypical — common cases fine, symbols and locale breakWrite dates, currency and codes in spoken form as standing policy
4–7 passPartial normalisationWrite everything numeric as words; check whether you are on a fast tier with normalisation off
0–3 passNo meaningful normalisation for this languageSpoken form is mandatory — the expected result in many non-major languages

Run it per voice and per tier, not per platform: a flagship model and a fast model can score very differently. Run it per language; your English score tells you nothing about your Spanish score. Save the render with the date and settings in the filename, because it becomes your control for the next section. The paragraph is deliberately ugly — it is not content, it is an instrument.

7. The digits-only QA pass

A full listen-through of every render is correct advice that almost nobody follows. Here is a targeted pass that catches most normalisation errors in a fraction of the time. Three rules.

  1. Listen. Never read. Proofreading is the trap, because the script is correct. Every minute reading it confirms the one thing that was never wrong.
  2. Listen only to lines containing digits. Put all your attention on the two per cent of the script carrying ninety per cent of the risk.
  3. Check the rendered audio, and check the exported file. Where a browser preview and an export can differ, verify the artefact you are publishing.

Find the lines by searching, not by eye. In any editor, enable regex in find-and-replace and search [0-9] with "highlight all" — you get a map of exactly where your risk is, usually six to twelve lines in a two-thousand-word script. A broader [0-9$£€%°#/@] also catches a stray dash in "20–30" where the digits were already spelled out. On the command line, grep -n '[0-9]' script.txt lists the lines to listen to. Note the timecodes before you press play and scrub to each one; twelve lines take about ninety seconds.

Work from the top by consequence: price, deadline, phone number, code, dosage, then the rest. And adopt one rule permanently: no script ships with a figure in it that has never been heard out loud by a human. Not reviewed — heard.

8. Why your fixes regress without warning

You fix the price. It reads correctly. Six weeks later it reads wrong again and you did not touch the script. This happens because normalisation behaviour belongs to the model version, not to the voice. The voice name is a front-end label; the normalisation step is part of the inference pipeline behind it. When a platform updates a model — routine, usually desirable, often unannounced — the voice can sound essentially the same while the preprocessing changes. A rule that expanded "£24.99" correctly may now behave differently; a locale default may shift; a fast tier may gain or lose a setting.

That is worse for a catalogue than a single clip. Re-render an old episode after a model change — to fix a typo, swap a sponsor read, bump the loudness — and its numbers are now normalised by a different pipeline than the rest of the series.

  1. Keep a dated control paragraph. The twelve lines above are the right content. Render them the day you commit to a voice and save with voice, tier, language and date in the filename: control_en-GB_flagship_2026-09-27.mp3.
  2. Re-render on a trigger, not a schedule. A changelog entry, a new voice in the library, a tier change, or a render that sounds subtly different.
  3. Compare line by line. Ninety seconds. Any line that changed tells you which category moved.
  4. Convert any regressed category to spoken form permanently. This is the ratchet: your writing rules absorb every category the platform has ever got wrong, so scripts become progressively immune to model changes rather than more exposed.

Text you wrote as words has no normalisation behaviour to regress. "One thousand four hundred and ninety-nine dollars" reads the same on every model version that has existed and every one that will.

9. Numbers in a second language

If you publish in more than one language, assume the problem is worse outside your main one — as a default, not an exception. Normalisation is hand-built, language-specific engineering, and those rules do not transfer between languages. It is unglamorous work, done first for the languages with the most commercial volume — hence platforms supporting ninety-plus languages for synthesis while implementing normalisation for a fraction of them.

  • Your English score does not generalise. Run the benchmark separately in every language you publish in, and expect materially lower scores in each secondary one.
  • Default to manual spoken form in secondary languages. Write every figure as words from the start and treat a correct automatic reading as a bonus.
  • Translating a script does not translate its number conventions. This is the one that catches people. A translator, human or machine, faithfully renders your sentence into German and leaves "$1,499" and "03/04/2026" untouched, because they are not words and there is nothing to translate. Your German script now has an American date order, a dollar-first symbol position and a decimal point in a decimal-comma locale — and the translation looks complete.
  • Localise the figures as an explicit separate step. After translation, run the digits pass with the locale table open: convert dates to words in the target convention, fix currency word order and decimal marks, check the billion/milliard trap in anything financial.
  • Have a native speaker hear the numbers, not read them. If you get five minutes an episode, spend them on the digit lines.

10. Automating it at volume

If you render programmatically from a template, CMS, spreadsheet or LLM, manual fixing does not scale. Normalise at generation, not at synthesis. Insert a conversion step wherever your script text is produced, before it is ever sent to the voice. Instead of depending on a vendor's undocumented, version-dependent normaliser, you depend on your own code, which you can test, version and fix. The engine receives words, and words are the one input every engine handles.

  1. Handle structured fields explicitly. Prices, dates and quantities from a database arrive as typed values. Format them to spoken strings at templating time — {{price_spoken}}, not {{price}} — using a locale-aware number-to-words library rather than string concatenation.
  2. Then pattern-match the free text. Order matters: expand currency symbols before stripping punctuation, and handle ranges before individual numbers, or "20–30" becomes two separate values.
  3. Fail loudly on anything left over. The most valuable piece and the one most often skipped. After conversion, scan the outgoing text for any remaining digit or risky symbol and raise a warning with the line number. You have just built the monitoring that section two said does not exist, in roughly one regular expression.
  4. Keep a per-channel spoken-form style sheet, versioned next to your scripts, so output stays consistent across writers, languages and time.
Style sheet entryExample decisionWhy decide it once
Currency phrasing"twenty-four pounds ninety-nine"Two writers will otherwise differ inside one series
Date format"the third of April twenty twenty-six"Removes locale ambiguity permanently
Year reading"twenty twenty-six", not "two thousand and twenty-six"Both valid; only one matches your register
Version numbers"version two point five""vee two five" and "version twenty-five" are both wrong and both common
Code pacingLetters hyphenated, digits comma-separatedDecides whether a listener can write the code down
Clock convention12-hour with am/pm for consumer, 24-hour for operationalPrevents "fourteen colon zero five" ever appearing
UnitsSpelled out always, abbreviated never"kay gee" is the most common unit failure
Approximation policyRound in ad reads; exact figures on screenSometimes the right fix is not to say the number

One operational rule with real money attached: never move a pipeline containing figures onto a faster or cheaper tier without re-running the benchmark. Latency-optimised tiers are exactly where normalisation is most likely to be off by default, and a tier change that halves your render cost while silently reading every price as a digit string is not a saving.

Pick the tier that gets your figures right, then stop thinking about it

Once you know which voice and model tier passes your benchmark, the only remaining question is volume — and that maths is simpler than the normalisation maths. Compare what you actually need, or remove the monthly calculation entirely with the lifetime plan.

Compare plans →

11. Honest limits: what you cannot fix from the script

Spoken-form writing solves most of this category, not all of it. What remains:

  • Prosody within a long figure. You control the words, not the rhythm across them. A human puts a small lift on "fourteen" and a settle on "ninety-nine"; many engines deliver a flat, evenly stressed chain. No respelling gets you there.
  • Pause placement inside digit sequences. Commas help and are not precise. You are negotiating with the engine's punctuation handling rather than specifying timing.
  • Stress that carries meaning. "It's only nine ninety-nine" and "it's only nine ninety-nine" mean different things, and emphasis inside numbers is largely not addressable from plain text.
  • Genuinely ambiguous values. No engine can know whether "SAVE20" is "save twenty" or "save two zero" — which means this was always your problem.

When you hit one of these, the answer is not another respelling. It is to change the sentence.

  1. Rewrite to avoid the construction. "Just under fifteen hundred dollars" is warmer, shorter, more persuasive and completely un-manglable compared with an exact price read. "Early April" beats a date. "About twenty minutes" beats "20–30 minutes". For much marketing and narrative content the approximate version is better copy anyway — the precision was a habit, not a requirement.
  2. Put the exact figure on screen and say it approximately. This is what broadcast has always done. The voice says "just under fifteen hundred dollars"; the lower third says "$1,499". The listener gets the feel, the viewer gets the number, and the engine never touches a string it can break. For phone numbers, codes and long identifiers this is close to mandatory: a listener cannot reliably capture an eleven-digit number by ear however perfectly it is read, so reading it aloud was never the right design.

Know when precision is genuinely load-bearing, though. In regulated, medical, legal and technical-specification content the approximation route is closed, and the requirement escalates instead: write the exact spoken form, have a human hear it, keep the control render, and do not use a fast tier. The cost of the pass rises because the cost of the error does.

12. FAQ

Why does my AI voice read numbers wrong?

Because text normalisation — the step converting written numerals into spoken words — either did not run, ran incompletely, or applied the wrong locale's rules. It happens before the voice model does any work, which is why changing voices rarely helps. Without it, the model receives characters with no word-level interpretation and reads them individually, so "$1,499" becomes "one four nine nine". The fix is to write the figure as words in the script.

Will a pronunciation dictionary fix a price or a date?

No. A pronunciation dictionary maps words to sounds, and "$1,499" is not a word — there is no entry to create. Dictionaries are the correct fix for brand names, surnames and acronyms, which fail inside the model. Numbers, dates, currency and units fail before the model, in normalisation, and the only reliable fix is rewriting the text in spoken form.

How do I make text to speech read numbers correctly?

Write them as words: "one thousand four hundred and ninety-nine dollars" instead of "$1,499", "the third of April twenty twenty-six" instead of "03/04/2026", "twenty to thirty minutes" instead of "20–30 minutes", "twelve kilometres" instead of "12km". This adds no runtime, because the spoken duration is identical, and it cannot regress when the platform updates its model.

Why did my British voice read the date in American order?

Because normalisation on many platforms is implemented per language rather than per locale, so en-US and en-GB normalise identically despite using opposite date orders. Selecting a British voice selects an accent, not a set of numeric conventions. The permanent fix is never to write a bare numeric date — write "the third of April" and no engine in any locale can misread it.

Why does the same script suddenly read a price differently than last month?

Because normalisation behaviour is a property of the model version, not of the voice. A platform update can change how figures are expanded while the voice still sounds the same, and it is rarely announced in terms you would connect to your prices. Keep a dated control render of a fixed test paragraph, re-render it whenever you notice a model change, and move any regressed category into spoken form permanently.

Does text to speech handle currency and dates in every language?

No. Some platforms implement normalisation for only a minority of the languages they support — one documented case covers twelve of ninety-four — so outside a short list of major languages, assume numbers, currency and dates need manual spoken-form writing. Translating a script does not translate its number conventions either: a translator leaves "$1,499" and "03/04/2026" untouched, because they are not words.

How do I test whether a voice reads numbers properly before committing?

Paste a twelve-line test paragraph containing one instance of each problem category — currency, percentages, ranges, numeric dates, 12- and 24-hour times, phone numbers, large round numbers, version strings, units, ordinals, fractions, negative temperatures and alphanumeric codes — and listen once, marking each line pass or fail. A line fails if any value would be misunderstood by a listener who cannot see the text. Run it per voice, per tier and per language.

Should I read a phone number or discount code aloud at all?

Usually not. Even perfectly normalised, a listener cannot reliably capture a long digit sequence by ear, so reading it aloud was never good design. Put the exact value on screen or in the description and have the voice say something approximate and memorable. If you must read it, separate the digits with commas so the pauses land where a listener needs them.

Pro tip: before your next render, search your script for a single digit — [0-9] in any find box with regex enabled — and convert every match to words. It is the fastest quality improvement available in text-to-speech, it takes about four minutes on a two-thousand-word script, and it permanently closes the one failure class no error message will ever warn you about. Render your fixed script on SpeakSay, or start with the free tools.

Give your words a voice

Start free with 10,000 credits. No credit card required.