A PHP 8.3+ port of the Indic-script conversion library (lipimala). It preserves identical conversion tables, profile defaults, contextual rules, Vedic handling, canonical reverse conversion, exact round-trip result envelope, and checksummed exact-source metadata format. The direct Gujarati ↔ Devanagari converter is included as well.
Package link on Packagist: packagist.org/packages/jayeshmepani/lipimala
composer require jayeshmepani/lipimala- PHP 8.3 or newer
declare(strict_types=1)throughout- no runtime package dependencies
- no
intl/mbstringrequirement - bundled Unicode 17.0.0 canonical normalization and mark data
The source project uses extendedIndic as the default forward profile, and this PHP port keeps that default.
- Latin/IAST + extended Indic → Devanagari
- Latin/IAST + extended Indic → Gujarati
- Latin/IAST → plain English
- explicit Hunterian view
- Devanagari → canonical IAST
- Gujarati → canonical IAST
- Devanagari → Gujarati
- Gujarati → Devanagari
- metadata-backed exact source recovery
- exact round-trip JSON envelope serialization
composer require jayeshmepani/lipimalarequire '/path/to/lipimala-php/autoload.php';- PHP 8.3 or newer
- No runtime dependencies — no
intl, nombstring
<?php
declare(strict_types=1);
require __DIR__ . '/autoload.php';
use function Lipimala\toCanonicalIastFromDevanagari;
use function Lipimala\toCanonicalIastFromGujarati;
use function Lipimala\toDevanagariFromIast;
use function Lipimala\toGujaratiFromIast;
use function Lipimala\toPlainEnglishFromIast;
echo toDevanagariFromIast('Kṛṣṇa'); // कृष्ण
echo toGujaratiFromIast('Kṛṣṇa'); // કૃષ્ણ
echo toPlainEnglishFromIast('Kṛṣṇa'); // Krishna
echo toCanonicalIastFromDevanagari('कृष्ण'); // kṛṣṇa
echo toCanonicalIastFromGujarati('કૃષ્ણ'); // kṛṣṇause function Lipimala\toDevanagariFromIastList;
use function Lipimala\toGujaratiFromIastList;
$items = ['Kṛṣṇa', 'Rāma', 'jñāna'];
$devaList = toDevanagariFromIastList($items);
// -> ['कृष्ण', 'राम', 'ज्ञान']
$gujrList = toGujaratiFromIastList($items);
// -> ['કૃષ્ણ', 'રામ', 'જ્ઞાન']The default is extendedIndic:
use Lipimala\DevanagariRomanizationProfile;
use Lipimala\IastToDevanagariOptions;
$options = new IastToDevanagariOptions(
profile: DevanagariRomanizationProfile::EXTENDED_INDIC,
);The forward script APIs expose the same policy families as the source implementation:
strictIastiso15919CoreextendedIndic- unknown Latin handling
- digit conversion/preservation
- punctuation preservation/Indic danda
- OM letter/sign policy
- ambiguous
ḷhandling - ASCII long-vowel aliases
sh,x,wcompatibility switches- Vedic accent preservation
- whitespace collapse
- exact-source metadata embedding
Visible Brahmic output is necessarily many-to-one. Case, source normalization, aliases, and equivalent extended spellings can collapse to the same visible script. Exact recovery therefore uses the same invisible Unicode-Tag trailer as the Dart/Python/JavaScript implementations.
use Lipimala\IastToDevanagariOptions;
use function Lipimala\toDevanagariFromIast;
use function Lipimala\toExactIastFromDevanagari;
$source = 'Kṛṣṇa / Kr̥ṣṇa / ḫāna / ṣ́akti';
$tagged = toDevanagariFromIast(
$source,
new IastToDevanagariOptions(
embedExactSourceMetadata: true,
),
);
assert(toExactIastFromDevanagari($tagged) === $source);Gujarati uses IastToGujaratiOptions and toExactIastFromGujarati().
The metadata encodes the exact UTF-16LE source unit sequence, stores independent FNV-1a checksums for source and visible rendering, and rejects corrupted/tampered trailers. The PHP implementation is byte-for-byte compatible with the supplied cross-language metadata vector, including supplementary code points and isolated UTF-16 surrogate units.
toIastFromDevanagari() exact metadata when present, canonical otherwise
toExactIastFromDevanagari() metadata required
toCanonicalIastFromDevanagari() always canonical visible reverse
toIastFromGujarati() exact metadata when present, canonical otherwise
toExactIastFromGujarati() metadata required
toCanonicalIastFromGujarati() always canonical visible reverse
Canonical reverse cannot infer which Latin alias/case/normalization originally produced a visible script string.
Canonical visible conversion:
use function Lipimala\toCanonicalDevanagariFromGujarati;
use function Lipimala\toCanonicalGujaratiFromDevanagari;
echo toCanonicalGujaratiFromDevanagari('कृष्ण'); // કૃષ્ણ
echo toCanonicalDevanagariFromGujarati('કૃષ્ણ'); // कृष्णThe two scripts have unequal Unicode repertoires, so visible conversion is non-injective. Exact script-source recovery uses a typed source marker inside the same metadata trailer:
use Lipimala\IndicScriptConversionOptions;
use function Lipimala\toCanonicalGujaratiFromDevanagari;
use function Lipimala\toExactDevanagariFromGujarati;
$source = 'ऄ ऎ ऍ ॲ ऒ ऑ ॵ ळ ऴ ग़ ॻ ड़ ॸ ॾ';
$taggedGujarati = toCanonicalGujaratiFromDevanagari(
$source,
new IndicScriptConversionOptions(
embedExactSourceMetadata: true,
),
);
assert(toExactDevanagariFromGujarati($taggedGujarati) === $source);The opposite direction uses toCanonicalDevanagariFromGujarati() and toExactGujaratiFromDevanagari().
Direct conversion also exposes source-digit preservation, target-digit conversion, unknown-character preservation/strict error, normalization, whitespace collapse, and exact round-trip-envelope APIs.
The forward implementation keeps the source library's Unicode-recommended Brahmic storage order: vowel/matra, then bindu/visarga, then svara. Forms such as वसोः॑ and जुष्टं॑ therefore remain unchanged from the verified Dart behavior.
use function Lipimala\toDevanagari;
$result = toDevanagari('Kṛṣṇa');
$json = $result->toJsonText();
$original = $result->restoreOriginal();The envelope schema is exact round-trip-indic-transliteration/1 and includes original code-point integrity checking.
Run from the PHP project root:
php tools/latn_iast_transliteration_verification/latn_iast_to_deva_test.php > latn_iast_to_deva_output.txt
php tools/latn_iast_transliteration_verification/latn_iast_to_gujr_test.php > latn_iast_to_gujr_output.txt
php tools/latn_iast_transliteration_verification/latn_iast_transcription_test.php > latn_iast_transcription_output.txt
php tools/latn_iast_transliteration_verification/deva_to_latn_iast_test.php > deva_to_latn_iast_output.txt
php tools/latn_iast_transliteration_verification/gujr_to_latn_iast_test.php > gujr_to_latn_iast_output.txt
php tools/latn_iast_transliteration_verification/deva_to_gujr_test.php > deva_to_gujr_output.txt
php tools/latn_iast_transliteration_verification/gujr_to_deva_test.php > gujr_to_deva_output.txtAll runners JSON-escape each source/result string so quotes and embedded newlines cannot corrupt record boundaries.
Run every output generator:
php tools/latn_iast_transliteration_verification/run_all.phpphp tests/run.phpThe bundled regression suite verifies the five original 497-case directions, both 497-case direct script directions, all 22 Vedic fixtures, profile/option behavior, exact metadata, tamper rejection, exact round-trip JSON envelopes, and exact direct-script corpus recovery.
See PORT_VERIFICATION.md for the executed result and parity counts.