lipimala · v1.2.0

Technical API Reference

Exact round-trip Indic transliteration across Dart, JavaScript, Python, and PHP. Same conversion tables, profiles, Vedic handling, metadata trailer format, and result envelopes on every runtime.

  • lipimala
  • lipimala
  • lipimala
  • jayeshmepani/lipimala
  • PHP ns Lipimala
  • Default profile extendedIndic
toDevanagariFromIast() live
Devanagari कृष्ण आत्मन्
Gujarati કૃષ્ણ આત્મન્
  • profile: extendedIndic
  • in: nfd → out: nfc
  • renderingIsInjective: false

1. What lipimala does

Converts between scholarly Latin (IAST / extended Indic / ISO-style tables), Devanagari, Gujarati, and plain-English / Hunterian views. Visible Brahmic rendering is many-to-one—case, aliases, and normalization collapse—so exact recovery uses an envelope or an invisible metadata trailer.

Supported directions

  • Latin/IAST → Devanagari
  • Latin/IAST → Gujarati
  • Latin/IAST → plain English / Hunterian
  • Devanagari / Gujarati → readable Plain English / Hunterian
  • Devanagari → IAST (canonical / smart / exact)
  • Gujarati → IAST (canonical / smart / exact)
  • Devanagari ↔ Gujarati (canonical / smart / exact)

Two recovery strategies

  1. TransliterationResult — keep the object / JSON and call restoreOriginal().
  2. Exact-source trailer — set embedExactSourceMetadata: true so the string carries a checksummed Unicode-Tag payload (LIT1:).

2. Installation & imports

Install commands and primary import paths
Language Install Import / use
Python (opens in new tab) pip install lipimala from lipimala import to_devanagari, to_devanagari_from_gujarati, ...
JavaScript (opens in new tab) npm install lipimala import { toDevanagari, toDevanagariFromGujarati } from 'lipimala'
Dart (opens in new tab) dart pub add lipimala import 'package:lipimala/lipimala.dart';
Extensions on String
PHP (opens in new tab) composer require jayeshmepani/lipimala use function Lipimala\toDevanagari;
use Lipimala\IastToDevanagariOptions;

3. Core concepts

3.1 Two API layers

String converters versus envelope converters
Layer Returns When to use
String converters
toDevanagariFromIast
string Rendered text only; optional invisible trailer for later exact reverse.
Envelope converters
toDevanagari
TransliterationResult Structured output, issues, profile metadata, JSON, restoreOriginal().

3.2 Smart vs exact vs canonical reverse

Reverse recovery modes (Devanagari → IAST example)
Variant Behavior Fails when
toIastFromDevanagari Exact trailer if present, else canonical reverse Never throws for missing trailer
toExactIastFromDevanagari Requires valid embedded metadata Throws if trailer missing/corrupt (empty → empty)
toCanonicalIastFromDevanagari Always visible-script reverse Does not throw for missing trailer

Same pattern for Gujarati→IAST and Deva↔Gujr with typed markers ISC:D: / ISC:G:.

3.3 Unicode normalization

Enum UnicodeNormalizationForm: preserve nfc nfd

Envelope defaults: input nfd, output nfc. Reverse APIs use ScriptToIastOptions.

4. Cross-language naming map

The table below maps all primary public functions, envelope APIs, reverse converters, script-to-script transformers, and metadata helpers across Dart, JavaScript, Python, and PHP environments.

