On this page
Why Arabic TTS misreads numbers
A string such as "AED 1,250" or "15/11" gives a TTS engine almost nothing to work with. It has to decide which language the digits are in, how the currency code is pronounced, whether the number agrees with a masculine or feminine noun, and whether the slash means a date or a fraction. Each decision is a chance to read the number in English, in formal Arabic on a casual call, or not at all.
The vendors say so themselves. ElevenLabs' help centre has a whole article on why numbers, dates, symbols and acronyms get mispronounced or read in the wrong language (ElevenLabs help centre). It recommends writing them out in words, prompting the LLM to do that, or turning on its text normalisation, the step that converts digits and symbols into words, which it notes adds latency. A Deepgram article on multilingual voice agents (February 2026) adds that phone numbers, addresses and IDs need "language-specific pronunciation rules" (Deepgram).
Open Arabic models show the same gap. The model card for NAMAA-Egyptian-TTS, an open Egyptian Arabic voice, lists "Numbers are sometimes not uttered correctly" among its known limitations (NAMAA-Egyptian-TTS). The safe assumption, whatever engine you use, is that numbers should reach it already turned into the words you want spoken. The same is true of Hindi TTS and rupee amounts, where lakh and crore add a grouping problem of their own.
Dirham and riyal prices: currency in words, number agreeing with it
Formal Arabic makes the counted noun change with the number. Numbers 3 to 10 take a plural noun with reversed gender agreement, 11 to 99 take a singular noun in the accusative, and 100 and 1,000 take a singular noun in the genitive. In MSA, 1,250 dirhams is ألف ومئتان وخمسون درهمًا, with the units before the tens as Arabic always orders them.
Spoken Arabic simplifies all of this. Wikipedia's summary of Arabic grammar notes that the formal system is rarely used in practice for large numbers, which people read in a simpler spoken form (Arabic grammar). A Gulf caller hears ألف ومتين وخمسين درهم, and a Riyadh caller hears ثلاث مية وخمسة وسبعين ريال ونص for 375.50 riyals. Pick the register that matches the rest of the call, and keep it for every number.
Small units need a rule too. Most calls round fils and halalas away or use a fraction word: ريال ونص for half a riyal, or درهم وربع for a quarter. When the exact amount matters, as in a bill or a refund, say both units, as in ثلاث مية ريال وخمسين هللة, and keep the same style throughout the call.
Write the currency as a word, not a code or a symbol. AED and SAR invite an English reading, and both currencies now have their own signs. The Saudi riyal sign was approved on 20 February 2025 and encoded as U+20C1 in Unicode 17.0, released on 9 September 2025 (Saudi riyal sign; Unicode blog). The UAE dirham sign was unveiled by the Central Bank on 27 March 2025 and encoded as U+20C3 in Unicode 18.0 (Emirati dirham sign), released on 16 September 2026 (Unicode 18.0). Both signs go before the amount, and fonts and text pipelines are still catching up, so a normaliser written before then may not recognise them at all.
The samples below are read by Nour and Tariq, the Modern Standard Arabic voices on Sonex Labs' Arabic text-to-speech page. The dialect comes from the words written, so the Gulf and Najdi lines use Gulf and Najdi words in a standard voice; a native local accent needs a voice cloned from a 10-second sample of a local speaker. The Gulf Arabic and Najdi Arabic pages have more examples.
المبلغ المستحق AED 1,250، وآخر موعد للسداد 15/11/2026.
المبلغ المستحق ألف ومئتان وخمسون درهمًا، وآخر موعد للسداد الخامس عشر من نوفمبر.
المبلغ ألف ومتين وخمسين درهم، وآخر يوم للدفع خمستعش نوفمبر.
المبلغ ثلاث مية وخمسة وسبعين ريال ونص، وتقدر تسدده من التطبيق الحين.
Dates and times: say the month the way your callers do
Arabic has more than one set of names for the Gregorian months, and callers notice the wrong one. Egypt, Sudan and the Gulf use names based on the Latin ones, such as يناير and فبراير. Iraq, Syria, Jordan, Lebanon and Palestine mainly use Syriac-derived names such as كانون الثاني and شباط. Algeria and Tunisia use names based on French, such as جانفي and فيفري, and Morocco has its own set (Arabic names of calendar months). The Wikipedia article marks some of these claims as needing citations, so confirm the choice with a local speaker for each market.
Numeric dates are worse, because 15/11 is day first in most Arab markets and month first to anyone thinking in US format. Write the date in words: الخامس عشر من نوفمبر in MSA, or خمستعش نوفمبر on a Gulf call. If a date is in the Hijri calendar, name the month (رمضان, شوال) so the caller knows which calendar you mean.
Times read best as words too. Sonex Labs' own Gulf Arabic page recommends "الساعة أربع العصر" (four in the afternoon) over 16:00. Spoken Arabic marks the part of the day rather than using a 24-hour clock, so "الصبح", "الظهر", "العصر" and "الليل" do the work that a.m. and p.m. do in English.
Phone numbers and IDs are read digit by digit, in groups
A phone number is a string of digits, not a quantity, and should never be read as one. UAE mobiles are written 05x xxx xxxx locally, ten digits with the leading zero, and +971 internationally. Saudi mobiles also start with 05 and run to ten digits, with +966 as the country code. Read them as single digits in the groups people write them in, with a short pause between groups.
IDs follow the same rule with their own grouping. An Emirates ID has 15 digits in the pattern 784-YYYY-NNNNNNN-N, where 784 is the UAE's country code and the last digit is a check digit (django-localflavor). A Saudi national ID has 10 digits, and the first one says who holds it: 1 for Saudi citizens and 2 for foreign residents, whose number matches their Iqama (SAMA Rulebook). Read the groups as they appear on the card, so the caller can follow along with it in their hand.
Do this in code, not in the prompt. Nothing guarantees that an LLM asked to spell out a ten-digit number copies every digit, and a phone number with one wrong digit is worse than one read badly. A small function that strips formatting, converts Eastern Arabic digits and outputs words is easy to test, and it gives the same answer every time.
Eastern Arabic digits (٠١٢٣) and Western digits (0123) are both common in Gulf data, and neither tells the engine how to say the number. Convert them to one form in your own code first, as the function below does, then turn the number into words, whichever digits your database or the language model produced.
DIGIT_WORDS = {
"0": "صفر", "1": "واحد", "2": "اثنين", "3": "ثلاثة", "4": "أربعة",
"5": "خمسة", "6": "ستة", "7": "سبعة", "8": "ثمانية", "9": "تسعة",
}
# Eastern Arabic (٠-٩) and Persian-style (۰-۹) digits both turn up in Gulf data.
TO_WESTERN = str.maketrans("٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹", "01234567890123456789")
def speak_gulf_mobile(raw: str) -> str:
"""Read a UAE (+971) or Saudi (+966) mobile number as words, in 3-3-4 groups."""
digits = "".join(ch for ch in raw.translate(TO_WESTERN) if ch in DIGIT_WORDS)
if digits.startswith("00"):
digits = digits[2:]
for country_code in ("971", "966"):
if digits.startswith(country_code) and len(digits) == len(country_code) + 9:
digits = "0" + digits[len(country_code):]
if len(digits) != 10 or not digits.startswith("05"):
raise ValueError(f"not a UAE or Saudi mobile number: {raw!r}")
groups = [digits[:3], digits[3:6], digits[6:]]
return "، ".join(" ".join(DIGIT_WORDS[d] for d in group) for group in groups)
for number in ["+971 50 123 4567", "00966 55 123 4567", "٠٥٠١٢٣٤٥٦٧"]:
print(speak_gulf_mobile(number))
# صفر خمسة صفر، واحد اثنين ثلاثة، أربعة خمسة ستة سبعة
# صفر خمسة خمسة، واحد اثنين ثلاثة، أربعة خمسة ستة سبعة
# صفر خمسة صفر، واحد اثنين ثلاثة، أربعة خمسة ستة سبعةتقدر تتواصل معنا على الرقم 0501234567.
تقدر تتواصل معنا على الرقم: صفر خمسة صفر، واحد اثنين ثلاثة، أربعة خمسة ستة سبعة.
Where to turn numbers into words: code, prompt or engine
There are three places to turn numbers into words, and each suits a different kind of number. Phone numbers, IDs, booking references and card endings belong in code, because one wrong digit breaks them. Amounts, dates and times can go in the LLM prompt, with an instruction and one example per type, because the model already knows the grammar and the context of the call.
A TTS engine's own normaliser is the backstop for anything that slips through. It can help, but it has to guess the register and the grouping, which is exactly where Arabic calls go wrong, and ElevenLabs notes that its version adds latency. Send numbers already written the way you want them heard, and treat the engine's normaliser as a safety net rather than the plan.
The work starts with an inventory. Go through your prompts, tool results and templates, list every number type the agent says, and note whether each comes from the language model or from a tool. Then render your ten most common sentences with real numbers in them and have a native speaker from each market listen on a phone line. Where a number sounds wrong, fix the text, not the voice.
Writing numbers out costs a little more, because TTS is billed per character. "AED 1,250" is 9 characters and "ألف ومئتان وخمسون درهمًا" is 24, and the phone number above goes from 10 characters to 51, so the reminder grows by 56 characters. At Pāṇini's list price of $0.03125 per 1,000 characters, 10,000 reminders add 560,000 characters, or $17.50. That is usually a fair price for callers who hear the amount and the number correctly, and the guide to what an Arabic AI voice agent costs per minute puts it in context.
Sources
- ElevenLabs help centre: why numbers, dates, symbols and acronyms are not properly pronouncedOfficial
- Deepgram: using ElevenLabs for multilingual voice agents, limitations to know (February 2026)Secondary
- NAMAA-Egyptian-TTS model card, known limitations (Hugging Face)Official
- Wikipedia: Arabic grammar, cardinal numeralsSecondary
- Wikipedia: Saudi riyal sign (U+20C1, Unicode 17.0)Secondary
- Unicode blog: support for the new Saudi riyal currency sign (March 2025)Official
- Wikipedia: Emirati dirham sign (U+20C3, Unicode 18.0)Secondary
- Unicode 18.0.0 (release date 16 September 2026)Official
- Wikipedia: Arabic names of calendar monthsSecondary
- Wikipedia: Telephone numbers in the United Arab EmiratesSecondary
- Wikipedia: Telephone numbers in Saudi ArabiaSecondary
- django-localflavor: UAE Emirates ID format (784-YYYY-NNNNNNN-N)Official
- SAMA Rulebook: structure of the 10-digit Saudi ID numberOfficial
Change log: 24 Oct 2026, First published. Later the same day, rewritten as one continuous guide: the introduction now starts from the calls where numbers matter; fils and halalas, Eastern Arabic digits and the engine normaliser moved from the FAQs into the body; the steps and checklist folded into the final section; Unicode 18.0 release date (16 September 2026) confirmed from unicode.org. Code and audio unchanged




