Skip to main content

lipimala — Indic Script Converter (Python)

PyPI version Downloads Python Versions License: MIT Wheel Status

This directory is a Python 3.12+ port of the Indic Script Transliteration library (lipimala). It keeps the default extendedIndic behavior and provides all public conversion directions:

  • Latin/IAST → Devanagari
  • Latin/IAST → Gujarati
  • Latin/IAST → plain English/Hunterian
  • Devanagari → canonical Latin/IAST
  • Gujarati → canonical Latin/IAST
  • metadata-backed exact source recovery
  • exact round-trip result envelopes and JSON serialization

The runtime has zero required third-party dependencies. Python's standard unicodedata module supplies NFC/NFD normalization and Unicode mark categories.

Install

Package link on PyPI: pypi.org/project/lipimala

pip install lipimala

For tests:

python -m pip install -e '.[dev]'
python -m pytest

Basic conversions

from lipimala import (
    to_devanagari_from_iast,
    to_gujarati_from_iast,
    to_plain_english_from_iast,
    to_canonical_iast_from_devanagari,
    to_canonical_iast_from_gujarati,
)

assert to_devanagari_from_iast('Kṛṣṇa') == 'कृष्ण'
assert to_gujarati_from_iast('Kṛṣṇa') == 'કૃષ્ણ'
assert to_plain_english_from_iast('Kṛṣṇa') == 'Krishna'
assert to_canonical_iast_from_devanagari('कृष्ण') == 'kṛṣṇa'
assert to_canonical_iast_from_gujarati('કૃષ્ણ') == 'kṛṣṇa'

Bulk Sequence Transliteration

from lipimala import (
    to_devanagari_from_iast_list,
    to_gujarati_from_iast_list,
    to_plain_english_from_iast_list,
)

items = ['Kṛṣṇa', 'Rāma', 'jñāna']

assert to_devanagari_from_iast_list(items) == ['कृष्ण', 'राम', 'ज्ञान']
assert to_gujarati_from_iast_list(items) == ['કૃષ્ણ', 'રામ', 'જ્ઞાન']

Exact original-key recovery

Visible Brahmic output is many-to-one. For example, aliases, case, and NFC/NFD forms can render identically. Exact recovery therefore uses the same checksummed invisible Unicode-tag trailer as the Dart implementation.

from lipimala import (
    IastToDevanagariOptions,
    IastToGujaratiOptions,
    to_devanagari_from_iast,
    to_gujarati_from_iast,
    to_exact_iast_from_devanagari,
    to_exact_iast_from_gujarati,
)

source = 'Kṛṣṇa / Kr̥ṣṇa / ḫāna / ṣ́akti'

devanagari = to_devanagari_from_iast(
    source,
    IastToDevanagariOptions(embed_exact_source_metadata=True),
)
gujarati = to_gujarati_from_iast(
    source,
    IastToGujaratiOptions(embed_exact_source_metadata=True),
)

assert to_exact_iast_from_devanagari(devanagari) == source
assert to_exact_iast_from_gujarati(gujarati) == source

The metadata stores the exact UTF-16LE code-unit sequence and preserves:

  • case
  • precomposed versus decomposed spelling
  • combining-mark order
  • aliases
  • punctuation and whitespace
  • supplementary Unicode characters
  • unpaired UTF-16 surrogates through Python's surrogatepass handling

The trailer is rejected if either the visible rendering or encoded source payload is modified.

Exact Round-Trip envelope

import json

from lipimala import (
    TransliterationResult,
    to_plain_english,
)

result = to_plain_english('Kṛṣṇa ā́tman ḷa')
assert result.restore_original() == 'Kṛṣṇa ā́tman ḷa'

encoded = json.dumps(result.to_json(), ensure_ascii=False)
restored = TransliterationResult.from_json(json.loads(encoded))
assert restored.restore_original() == result.original

Devanagari ↔ Gujarati Direct Converter

This package includes a direct converter between Devanagari and Gujarati.

Canonical visible conversion

from lipimala import (
    to_canonical_gujarati_from_devanagari,
    to_canonical_devanagari_from_gujarati,
)

print(to_canonical_gujarati_from_devanagari('कृष्ण'))  # કૃષ્ણ
print(to_canonical_devanagari_from_gujarati('કૃષ્ણ'))  # कृष्ण