Comprehensive API names across runtimes
Concept / Functionality Dart (package:lipimala/lipimala.dart) JavaScript (lipimala) Python (lipimala) PHP (Lipimala\*)
Devanagari Envelope toDevanagari()
text.toDevanagari()
toDevanagari()
to_devanagari()
to_devanagari()
toDevanagari()
toDevanagari()
to_devanagari()
Gujarati Envelope toGujarati()
text.toGujarati()
toGujarati()
to_gujarati()
to_gujarati()
toGujarati()
toGujarati()
to_gujarati()
Plain English Envelope toPlainEnglish()
text.toPlainEnglish()
toPlainEnglish()
to_plain_english()
to_plain_english()
toPlainEnglish()
toPlainEnglish()
to_plain_english()
IAST → Devanagari String toDevanagariFromIast()
text.toDevanagariFromIast()
toDevanagariFromIast()
to_devanagari_from_iast()
to_devanagari_from_iast()
toDevanagariFromIast()
toDevanagariFromIast()
to_devanagari_from_iast()
IAST → Gujarati String toGujaratiFromIast()
text.toGujaratiFromIast()
toGujaratiFromIast()
to_gujarati_from_iast()
to_gujarati_from_iast()
toGujaratiFromIast()
toGujaratiFromIast()
to_gujarati_from_iast()
IAST → Plain English String toPlainEnglishFromIast()
text.toPlainEnglishFromIast()
toPlainEnglishFromIast()
to_plain_english_from_iast()
to_plain_english_from_iast()
toPlainEnglishFromIast()
toPlainEnglishFromIast()
to_plain_english_from_iast()
Devanagari → Plain / Hunterian text.toPlainEnglishFromDevanagari()
text.toHunterianFromDevanagari()
toPlainEnglishFromDevanagari()
toHunterianFromDevanagari()
to_plain_english_from_devanagari()
to_hunterian_from_devanagari()
toPlainEnglishFromDevanagari()
toHunterianFromDevanagari()
Gujarati → Plain / Hunterian text.toPlainEnglishFromGujarati()
text.toHunterianFromGujarati()
toPlainEnglishFromGujarati()
toHunterianFromGujarati()
to_plain_english_from_gujarati()
to_hunterian_from_gujarati()
toPlainEnglishFromGujarati()
toHunterianFromGujarati()
Bulk Array / List Transliteration items.toDevanagariFromIast()
toDevanagariFromIastList()
toDevanagariFromIastList() to_devanagari_from_iast_list() toDevanagariFromIastList()
Devanagari → Smart IAST toIastFromDevanagari() toIastFromDevanagari()
to_iast_from_devanagari()
to_iast_from_devanagari()
toIastFromDevanagari()
toIastFromDevanagari()
to_iast_from_devanagari()
Devanagari → Canonical IAST toCanonicalIastFromDevanagari() toCanonicalIastFromDevanagari()
to_canonical_iast_from_devanagari()
to_canonical_iast_from_devanagari()
toCanonicalIastFromDevanagari()
toCanonicalIastFromDevanagari()
to_canonical_iast_from_devanagari()
Devanagari → Exact IAST toExactIastFromDevanagari() toExactIastFromDevanagari()
to_exact_iast_from_devanagari()
to_exact_iast_from_devanagari()
toExactIastFromDevanagari()
toExactIastFromDevanagari()
to_exact_iast_from_devanagari()
Gujarati → Smart IAST toIastFromGujarati() toIastFromGujarati()
to_iast_from_gujarati()
to_iast_from_gujarati()
toIastFromGujarati()
toIastFromGujarati()
to_iast_from_gujarati()
Gujarati → Canonical IAST toCanonicalIastFromGujarati() toCanonicalIastFromGujarati()
to_canonical_iast_from_gujarati()
to_canonical_iast_from_gujarati()
toCanonicalIastFromGujarati()
toCanonicalIastFromGujarati()
to_canonical_iast_from_gujarati()
Gujarati → Exact IAST toExactIastFromGujarati() toExactIastFromGujarati()
to_exact_iast_from_gujarati()
to_exact_iast_from_gujarati()
toExactIastFromGujarati()
toExactIastFromGujarati()
to_exact_iast_from_gujarati()
Devanagari → Smart Gujarati toGujaratiFromDevanagari() toGujaratiFromDevanagari()
to_gujarati_from_devanagari()
to_gujarati_from_devanagari()
toGujaratiFromDevanagari()
toGujaratiFromDevanagari()
to_gujarati_from_devanagari()
Devanagari → Canonical Gujarati toCanonicalGujaratiFromDevanagari() toCanonicalGujaratiFromDevanagari()
to_canonical_gujarati_from_devanagari()
to_canonical_gujarati_from_devanagari()
toCanonicalGujaratiFromDevanagari()
toCanonicalGujaratiFromDevanagari()
to_canonical_gujarati_from_devanagari()
Devanagari → Exact Gujarati toExactGujaratiFromDevanagari() toExactGujaratiFromDevanagari()
to_exact_gujarati_from_devanagari()
to_exact_gujarati_from_devanagari()
toExactGujaratiFromDevanagari()
toExactGujaratiFromDevanagari()
to_exact_gujarati_from_devanagari()
Gujarati → Smart Devanagari toDevanagariFromGujarati() toDevanagariFromGujarati()
to_devanagari_from_gujarati()
to_devanagari_from_gujarati()
toDevanagariFromGujarati()
toDevanagariFromGujarati()
to_devanagari_from_gujarati()
Gujarati → Canonical Devanagari toCanonicalDevanagariFromGujarati() toCanonicalDevanagariFromGujarati()
to_canonical_devanagari_from_gujarati()
to_canonical_devanagari_from_gujarati()
toCanonicalDevanagariFromGujarati()
toCanonicalDevanagariFromGujarati()
to_canonical_devanagari_from_gujarati()
Gujarati → Exact Devanagari toExactDevanagariFromGujarati() toExactDevanagariFromGujarati()
to_exact_devanagari_from_gujarati()
to_exact_devanagari_from_gujarati()
toExactDevanagariFromGujarati()
toExactDevanagariFromGujarati()
to_exact_devanagari_from_gujarati()
Check IAST Source Metadata hasExactGujaratiIastSourceMetadata
hasExactDevanagariIastSourceMetadata
hasExactGujaratiIastSourceMetadata
hasExactDevanagariIastSourceMetadata
has_exact_gujarati_iast_source_metadata
has_exact_devanagari_iast_source_metadata
hasExactGujaratiIastSourceMetadata()
hasExactDevanagariIastSourceMetadata()
Check Direct Metadata hasExactGujaratiSourceMetadata()
hasExactDevanagariSourceMetadata()
hasExactGujaratiSourceMetadata()
hasExactDevanagariSourceMetadata()
has_exact_gujarati_source_metadata()
has_exact_devanagari_source_metadata()
hasExactGujaratiSourceMetadata()
hasExactDevanagariSourceMetadata()
Strip Direct Metadata visibleWithoutExactSourceMetadata() visibleWithoutExactSourceMetadata() visible_without_exact_source_metadata() visibleWithoutExactSourceMetadata()
Embed Source Metadata embedExactSourceMetadata() embedExactSourceMetadata()
embed_exact_source_metadata()
embed_exact_source_metadata()
embedExactSourceMetadata()
embedExactSourceMetadata()
embed_exact_source_metadata()
Decode Metadata tryDecodeExactSourceMetadata() tryDecodeExactSourceMetadata()
try_decode_exact_source_metadata()
try_decode_exact_source_metadata()
tryDecodeExactSourceMetadata()
tryDecodeExactSourceMetadata()
try_decode_exact_source_metadata()
Strip Tag Metadata stripExactSourceMetadata() stripExactSourceMetadata()
strip_exact_source_metadata()
strip_exact_source_metadata()
stripExactSourceMetadata()
stripExactSourceMetadata()
strip_exact_source_metadata()
Recover Original Source recoverEmbeddedExactSource() recoverEmbeddedExactSource()
recover_embedded_exact_source()
recover_embedded_exact_source()
recoverEmbeddedExactSource()
recoverEmbeddedExactSource()
recover_embedded_exact_source()
Check Tag Metadata hasEmbeddedExactSource() hasEmbeddedExactSource()
has_embedded_exact_source()
has_embedded_exact_source()
hasEmbeddedExactSource()
hasEmbeddedExactSource()
has_embedded_exact_source()
Unicode Normalization normalizeUnicode() normalizeUnicode()
normalize_unicode()
normalize_unicode()
normalizeUnicode()
Unicode::normalize()

5. Envelope APIs

Return TransliterationResult. Always set renderingIsInjective = false for script/plain views.

toDevanagari / to_devanagari

  • IAST → Devanagari
  • TransliterationResult
Parameters
Parameter Type Default Description
text string required Latin/IAST (or extended) source
options IastToDevanagariOptions defaults Profile + policies — see §13
inputNormalization UnicodeNormalizationForm nfd Applied before conversion
outputNormalization UnicodeNormalizationForm nfc Applied to visible rendered text

Issue attached: SOURCE_METADATA_REQUIRED_FOR_EXACT_REVERSE (info).

