indic-transliterator
v1.3.1
Published
Zero-dependency phonetic transliteration for 11 Indian scripts — pure functions + React hook
Downloads
385
Maintainers
Readme
indic-transliterator
A zero-dependency, fully offline phonetic transliteration library for 11 Indian languages. Type English (Roman) phonetically → get Indic script output instantly. Works as plain JavaScript functions or as a React hook.
Table of Contents
- How It Works
- Supported Languages
- Installation
- Quick Start
- API Reference
- Phonetic Rules
- Project Structure
- Running Tests
- Local Development (npm link)
- Limitations
How It Works
The engine uses a three-step pipeline:
English input ──► Devanagari (pivot) ──► Target script
"namaste" "नमस्ते" "নমস্তে" (Bengali)Step 1 — Roman → Devanagari
A greedy character-by-character parser matches phonetic patterns (digraphs like sh, bh, ksh, vowels, modifiers) against lookup tables and builds the Devanagari Unicode string.
Step 2 — Devanagari → Target script
- Brahmic scripts (Bengali, Gurmukhi, Gujarati, Odia, Telugu, Kannada, Malayalam): Unicode codepoint offset remapping. All Brahmic scripts share the same layout starting at different base codepoints, so each Devanagari character is simply shifted to the target block.
- Perso-Arabic scripts (Urdu, Kashmiri): A character-by-character map converts each Devanagari codepoint to the corresponding Arabic letter. Nukta'd consonants (ज़, क़, etc.) are handled with a lookahead.
- Tamil: Uses a Tamil-specific exception map because Tamil has fewer consonant distinctions than Devanagari.
Step 3 — Variant / suggestion generation
For IME-style suggestions, the engine generates phonetic alternatives (vowel elongation: a→aa, i→ee, o→au; double consonant collapsing) and deduplicates, returning up to 6 variants.
Reverse (romanize) The reverse pipeline maps each Indic codepoint back to its phonetic Roman equivalent using the same lookup tables in reverse, restoring inherent vowels and handling halant (virama) clusters.
Supported Languages
| Script key | Language | Script family |
| -------------- | ------------------------ | ----------------------- |
| devanagari | Hindi, Marathi, Sanskrit | Brahmic |
| bengali | Bengali / Bangla | Brahmic |
| gurmukhi | Punjabi | Brahmic |
| gujarati | Gujarati | Brahmic |
| odia | Odia (Oriya) | Brahmic |
| tamil | Tamil | Brahmic (reduced) |
| telugu | Telugu | Brahmic |
| kannada | Kannada | Brahmic |
| malayalam | Malayalam | Brahmic |
| urdu | Urdu | Perso-Arabic |
| kashmiri | Kashmiri | Perso-Arabic (Nastaliq) |
Installation
From npm (when published)
npm install indic-transliteratorLocal development (npm link)
# 1. Inside the library folder — register globally (run once)
cd path/to/indic-transliteration-library
npm link
# 2. Inside your React app
cd path/to/your-react-app
npm link indic-transliteratorAny change saved in the library is immediately available in your app — no reinstall needed.
Vite users: add
resolve: { preserveSymlinks: true }tovite.config.jsif you hit symlink issues.
Quick Start
Plain JavaScript (no React)
import { transliterate, getSuggestions, romanize } from 'indic-transliterator';
// English → Indic
transliterate('namaste', 'devanagari'); // → 'नमस्ते'
transliterate('vanakkam', 'tamil'); // → 'வணக்கம்'
transliterate('salam', 'urdu'); // → 'سلام'
// Get spelling suggestions for a word being typed
getSuggestions('rama', 'devanagari'); // → ['रामा', 'राम', 'रामाा', ...]
// Indic → English (reverse)
romanize('नमस्ते', 'devanagari'); // → 'namaste'
romanize('নমস্তে', 'bengali'); // → 'namaste'React Hook
import { useTransliterate } from 'indic-transliterator';
function TransliterateInput() {
const { value, setValue, output, suggestions, script, setScript } =
useTransliterate({ script: 'devanagari' });
return (
<div>
{/* Language selector */}
<select value={script} onChange={(e) => setScript(e.target.value)}>
<option value="devanagari">Hindi</option>
<option value="bengali">Bengali</option>
<option value="tamil">Tamil</option>
<option value="telugu">Telugu</option>
<option value="urdu">Urdu</option>
</select>
{/* Type English here */}
<input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Type in English..."
/>
{/* Live Indic output */}
<p>{output}</p>
{/* Suggestion chips */}
{suggestions.map((s) => (
<button key={s} onClick={() => setValue(s)}>{s}</button>
))}
</div>
);
}API Reference
transliterate(text, script?)
Converts an English phonetic string to the target Indic script. Multi-word input is supported; whitespace is preserved.
| Parameter | Type | Default | Description |
| ---------- | ---------- | ---------------- | --------------------- |
| text | string | — | English (Roman) input |
| script | string | 'devanagari' | Target script key |
Returns: string
transliterate('bharat mata ki jai', 'devanagari')
// → 'भरत मता की जई'
transliterate('namaste', 'bengali') // → 'নমস্তে'
transliterate('namaste', 'telugu') // → 'నమస్తే'
transliterate('namaste', 'urdu') // → 'نمستے'getSuggestions(word, script?)
Returns up to 6 phonetic variants for a single word. Use this to build an IME-style suggestion dropdown.
| Parameter | Type | Default | Description |
| ---------- | ---------- | ---------------- | ------------------- |
| word | string | — | Single English word |
| script | string | 'devanagari' | Target script key |
Returns: string[] (1–6 items)
getSuggestions('rama', 'devanagari')
// → ['रामा', 'राम', 'रम', 'रमाा', ...]
getSuggestions('hello', 'bengali')
// → ['হেলো', 'হেল্লো', 'হৈলো', ...]Variants are generated by:
- Collapsing double consonants (
ll→l) - Vowel substitutions:
e→ai,e→a,i→ee,o→au,a→aa,u→oo
romanize(text, script?)
Reverse-transliterates Indic script text back to phonetic English. Full support for all 9 Brahmic scripts. Urdu/Kashmiri output is approximate.
| Parameter | Type | Default | Description |
| ---------- | ---------- | ---------------- | ------------------------------ |
| text | string | — | Text in the given Indic script |
| script | string | 'devanagari' | Source script key |
Returns: string
romanize('नमस्ते', 'devanagari') // → 'namaste'
romanize('শান্তি', 'bengali') // → 'shanti'
romanize('నమస్తే', 'telugu') // → 'namaste'
romanize('வணக்கம்', 'tamil') // → approximateNote: Tamil has phoneme merging (multiple Devanagari consonants map to one Tamil character), so its reverse output is approximate rather than an exact round-trip.
toDevanagari(text)
Converts English phonetic text to Devanagari only (no further script conversion). Useful when you want the Devanagari intermediate form.
toDevanagari('shanti') // → 'शान्ति'
toDevanagari('bharat') // → 'भरत'convertScript(devanagariText, script)
Converts already-transliterated Devanagari text to another script. Useful when you have Devanagari and want to cross-convert.
convertScript('नमस्ते', 'bengali') // → 'নমস্তে'
convertScript('नमस्ते', 'telugu') // → 'నమస్తే'
convertScript('शान्ति', 'gurmukhi') // → 'ਸ਼ਾਨ੍ਤਿ'SCRIPTS
An array of all supported script key strings.
import { SCRIPTS } from 'indic-transliterator';
console.log(SCRIPTS);
// → ['devanagari', 'bengali', 'gurmukhi', 'gujarati', 'odia',
// 'tamil', 'telugu', 'kannada', 'malayalam', 'urdu', 'kashmiri']useTransliterate — React Hook
A stateful React hook (requires React ≥ 16.8) that manages input value, live output, and suggestions.
const { value, setValue, output, suggestions, script, setScript } =
useTransliterate(options?)Options
| Option | Type | Default | Description |
| ------------------ | ---------- | ---------------- | ---------------------------------- |
| script | string | 'devanagari' | Initial target script |
| maxSuggestions | number | 6 | Max items in suggestions array |
| initialValue | string | '' | Pre-fill the input |
Return values
| Field | Type | Description |
| --------------- | ------------ | ---------------------------------------------------- |
| value | string | Current English input (what the user types) |
| setValue | Function | Setter — update the English input |
| output | string | Full transliterated text, updates on every keystroke |
| suggestions | string[] | Phonetic variants for the last word being typed |
| script | string | Currently active script key |
| setScript | Function | Switch the target script at runtime |
Suggestion behaviour
- Populated only when the last word in the input has ≥ 2 characters
- Cleared immediately when the input ends with whitespace (word committed)
- Respects
maxSuggestionscap
Phonetic Rules
| You type | Devanagari | Notes |
| ---------------- | ----------- | ---------------------------------------------------- |
| a | अ | short a |
| aa / A | आ | long ā |
| i | इ | short i |
| ee / I | ई | long ī |
| u | उ | short u |
| oo / U | ऊ | long ū |
| e | ए | |
| ai | ऐ | |
| o | ओ | |
| au | औ | |
| k | क | |
| kh | ख | |
| g | ग | |
| gh | घ | |
| ch | च | |
| chh | छ | |
| j | ज | |
| jh | झ | |
| t | त | dental |
| T | ट | retroflex |
| th | थ | aspirated dental |
| Th | ठ | aspirated retroflex |
| d | द | dental |
| D | ड | retroflex |
| dh | ध | aspirated dental |
| Dh | ढ | aspirated retroflex |
| n | न | |
| N | ण | retroflex nasal |
| p | प | |
| ph | फ | |
| b | ब | |
| bh | भ | |
| m | म | |
| y | य | |
| r | र | |
| l | ल | |
| v / w | व | |
| s | स | |
| sh | श | |
| Sh / shh | ष | retroflex sibilant |
| h | ह | |
| ksh / x | क्ष | conjunct |
| gny | ज्ञ | conjunct |
| shr | श्र | conjunct |
| f | फ़ | nukta |
| z | ज़ | nukta |
| q | क़ | nukta |
| M | ं | anusvara |
| ~ | ँ | chandrabindu |
| : | ः | visarga |
| \| | । | danda |
| \|\| | ॥ | double danda |
| \x | x (literal) | escape: backslash passes next char through unchanged |
Project Structure
indic-transliteration-library/
├── src/
│ ├── engine.js ← Core phonetic engine (pure ES module, no dependencies)
│ └── index.js ← Public API exports + useTransliterate React hook
├── lib/ ← Original browser/UMD versions (legacy, for reference)
│ ├── indic-transliterate.js
│ ├── indic-transliterate-widget.js
│ └── indic-transliterate.css
├── tests/
│ ├── engine.test.js ← Pure function tests (Jest)
│ └── hook.test.jsx ← React hook tests (@testing-library/react)
├── index.html ← Interactive demo page
├── package.json
├── jest.config.js
├── babel.config.js
└── .gitignoreRunning Tests
npm test # run all tests once
npm run test:watch # watch mode (re-runs on file change)
npm run test:coverage # with coverage reportThe test suite covers:
- All 11 scripts for
transliterate() - Round-trip accuracy for
romanize()across all Brahmic scripts - Suggestion count, uniqueness, and vowel/consonant variants
- React hook state management, reactive output, and
setScriptbehaviour
Local Development (npm link)
# Step 1 — inside this library folder (run once)
npm link
# Step 2 — inside your React app
npm link indic-transliterator
# To unlink
npm unlink indic-transliterator # in the app
npm unlink # in the libraryLimitations
| Limitation | Detail |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Tamil round-trip | Tamil merges multiple Devanagari consonants into one character, so romanize() output for Tamil is approximate |
| Urdu / Kashmiri reverse | Perso-Arabic → Roman is approximate due to many-to-one mappings |
| No NLP / dictionary | This is arule-based phonetic engine, not a spell-checker or translator |
| No English → English | Only Roman phonetic → Indic script (and back); no ITRANS or ISO-15919 standard support yet |
