@demystify/indic-numerals
v0.1.0
Published
Spoken Indian number words to integer minor units. "sadhe teen lakh" -> 35000000 paise. Handles sava/sadhe/paune/dedh/dhai fractional forms, lakh/crore scales, Devanagari and Latin transliteration. Zero dependencies, pure, offline. Leaf package.
Maintainers
Readme
@demystify/indic-numerals
Spoken Indian number words → integer minor units.
import { parseIndicAmount } from "@demystify/indic-numerals";
parseIndicAmount("sadhe teen lakh");
// { ok: true, amountMinor: 35_000_000, currency: "INR", major: 350_000,
// matched: "sadhe teen lakh" }Zero dependencies. Pure, offline, no clock.
Why this exists
Indic speech models transcribe "sadhe teen lakh" correctly — Sarvam's Saaras v3 gives you those three words. None of them turn the words into money. That gap is this package.
What it handles
| Form | Example | Value |
|---|---|---|
| Units and scales | teen lakh | 3,00,000 |
| sava — a quarter more | sava do lakh | 2,25,000 |
| sadhe — a half more | sadhe teen lakh | 3,50,000 |
| paune — a quarter LESS | paune teen lakh | 2,75,000 |
| dedh (1.5), dhai (2.5), adha (0.5) | dhai lakh | 2,50,000 |
| Devanagari | साढ़े तीन लाख | 3,50,000 |
| Mixed digits | 3.5 lakh, 1,23,456 | 3,50,000 · 1,23,456 |
paune is the one that catches people. It counts down from the next number:
paune teen is 2.75, not 3.25. Reading it as an increment overstates what someone
said by ₹50,000 on a lakh-scale amount.
dedh and dhai matter because Hindi does not say "sadhe ek" or "sadhe do". A
parser that only understands modifier+unit silently fails on the two most common
fractional amounts in everyday speech.
Cr is Credit, never crore — the same rule @demystify/grounding enforces.
panch hazaar cr is ₹5,000, not ₹50bn.
It refuses rather than guessing
This runs on money. A confident wrong answer is far worse than an honest refusal — a caller can ask the user to repeat, but cannot un-post a journal entry.
parseIndicAmount("sadhe paune teen lakh");
// { ok: false, reason: "ambiguous_modifier", detail: "two fractional modifiers …" }Failure reasons: no_number_found · ambiguous_modifier · modifier_without_number
· unsupported_fraction · not_an_integer_minor_amount. Every one carries a
renderable detail, and matched on success shows which words were consumed — so a
UI can echo "I understood: sadhe teen lakh" before anything is posted.
Testing
pnpm test # 33 tests98% statements. Two bugs were found by these tests rather than by reading: stripping
punctuation turned 3.5 into 3 5 (= 8, so 3.5 lakh parsed as ₹8,00,000), and
1,23,456 tokenized as 1 + 23 + 456. Both are pinned.
MIT.