Dart: method on String. JS: second arg is { options, inputNormalization, outputNormalization }.

toGujarati / to_gujarati

  • IAST → Gujarati
  • TransliterationResult

Same shape as toDevanagari with IastToGujaratiOptions.

toPlainEnglish / to_plain_english

  • IAST → plain English
  • TransliterationResult

Uses IastPlainEnglishOptions. Result profile is hunterian or plainEnglish.

Issue: HUNTERIAN_VIEW_IS_INTRINSICALLY_LOSSY or PLAIN_ENGLISH_VIEW_IS_INTRINSICALLY_LOSSY (info).

Envelope examples

Pass IastToDevanagariOptions for script output and IastPlainEnglishOptions for plain English. inputNormalization defaults to nfd and outputNormalization defaults to nfc. In JavaScript those fields sit beside options on the second argument. Dart, Python, and PHP pass the options object itself. toGujarati('Kṛṣṇa') returns કૃષ્ણ and takes IastToGujaratiOptions with the same fields.

import 'package:lipimala/lipimala.dart';

void main() {
  final script = 'Kṛṣṇa'.toDevanagari();
  print(script.rendered); // कृष्ण
  print(script.restoreOriginal()); // Kṛṣṇa

  print('Rāma 2.'.toDevanagari(
    options: const IastToDevanagariOptions(
      digitPolicy: IastToDevanagariDigitPolicy.convertToScript,
      punctuationPolicy: IastToDevanagariPunctuationPolicy.indicDanda,
    ),
  ).rendered); // राम २।

  final english = 'Rāma'.toPlainEnglish();
  print(english.rendered); // Ram
  print(english.restoreOriginal()); // Rāma
}

6. IAST → Devanagari (string API)

toDevanagariFromIast / to_devanagari_from_iast

  • string
  • optional metadata trailer
Parameters
Parameter Type Default
text string required
options IastToDevanagariOptions all defaults (§13)

When: you only need the rendered script string, or you will reverse later via metadata.

How exact reverse works: pass embedExactSourceMetadata: true, then call toExactIastFromDevanagari(tagged). The three reverse modes are in section 9.

Option examples

toGujaratiFromIast('Kṛṣṇa') returns કૃષ્ણ. It takes IastToGujaratiOptions; the fields match the calls below, with the Gujarati enum names. iso15919Core is the third profile. throwError raises on an unknown Latin letter. For kḷ, context and preferVocalic both yield कॢ.

import 'package:lipimala/lipimala.dart';

void main() {
  print('shiva'.toDevanagariFromIast()); // शिव
  print('shiva'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(
      profile: DevanagariRomanizationProfile.strictIast,
    ),
  )); // sहिव

  print('Raama'.toDevanagariFromIast()); // रअम
  print('Raama'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(acceptAsciiLongVowels: true),
  )); // राम

  print('oṃ'.toDevanagariFromIast()); // ओं
  print('oṃ'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(
      omPolicy: IastToDevanagariOmPolicy.useOmSign,
    ),
  )); // ॐ

  print('ə'.toDevanagariFromIast()); // ə
  print('ə'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(
      unknownLatinPolicy: IastToDevanagariUnknownLatinPolicy.bracket,
    ),
  )); // [ə]

  print('kḷ'.toDevanagariFromIast()); // कॢ
  print('kḷ'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(
      ambiguousLPolicy: IastToDevanagariAmbiguousLPolicy.preferConsonant,
    ),
  )); // क्ळ्

  print('sha'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(acceptPlainSh: false),
  )); // sह  (default श)
  print('xa'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(acceptPlainXAsKha: false),
  )); // xअ  (default ख़)
  print('swa'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(acceptWAsVa: false),
  )); // स्wअ  (default स्व)
  print('ā́'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(preserveVedicAccentMarks: false),
  )); // आ  (default आ॑)
  print('a  b'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(collapseWhitespace: true),
  )); // अ ब्

  final tagged = 'Kṛṣṇa'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(embedExactSourceMetadata: true),
  );
  print(stripExactSourceMetadata(tagged)); // कृष्ण
  print(hasEmbeddedExactSource(tagged)); // true
}

7. IAST → Gujarati (string API)

toGujaratiFromIast / to_gujarati_from_iast

Same fields as the Devanagari string example, using IastToGujaratiOptions and the Gujarati profile and policy enums. toGujaratiFromIast('Kṛṣṇa') returns કૃષ્ણ. Exact reverse: toExactIastFromGujarati.

8. IAST / Brahmic → plain English / Hunterian

toPlainEnglishFromIast / to_plain_english_from_iast

  • string
  • intrinsically lossy

ASCII-friendly transcription. Keep the envelope for exact source recovery. IAST input uses the legacy Plain-English/Hunterian policies; direct Devanagari/Gujarati input additionally tracks inherent schwas before applying language-aware Gujarati/Hindi deletion rules, with a Sanskrit no-deletion mode.

Direct APIs: toPlainEnglishFromDevanagari, toHunterianFromDevanagari, toPlainEnglishFromGujarati, and toHunterianFromGujarati, with matching list APIs and loss-aware result-envelope APIs such as toPlainEnglishFromGujaratiResult.

BrahmicPlainEnglishOptions controls language, schwa deletion, vowel length, terminal anusvara, Gujarati ʿayn rendering, jñ/ñ/glottal handling, Vedic-mark preservation, whitespace, and contextual v/w behavior. Since 1.2.0 it also accepts readableStyle (legacy or natural), vowelLength: smart, sentence-start capitalization, and exact readable-word overrides. Historic prishthamatra and short-AI forms, Vedic nasal/visarga signs, OM, Sindhi implosives, Konkani च़, Gujarati Sukūn/Shadda/Maddah and special nuktas are interpreted semantically instead of leaking raw source-script marks into ordinary readable output.

SMART runs only with natural. Closed monosyllables keep length (chaar, hoon, swaroop). Open particles and heavy clusters shorten (dharan, karine). An open ending keeps stem length (swaroopama, paasethi). A nasal coda keeps a peripheral vowel (hoonga). Sanskrit SMART still doubles every long vowel (shvetadveepa). With natural + smart set on both calls, Gujarati Plain and Hunterian return the same string.