Exact exact round-trip round trip

The visible Gujarati and Devanagari repertoires are not one-to-one. Therefore, exact round-trip recovery uses a checksummed Unicode-tag trailer.

from lipimala.deva_gujr_converter import (
    IndicScriptConversionOptions,
    to_canonical_gujarati_from_devanagari,
    to_exact_devanagari_from_gujarati,
)

source = 'ऄ ऎ ऍ ॲ ऒ ऑ ॵ ळ ऴ ग़ ॻ ड़ ॸ ॾ'

tagged_gujarati = to_canonical_gujarati_from_devanagari(
    source,
    IndicScriptConversionOptions(embed_exact_source_metadata=True),
)

assert to_exact_devanagari_from_gujarati(tagged_gujarati) == source

The opposite Gujarati → Devanagari → exact Gujarati direction uses to_exact_gujarati_from_devanagari.

Smart exact-or-canonical APIs

These recover a correctly typed exact source trailer if present, and otherwise fall back to canonical visible conversion:

  • to_devanagari_from_gujarati(text, options)
  • to_gujarati_from_devanagari(text, options)

Strict exact APIs throw when typed metadata is absent or damaged:

  • to_exact_devanagari_from_gujarati(text)
  • to_exact_gujarati_from_devanagari(text)

Generate the verification outputs

Run from this directory after installation:

python3 -m tools.latn_iast_transliteration_verification.latn_iast_to_deva_test > latn_iast_to_deva_output.txt
python3 -m tools.latn_iast_transliteration_verification.latn_iast_to_gujr_test > latn_iast_to_gujr_output.txt
python3 -m tools.latn_iast_transliteration_verification.latn_iast_transcription_test > latn_iast_transcription_output.txt
python3 -m tools.latn_iast_transliteration_verification.deva_to_latn_iast_test > deva_to_latn_iast_output.txt
python3 -m tools.latn_iast_transliteration_verification.gujr_to_latn_iast_test > gujr_to_latn_iast_output.txt
python3 -m tools.latn_iast_transliteration_verification.deva_to_gujr_test > deva_to_gujr_output.txt
python3 -m tools.latn_iast_transliteration_verification.gujr_to_deva_test > gujr_to_deva_output.txt

Verification performed

The automated parity suite compares the Python implementation against the five supplied Dart-generated output files:

  • 497 Latin → Devanagari cases
  • 497 Latin → Gujarati cases
  • 497 Latin → plain-English cases
  • 497 Devanagari → canonical IAST cases
  • 497 Gujarati → canonical IAST cases

That is 2,485 exact result comparisons, including the complete supplied Vedic corpus. Additional tests cover exact metadata recovery, normalization distinctions, combining-mark order, supplementary characters, JSON envelopes, and tamper rejection.

Important distinction

to_canonical_iast_from_devanagari() and to_canonical_iast_from_gujarati() generate canonical reverse transliteration from visible text. They cannot infer the exact original alias or case. Use embed_exact_source_metadata=True plus to_exact_iast_from_*() when the exact original key must be recovered.

Metadata

Release files for lipimala 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lipimala 1.0.2
File Size Uploaded
lipimala-1.0.2.tar.gz 76.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lipimala 1.0.2
File Interpreter ABI Platform
lipimala-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 109.3 kB

Release files / lipimala-1.0.2.tar.gz

Download URL lipimala-1.0.2.tar.gz
Size 76.0 kB
Tags Source
SHA-256 checksum
How to use checksums
95d4dd89bfaa158204a23a3ff5bcdcb3715cb14cd03791e080114b1fb9ae65af
BLAKE2b-256 checksum
How to use checksums
81beaba6a81d4c068866716f53ed3366dabd2516652043599ebcc970205dab2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release files / lipimala-1.0.2-py3-none-any.whl

Download URL lipimala-1.0.2-py3-none-any.whl
Size 33.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ce89fd82da829d866caac04abf71e2a9c764345df17fc942244ff4bcef8d90f2
BLAKE2b-256 checksum
How to use checksums
77f8b413c16274c780e667c83cc1a9d9031b01d86d064404d0fcd9455bb344d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page