Natural schwa keeps a vowel between p and an unaspirated t (राष्ट्रपति → rashtrapati). An aspirated થ / थ still contracts (શાપથી → shaapthi). Legacy गांधीनगर stays gaandheengar; natural Hindi is gandhinagar.

IAST plain-English examples

One call for each IastPlainEnglishOptions field that changes the string. This is the Latin-input API. Brahmic natural and smart are below and do not apply here. keepFinalAForWords is consulted by smart, and the set stores the folded spelling rama.

import 'package:lipimala/lipimala.dart';

void main() {
  print('vrata'.toPlainEnglishFromIast()); // vrat
  print('vrata'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(finalA: FinalAPolicy.keep),
  )); // vrata
  print('Kṛṣṇa'.toPlainEnglishFromIast()); // Krishna
  print('Kṛṣṇa'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(finalA: FinalAPolicy.drop),
  )); // Krishn
  print('Rāma'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(keepFinalAForWords: {'rama'}),
  )); // Rama

  print('jñāna'.toPlainEnglishFromIast()); // gyan
  print('jñāna'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(jna: JnaPolicy.jnya),
  )); // jnyan
  print('jñāna'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(jna: JnaPolicy.jna),
  )); // jnan

  print('pañca'.toPlainEnglishFromIast()); // panch
  print('pañca'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(nya: NyaPolicy.nya),
  )); // panycha
  print('pañca'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(nya: NyaPolicy.gna),
  )); // pagncha

  print('svarga'.toPlainEnglishFromIast()); // svarg
  print('svarga'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(
      profile: PlainEnglishRomanizationProfile.hunterian,
    ),
  )); // swarg

  print('candra'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(convertCToCh: false),
  )); // candra  (default chandra)
  print('aʔa'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(glottalStop: GlottalStopPolicy.apostrophe),
  )); // a'  (default aa)
  print('saṃskāra'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(assimilateAnusvara: false),
  )); // samskar  (default sanskar)
  print("so'ham".toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(removeAvagraha: false),
  )); // so'ham  (default soham)
  print('a  b'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(collapseWhitespace: true),
  )); // a b
  print('rāmagupta'.toPlainEnglishFromIast(
    options: const IastPlainEnglishOptions(enableInternalSchwaSyncope: true),
  )); // ramgupt  (default ramagupt)
}

Readable Latin examples

One call for each Brahmic option mode. Plain English doubles long vowels. Hunterian collapses them when vowel length is omitted, and it absorbs visarga before a consonant. Gujarati Hunterian keeps v (સર્વે stays sarve). With natural and smart set on both calls, Gujarati Plain and Hunterian return the same string. toPlainEnglishFromDevanagari takes the same options. Word overrides match the rendered spelling.

import 'package:lipimala/lipimala.dart';

void main() {
  const phrase = 'શ્વેતદ્વીપ સ્વરૂપ ધારણ કરીને ચાર માસ';
  const natural = BrahmicPlainEnglishOptions(
    readableStyle: BrahmicReadableStyle.natural,
    vowelLength: BrahmicVowelLengthPolicy.smart,
  );

  print(toPlainEnglishFromGujarati(phrase));
  // shvetadveep svaroop dhaaran kareene chaar maas
  print(toHunterianFromGujarati(phrase));
  // shvetadvip svarup dharan karine char mas
  print(toPlainEnglishFromGujarati(phrase, options: natural));
  print(toHunterianFromGujarati(phrase, options: natural));
  // shwetdweep swaroop dharan karine chaar maas

  print(toPlainEnglishFromGujarati('દુઃખ')); // duhkh
  print(toHunterianFromGujarati('દુઃખ')); // dukh

  print(toPlainEnglishFromDevanagari('ऋतु', options: natural)); // ritu
  print(toPlainEnglishFromDevanagari(
    'ऋतु',
    options: const BrahmicPlainEnglishOptions(
      language: BrahmicLanguage.gujarati,
      readableStyle: BrahmicReadableStyle.natural,
      vowelLength: BrahmicVowelLengthPolicy.smart,
    ),
  )); // rutu
  print(toPlainEnglishFromDevanagari(
    'धर्म',
    options: const BrahmicPlainEnglishOptions(
      language: BrahmicLanguage.sanskrit,
      readableStyle: BrahmicReadableStyle.natural,
      vowelLength: BrahmicVowelLengthPolicy.smart,
    ),
  )); // dharma

  print(toPlainEnglishFromGujarati(
    'આજ મારે. શ્વેતદ્વીપ ધર્મ છે.',
    options: const BrahmicPlainEnglishOptions(
      readableStyle: BrahmicReadableStyle.natural,
      vowelLength: BrahmicVowelLengthPolicy.smart,
      capitalizeSentenceStarts: true,
      readableWordOverrides: {'shwetdweep': 'Shwetdweep', 'dharm': 'Dharm'},
    ),
  )); // Aaj maare. Shwetdweep Dharm chhe.
}

8b. Bulk Array / List Transliteration API

Bulk Array / List Conversion Functions Across All 4 Ecosystems

Bulk convert an array, list, or sequence of text values (["Kṛṣṇa", "Rāma", "jñāna"]) in a single operation without manual iteration loops across all conversion directions:

  • Latin (IAST) → Devanagari / Gujarati / Plain English: toDevanagariFromIastList(), toGujaratiFromIastList(), toPlainEnglishFromIastList()
  • Brahmic (Devanagari / Gujarati) → Latin IAST: toCanonicalIastFromDevanagariList(), toCanonicalIastFromGujaratiList(), toIastFromDevanagariList(), toIastFromGujaratiList()
  • Brahmic → readable Plain English / Hunterian: toPlainEnglishFromDevanagariList(), toHunterianFromDevanagariList(), toPlainEnglishFromGujaratiList(), toHunterianFromGujaratiList()
  • Direct Devanagari ↔ Gujarati: toCanonicalGujaratiFromDevanagariList(), toCanonicalDevanagariFromGujaratiList(), toGujaratiFromDevanagariList(), toDevanagariFromGujaratiList()
  • Result Envelopes: toDevanagariList(), toGujaratiList(), toPlainEnglishList()

List example

Every list function takes the options object of its string twin and applies it to each item. The other names in the list above are that same call for a different direction.

import 'package:lipimala/lipimala.dart';

void main() {
  print(toDevanagariFromIastList(
    ['Rāma 2', 'Kṛṣṇa'],
    options: const IastToDevanagariOptions(
      digitPolicy: IastToDevanagariDigitPolicy.convertToScript,
    ),
  ).join(', ')); // राम २, कृष्ण
}

9. Brahmic → IAST reverse

Lipimala provides three distinct reverse conversion strategies for translating Devanagari or Gujarati text back into Latin IAST. Choose between smart metadata-aware recovery, pure canonical visible reverse, or strict metadata verification.

Reverse IAST conversion functions
Function Signature Expected Parameters Output Type Behavior & Strategy
toIastFromDevanagari(text, options?)
to_iast_from_devanagari(text, options?)
text: string
options: ScriptToIastOptions?
string Smart Reverse: If an embedded exact-source metadata trailer is present and valid, recovers exact original Latin. Otherwise, performs canonical visible reverse transliteration.
toCanonicalIastFromDevanagari(text, options?)
to_canonical_iast_from_devanagari(text, options?)
text: string
options: ScriptToIastOptions?
string Canonical Reverse: Always performs deterministic visible reverse conversion from Devanagari to lower-case IAST, completely ignoring any embedded metadata trailer.
toExactIastFromDevanagari(text)
to_exact_iast_from_devanagari(text)
text: string string Strict Exact Recovery: Decodes and verifies the embedded metadata trailer. Returns exact original Latin input (with original casing/aliases). Throws/raises an exception if metadata is missing or checksum validation fails.
toIastFromGujarati(text, options?)
to_iast_from_gujarati(text, options?)
text: string
options: ScriptToIastOptions?
string Smart Reverse: Recovers exact original Latin if embedded metadata trailer is valid; falls back to canonical Gujarati → IAST visible reverse.
toCanonicalIastFromGujarati(text, options?)
to_canonical_iast_from_gujarati(text, options?)
text: string
options: ScriptToIastOptions?
string Canonical Reverse: Always performs visible reverse conversion from Gujarati to lower-case IAST, ignoring metadata trailers.
toExactIastFromGujarati(text)
to_exact_iast_from_gujarati(text)
text: string string Strict Exact Recovery: Decodes and verifies the Gujarati metadata trailer. Returns exact original Latin input. Throws/raises an error if trailer is missing or corrupted.

Reverse examples

Smart reverse returns the embedded source when the trailer is present, and canonical IAST otherwise. Canonical reverse always reads the visible script. Exact reverse requires the trailer. The Gujarati twins are toIastFromGujarati, toCanonicalIastFromGujarati, and toExactIastFromGujarati. ScriptToIastOptions also accepts input and output normalization and preserveEncodedVedicMarks.

import 'package:lipimala/lipimala.dart';

void main() {
  final tagged = 'Kṛṣṇa'.toDevanagariFromIast(
    options: const IastToDevanagariOptions(embedExactSourceMetadata: true),
  );
  print(tagged.toIastFromDevanagari()); // Kṛṣṇa
  print(tagged.toCanonicalIastFromDevanagari()); // kṛṣṇa
  print(tagged.toExactIastFromDevanagari()); // Kṛṣṇa

  print('कृष्ण©'.toCanonicalIastFromDevanagari()); // kṛṣṇa©
  print('कृष्ण©'.toCanonicalIastFromDevanagari(
    options: const ScriptToIastOptions(preserveUnmapped: false),
  )); // kṛṣṇa
}

ScriptToIastOptions

Options object controlling reverse transliteration behavior. Parameter fields, default values, and effects are detailed in §15 Reverse options.

10. Direct Devanagari ↔ Gujarati

Direct script conversion maps characters natively between Devanagari and Gujarati. Because the two scripts have unequal Unicode repertoires, Lipimala supports direct-script metadata trailers (using typed prefixes ISC:D: and ISC:G:) for 100% exact round-trip source script recovery.

Direct script conversion & metadata helper functions
Function Signature Parameters Output Type Behavior & Description
toGujaratiFromDevanagari(input, options?)
to_gujarati_from_devanagari()
input: string
options: IndicScriptConversionOptions?
string Smart Direct Conversion: Converts Devanagari to Gujarati. If an exact Gujarati source trailer (ISC:G:) is present, recovers original Gujarati; otherwise performs canonical conversion.
toCanonicalGujaratiFromDevanagari(input, options?)
to_canonical_gujarati_from_devanagari()
input: string
options: IndicScriptConversionOptions?
string Canonical Conversion: Maps Devanagari code points directly to Gujarati equivalents, ignoring any metadata trailers.
toExactGujaratiFromDevanagari(input)
to_exact_gujarati_from_devanagari()
input: string string Strict Exact Recovery: Decodes exact Gujarati source trailer (ISC:G:). Returns exact original Gujarati input text. Throws/raises an error if trailer is missing or invalid.
hasExactGujaratiSourceMetadata(input)
has_exact_gujarati_source_metadata()
input: string bool Returns true if the input text contains a valid direct Gujarati exact-source metadata trailer (ISC:G:).
toDevanagariFromGujarati(input, options?)
to_devanagari_from_gujarati()
input: string
options: IndicScriptConversionOptions?
string Smart Direct Conversion: Converts Gujarati to Devanagari. Recovers exact Devanagari if a ISC:D: trailer is present; otherwise performs canonical conversion.
toCanonicalDevanagariFromGujarati(input, options?)
to_canonical_devanagari_from_gujarati()
input: string
options: IndicScriptConversionOptions?
string Canonical Conversion: Maps Gujarati code points directly to Devanagari equivalents, ignoring metadata trailers.
toExactDevanagariFromGujarati(input)
to_exact_devanagari_from_gujarati()
input: string string Strict Exact Recovery: Decodes exact Devanagari source trailer (ISC:D:). Returns exact original Devanagari text. Throws/raises an error if trailer is missing or invalid.
hasExactDevanagariSourceMetadata(input)
has_exact_devanagari_source_metadata()
input: string bool Returns true if the input text contains a valid direct Devanagari exact-source metadata trailer (ISC:D:).
visibleWithoutExactSourceMetadata(input)
visible_without_exact_source_metadata()
input: string string Strips any embedded metadata trailer (whether Latin LIT1, Devanagari ISC:D:, or Gujarati ISC:G:) and returns clean visible script text.

Direct-script examples

The opposite direction is toCanonicalDevanagariFromGujarati, toDevanagariFromGujarati, and toExactGujaratiFromDevanagari. hasExactGujaratiSourceMetadata checks the other trailer. unknownPolicy: throwError raises when a character has no target letter. The low-level trailer helpers are in section 11.

import 'package:lipimala/lipimala.dart';

void main() {
  print(toCanonicalGujaratiFromDevanagari('कृष्ण २')); // કૃષ્ણ ૨
  print(toCanonicalGujaratiFromDevanagari(
    'कृष्ण २',
    options: const IndicScriptConversionOptions(
      digitPolicy: IndicScriptDigitPolicy.preserveSource,
    ),
  )); // કૃષ્ણ २
  print(toCanonicalGujaratiFromDevanagari(
    'कृष्ण  कृष्ण',
    options: const IndicScriptConversionOptions(collapseWhitespace: true),
  )); // કૃષ્ણ કૃષ્ણ

  final tagged = toGujaratiFromDevanagari(
    'कृष्ण',
    options: const IndicScriptConversionOptions(embedExactSourceMetadata: true),
  );
  print(hasExactDevanagariSourceMetadata(tagged)); // true
  print(visibleWithoutExactSourceMetadata(tagged)); // કૃષ્ણ
  print(toExactDevanagariFromGujarati(tagged)); // कृष्ण
}

11. Metadata & Unicode helpers

Low-level functions for manually manipulating embedded Unicode tag trailers, decoding checksummed metadata payloads, and performing Unicode 17.0.0 normalization and mark classification.

Shared metadata & Unicode utility functions
Function Signature Parameters & Types Output Type Usage & Behavior
embedExactSourceMetadata(rendered, originalSource)
embed_exact_source_metadata()
rendered: string
originalSource: string
string Manually attaches an invisible Unicode tag trailer encoding originalSource onto the end of rendered visible script string.
tryDecodeExactSourceMetadata(text)
try_decode_exact_source_metadata()
text: string EmbeddedExactSource | null Parses and verifies checksums of any embedded metadata trailer. Returns an EmbeddedExactSource object if valid, or null if missing/corrupted.
stripExactSourceMetadata(text)
strip_exact_source_metadata()
text: string string Strips any trailing invisible Unicode tag metadata sequence from text, returning pure display-only visible script string.
recoverEmbeddedExactSource(text)
recover_embedded_exact_source()
text: string string Decodes embedded metadata trailer and returns original source text. Throws/raises an exception if metadata is missing or invalid.
hasEmbeddedExactSource(text)
has_embedded_exact_source()
text: string bool Returns true if text ends with a valid, checksum-verified embedded exact-source metadata trailer.
normalizeUnicode(input, form)
normalize_unicode()
input: string
form: UnicodeNormalizationForm
string Performs canonical Unicode normalization (NFC, NFD, NFKC, or NFKD) using Unicode 17.0.0 rules.
isUnicodeCombiningMark(value)
is_unicode_combining_mark()
value: string | int (char/code point) bool Returns true if the specified character or code point is classified as a Unicode combining mark (Mn, Mc, or Me).
isEncodedVedicMark(value)
is_encoded_vedic_mark()
value: string | int (char/code point) bool Returns true if the specified character or code point is a recognized Vedic accent mark (e.g., svara, anudātta, svarita).

Metadata examples

0x094D is the Devanagari virama. 0x0951 is udātta. Direct-script metadata checks stay in section 10.

import 'package:lipimala/lipimala.dart';

void main() {
  final tagged = embedExactSourceMetadata('कृष्ण', 'Kṛṣṇa');
  final decoded = tryDecodeExactSourceMetadata(tagged)!;
  print(hasEmbeddedExactSource(tagged)); // true
  print(decoded.visibleText); // कृष्ण
  print(decoded.originalSource); // Kṛṣṇa
  print(stripExactSourceMetadata(tagged)); // कृष्ण
  print(recoverEmbeddedExactSource(tagged)); // Kṛṣṇa
  print(normalizeUnicode('a\u0304', UnicodeNormalizationForm.nfc) == 'ā'); // true
  print(isUnicodeCombiningMark(0x094D)); // true
  print(isEncodedVedicMark(0x0951)); // true
}

12. Result structures

TransliterationResult

Envelope fields and methods
Field / method Type Description
original string Exact source string from caller
normalizedInput string Source after input normalization
rendered string Converted view (may include trailer)
profile TransliterationProfile Profile used for this conversion
inputNormalization / outputNormalization UnicodeNormalizationForm Forms applied
renderingIsInjective bool Always false for these views
issues list of TransliterationIssue Diagnostics
originalCodePoints list<int> Integrity codes of original
restoreOriginal() string Returns original
hasErrors bool Any issue with severity error
toJson() / fromJson object / factory Serialize / rebuild with integrity check
toJsonText / fromJsonText string / factory JSON text form

JSON envelope shape

{
  "schema": "indic-script-converter/1" | "exact round-trip-indic-transliteration/1",
  "original": "Kṛṣṇa",
  "originalCodePoints": [75, 7771, 7779, 7751, 97],
  "normalizedInput": "...",
  "rendered": "कृष्ण",
  "profile": "extendedIndic",
  "inputNormalization": "nfd",
  "outputNormalization": "nfc",
  "renderingIsInjective": false,
  "issues": [
    { "code": "...", "message": "...", "severity": "info", "sourceRuneOffset": null }
  ]
}

TransliterationIssue

Issue object fields
Field Type Default
code string required
message string required
severity info | warning | error warning
sourceRuneOffset int | null null

EmbeddedExactSource

Fields: visibleText, originalSource.

13. Forward options (IAST → Deva / Gujr)

IastToDevanagariOptions / IastToGujaratiOptions

Forward conversion option fields
Field Values Default Effect
profile strictIast | iso15919Core | extendedIndic extendedIndic Accepted Latin inventory
unknownLatinPolicy passThrough | bracket | throwError passThrough Unknown Latin handling
digitPolicy preserveAscii | convertToScript preserveAscii ASCII vs script digits
punctuationPolicy preserve | indicDanda preserve Period → danda
omPolicy transliterateLetters | useOmSign transliterateLetters oṃ → letters vs ॐ/ૐ
ambiguousLPolicy context | preferVocalic | preferConsonant context Resolve ḷ
acceptAsciiLongVowels bool false Allow aa/ii/uu
acceptPlainSh bool true Plain sh
acceptPlainXAsKha bool true Compatibility for x
acceptWAsVa bool true Treat w as v
preserveVedicAccentMarks bool true Keep svara marks
collapseWhitespace bool false Collapse whitespace runs
embedExactSourceMetadata bool false Append exact-source trailer

Gujarati types mirror the same fields with Gujarati-prefixed enum type names.

14. Plain-English options

IastPlainEnglishOptions

Plain-English / Hunterian option fields
Field Values Default Effect
finalA keep | drop | smart smart Trailing inherent a
jna gya | jnya | jna gya jñ conjunct
nya na | nya | gna na Standalone ñ
profile strictIast | extendedIndic | hunterian extendedIndic hunterian is simplified ASCII Hunterian: one letter per long vowel, no consonant dots. See which Hunterian.
glottalStop remove | apostrophe remove ʔ handling
convertCToCh bool true c → ch style
assimilateAnusvara bool true Anusvara assimilation
removeAvagraha bool true Strip avagraha-like marks
collapseWhitespace bool false Whitespace collapse
enableInternalSchwaSyncope bool false Hunterian schwa drop
useWForVAfterConsonants bool false Hunterian v/w
preserveVedicAccentMarks bool false Usually stripped
keepFinalAForWords set/list empty Force keep final a

BrahmicPlainEnglishOptions 1.1.0 fields 1.2.0

Used only by direct Devanagari/Gujarati → readable Latin APIs. These options are separate from IastPlainEnglishOptions, preserving the pre-1.1.0 IAST API contract. Fields added in 1.2.0 are appended, so an existing positional constructor stays valid. Python uses snake_case names (readable_style, vowel_length, capitalize_sentence_starts, readable_word_overrides). Dart spells the schwa member finalOnly and the vowel-length member doubled. JavaScript, PHP, and Python spell those final and double.

Direct Brahmic → Plain-English / Hunterian option fields
FieldValuesDefaultEffect
languageauto | hindi | gujarati | sanskritautoResolves language-aware schwa and v/w behavior.
schwaDeletionnone | final | language
Dart: finalOnly
languageDeletes only internally marked inherent schwas; explicit written vowels are not removed. natural adds modern Hindi and Gujarati contraction. Sanskrit does not delete schwa.
vowelLengthcollapse | double | smart
Dart: doubled
double for Plain; collapse when a Hunterian helper omits itdouble writes aa/ee/oo. collapse writes a/i/u. smart is syllable spelling and applies only with readableStyle: natural. Sanskrit smart doubles every long vowel.
terminalAnusvaran | m | dropnReadable terminal anusvara/candrabindu fallback.
aynapostrophe | drop | preserveapostropheGujarati Arabic-transliteration ʿayn rendering.
jna / nyasame policies as IAST plain-English optionsgya / najñ and ñ readability.
glottalStopremove | apostropheremoveReadable glottal-stop treatment.
convertCToChbooltruec → ch readability style.
assimilateAnusvarabooltrueContextual nasal assimilation.
removeAvagrahabooltrueRemove avagraha-like marks in readable output.
collapseWhitespaceboolfalseCollapse whitespace runs.
preserveVedicAccentMarksboolfalseKeep pronunciation-neutral Vedic accent/cantillation marks when requested.
useWForVAfterConsonantsbool? / nullableautoOverride resolved-language contextual v/w behavior. Gujarati, and modern natural Hindi, do not apply blanket consonant-plus-v → w.
readableStylelegacy | naturallegacy1.2.0. natural opts into modern Hindi/Gujarati schwa, endings, and cluster spelling. Sanskrit stays conservative.
capitalizeSentenceStartsboolfalse1.2.0 presentation. Capitalizes a sentence start. It does not guess proper names.
readableWordOverridesmap of whole word → spellingempty1.2.0 presentation. Exact replacements after rendering, supplied by the caller.

15. Reverse options

ScriptToIastOptions

Options class controlling Brahmic → IAST reverse transliteration (Devanagari → IAST and Gujarati → IAST).

ScriptToIastOptions parameter fields & defaults
Field Name Type / Allowed Values Default Value Description & Behavior
targetProfile TransliterationProfile
(strictIast | extendedIndic)
strictIast Target character inventory profile for visible reverse mapping. strictIast uses standard academic IAST diacritics.
preserveVedicAccents bool true When true, preserves Vedic accent marks (svara, anudātta, svarita) in the reversed IAST output.
unknownPolicy passThrough | bracket | throwError passThrough Policy for unmapped input characters. passThrough keeps them as-is; bracket wraps them in [...]; throwError raises an exception.
digitPolicy preserveScriptDigits | convertToAsciiDigits preserveScriptDigits Determines whether Indic script digits (e.g. ०-९ or ૦-૯) are converted to ASCII digits (0-9) or preserved.
punctuationPolicy preserveDanda | convertToPeriod preserveDanda Determines whether Indic dandas (।, ॥) are converted to standard periods (.) or preserved.
collapseWhitespace bool false When true, collapses multiple consecutive whitespace characters into a single space.
ignoreEmbeddedMetadata bool false When true, forces toIastFromDevanagari() / toIastFromGujarati() to ignore any embedded metadata trailer and execute canonical visible reverse.

16. Direct-script options

IndicScriptConversionOptions

Direct Devanagari ↔ Gujarati options
Field Values Default Effect
inputNormalization preserve | nfc | nfd nfd Input normalize
outputNormalization preserve | nfc | nfd nfc Output normalize
unknownPolicy preserve | throwError preserve Unmapped chars
digitPolicy convertToTarget | preserveSource convertToTarget Digit block conversion
collapseWhitespace bool false Whitespace collapse
embedExactSourceMetadata bool false Typed exact source trailer

17. Dart-specific notes

The Dart implementation (package:lipimala) targets Dart 3.0+. It is usable in Dart applications and Flutter projects. It exposes both functional APIs and natural extensions on String. Option examples for each API are in the conversion sections above. Enum members here are natural, smart, and doubled.

  • Primary Barrel Import: import 'package:lipimala/lipimala.dart'; (exports all converters, options, enums, and result models).
  • String Extension APIs: Call 'Kṛṣṇa'.toDevanagari(), 'Kṛṣṇa'.toGujarati(), 'Kṛṣṇa'.toPlainEnglish() directly on String instances.
  • String Extension APIs: Dart uses extensions on String rather than wrapper/subclass return types. Envelope APIs return TransliterationResult; exact recovery is available through the result object or the metadata-aware reverse helpers.
  • Option Constructors: Options use named parameters with defaults: IastToDevanagariOptions(profile: DevanagariRomanizationProfile.extendedIndic, embedExactSourceMetadata: true).
  • Error Handling: Throws ArgumentError on invalid options or corrupted metadata trailers.

18. JavaScript-specific notes

The JavaScript implementation targets Node.js ≥ 20 and modern JavaScript environments using ES modules (ESM). Option examples for each API are in the conversion sections above. Enum members here are NATURAL, SMART, and DOUBLE.

  • Module Imports: ESM: import { toDevanagari, toDevanagariFromIast } from 'lipimala';
  • Dual Export Naming: Exports both camelCase (toDevanagariFromIast) and snake_case (to_devanagari_from_iast) aliases for all functions.
  • Flexible Options: String and direct converters accept new IastToDevanagariOptions({...}) or a plain object, with camelCase or snake_case keys. Envelope functions take { options, inputNormalization, outputNormalization }. Putting the option fields on that outer object does not apply them.
  • String Subclasses: String converters return instances of IastToDevanagariString, IastToGujaratiString, or IastToPlainEnglish extending native String, offering .toExactIast().
  • Error Handling: Throws standard TypeError or Error on bad arguments or metadata decoding failures.

19. Python-specific notes

The Python package (pip install lipimala) requires Python ≥ 3.12, utilizing modern type hints and dataclasses. Option examples for each API are in the conversion sections above. Use snake_case fields such as readable_style and vowel_length.

  • Imports: Main & direct script converters: from lipimala import to_devanagari, to_devanagari_from_iast, to_devanagari_from_gujarati
  • Function & Enum Aliases: Supports standard Python PEP 8 snake_case functions and camelCase aliases for cross-language parity. Enums inherit (str, Enum) and support both EXTENDED_INDIC and extendedIndic member access.
  • Dataclass Options: Options are Python @dataclass objects instantiated with keyword arguments: IastToDevanagariOptions(embed_exact_source_metadata=True).
  • String Subclass Returns: Returns IastToDevanagariString, IastToGujaratiString, IastToPlainEnglish subclasses of str with .to_exact_iast() / .restore_original().
  • Error Handling: Raises ValueError on invalid option configurations or corrupted metadata.

20. PHP-specific notes

The PHP port (composer require jayeshmepani/lipimala) requires PHP ≥ 8.3 with strict typing throughout. Option examples for each API are in the conversion sections above. Pass options with named arguments.

  • Namespace & Autoload: Namespace Lipimala. Import functions with use function Lipimala\toDevanagariFromIast;.
  • Dual Function Aliases: Supports both toDevanagariFromIast() and to_devanagari_from_iast() namespaced functions.
  • Final Readonly Options: Options are final readonly class instances with promoted constructor properties and default values. Options parameters are nullable (pass null for defaults).
  • Zero Runtime Dependencies: Pure PHP code with bundled Unicode 17.0.0 data tables; does not require mbstring or intl extensions.
  • Error Handling: Throws InvalidArgumentException on invalid parameters or failed metadata verification.

21. Example files

Each runtime has a comprehensive example that exercises public APIs with option permutations.

Runnable public-API example entry points
Language Path Run
Python python/examples/public_api_examples.py PYTHONPATH=python python3 python/examples/public_api_examples.py
JavaScript javascript/examples/public-api-examples.js node javascript/examples/public-api-examples.js
Dart dart/example/public_api_examples.dart cd dart && dart run example/public_api_examples.dart
PHP php/examples/public_api_examples.php php php/examples/public_api_examples.php

What each example covers

  1. Envelope APIs + JSON round-trip + normalization permutations
  2. IAST→Devanagari option permutations
  3. IAST→Gujarati option permutations
  4. Plain English / Hunterian option permutations
  5. Reverse canonical / smart / exact
  6. Direct Deva↔Gujr with policies + exact recovery
  7. Metadata helper functions

22. Verification & Unicode scope

1.1.0 release-hardening results, plus the 1.2.0 readable-Latin behavior locked by the current suites.

1.1.0 executed verification

  • JavaScript: 75/75 tests; Prettier + ESLint + quality gate passed.
  • Python: 74/74 tests and compileall passed.
  • PHP: 41 tests / 7,752 assertions; syntax, oracle runner, Rector dry-run passed.
  • Targeted JS/Python/PHP parity: 391/391.
  • Generated sequence/fuzz parity: 2,597/2,597.

Unicode repertoire handled by 1.1.0

  • Devanagari U+0900–U+097F
  • Gujarati U+0A80–U+0AFF
  • Common Indic Number Forms U+A830–U+A839
  • Devanagari Extended U+A8E0–U+A8FF
  • Applicable Vedic Extensions U+1CD0–U+1CFA
  • Devanagari Extended-A U+11B00–U+11B0A
  • ZWJ/ZWNJ/CGJ and dotted-circle handling

1.2.0: LEGACY calls keep the 1.1 readable output. The Brahmic plain-English suites in Dart, JavaScript, Python, and PHP lock that default, the golden Gujarati paragraph under NATURAL + SMART, Sanskrit conservatism, and the syllable cases (swaroopama, paasethi, hoonga, rashtrapati). dart analyze --fatal-infos is clean.

Unicode-version distinction: transliteration tables explicitly handle the Unicode 18 Devanagari/Gujarati repertoire targeted by this release. PHP's dependency-free normalization/case/mark database remains Unicode 17.0.0 and is intentionally labelled as such.

23. Errors & recovery matrix

Common failure modes and outcomes
Situation Typical outcome
unknownLatinPolicy = throwError Throws / raises on unmapped Latin
unknownPolicy = throwError (direct) Throws / raises on unmapped script chars
toExact* without trailer FormatException / TypeError / ValueError / InvalidArgumentException
toExact* with empty string Returns empty string
fromJson integrity failure Throws; schema or code-point mismatch
Tampered metadata trailer Checksum fails; treated as no exact source