Skip to main content

Zero-dependency script & phoneme-notation core — ISO-15924 detection & metadata, IPA↔ARPABET/X-SAMPA/Lexique/Kirshenbaum/Cotovía/RFE, Buckwalter↔Arabic, Hangul→jamo, kana

Project description

scriptconv

License: Apache 2.0 Build Tests PyPI version

scriptconv is a zero-dependency Python library for written-script and phoneme-notation operations:

  • Script identification & metadata — ISO-15924 detection, character-range lookup, typological script_type, base direction, mixed-script segmentation (script_runs), and language ↔ script mapping.
  • Phoneme-notation transcoding — IPA ↔ ARPABET, X-SAMPA, Lexique, Kirshenbaum, Cotovía and RFE, routed through IPA, with queryable per-notation fidelity metadata (NOTATION_INFO) and a looks_like_ipa detector.
  • Script transliteration & decomposition — Buckwalter ↔ Arabic script, Hangul → jamo (compatibility or conjoining), Hiragana ↔ Katakana.

Every conversion is a pure data table or arithmetic operation — no phonemization, no linguistic rules, no external files, and no runtime dependencies beyond the Python standard library.

Transcoding is reversible where the target inventory permits — see Fidelity guarantees for the exact per-notation guarantees.

Scope

scriptconv is exclusively about written scripts: identification and metadata, transliteration between script representations, re-encoding of phoneme symbols between notation systems, and orthographic decomposition. It never phonemizes — anything that requires knowing how a language sounds (grapheme-to-phoneme rules, allophony, coarticulation, sandhi) is outside this library's scope.

Installation

pip install scriptconv

Development

uv pip install -e '.[test]'
pytest tests/

tests/test_examples.py runs the scripts under examples/, which import the installed package — install with -e first.

Quick start

from scriptconv import (
    detect_script, char_script, script_distribution, script_runs, base_direction,
    lang_to_script, script_to_langs, normalize_script_tag, SCRIPT_REGISTRY,
    arpa_to_ipa, ipa_to_arpa,
    xsampa_to_ipa, ipa_to_xsampa,
    buckwalter_to_arabic, arabic_to_buckwalter,
    lexique_to_ipa, ipa_to_lexique,
    kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
    rfe_to_ipa, ipa_to_rfe, looks_like_ipa,
    decompose_hangul, hira_to_kana, kana_to_hira,
    convert, can_convert, convert_batch, Notation, NOTATION_INFO,
)

detect_script("안녕하세요")           # "Hang"
char_script("ɑ")                    # "Latn" (IPA Extensions)
script_distribution("Hello مرحبا")   # {'Latn': 5, 'Arab': 5}
script_runs("привет hello")          # [('Cyrl', 'привет '), ('Latn', 'hello')]
base_direction("مرحبا بالعالم")      # "rtl"
SCRIPT_REGISTRY["Arab"].script_type  # "abjad"  (typological class)

lang_to_script("pt-BR")             # "Latn"
script_to_langs("Cyrl")             # ['av', 'ba', 'be', 'bg', ...]
normalize_script_tag("syllabics")   # "Cans"
normalize_script_tag("japanese")    # "Hira"

arpa_to_ipa("HH AH0 L OW1")        # "həloʊ"
ipa_to_arpa("həloʊ")               # "HH AX L OW"

xsampa_to_ipa("tS")                 # "tʃ"
ipa_to_xsampa("ɹ")                  # "r\\"

buckwalter_to_arabic("mrHbA")       # "مرحبا"
arabic_to_buckwalter("مرحبا")      # "mrHbA"

lexique_to_ipa("b§ZuR")            # "bɔ̃ʒuʁ"  (bonjour)
ipa_to_lexique("vɛ̃")               # "v5"  (vin)

kirshenbaum_to_ipa("S")             # "ʃ"   (espeak-ng ASCII-IPA)
ipa_to_kirshenbaum("ŋ")             # "N"

cotovia_to_ipa("karro")             # "karo"  (Galician Cotovía TTS notation)
ipa_to_cotovia("ʎ")                 # "L"

rfe_to_ipa("kaša")                  # "kaʃa"  (Spanish/Romance RFE alphabet)
ipa_to_rfe("ɲ")                     # "ñ"

looks_like_ipa("pʰɑtʃ")             # True  (heuristic: has IPA-distinctive symbols)
looks_like_ipa("hello")             # False

decompose_hangul("국민")             # "ㄱㅜㄱㅁㅣㄴ"  (orthographic jamo, no assimilation)
hira_to_kana("ひらがな")             # "ヒラガナ"
kana_to_hira("カタカナ")             # "かたかな"

convert("NG", Notation.ARPA, Notation.XSAMPA)  # "N"
convert("HH AH0 L OW1", "arpa", "kirshenbaum") # "h@loU"
can_convert("arpa", "x-sampa")                 # True
can_convert("buckwalter", "ipa")               # False
list(convert_batch(["HH AH0", "AY1"], "arpa", "ipa"))  # ['hə', 'aɪ']

NOTATION_INFO[Notation.ARPA].lossless_from_ipa  # False (restricted inventory)

CLI

python -m scriptconv convert arpa ipa "HH AH0 L OW1"
python -m scriptconv detect "안녕하세요"
python -m scriptconv distribution "Hello مرحبا"
python -m scriptconv direction "مرحبا بالعالم"
python -m scriptconv decompose "국민"
python -m scriptconv lang ko

Modules

Module Contents
scriptconv.scripts Script dataclass (with script_type), SCRIPT_REGISTRY (34 scripts), detect_script, char_script, script_distribution, script_runs, base_direction, lang_to_script, script_to_langs, normalize_script_tag
scriptconv.notation Notation enum, NotationInfo/NOTATION_INFO fidelity registry, convert facade, can_convert predicate, convert_batch generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA, Cotovía ↔ IPA, RFE ↔ IPA), looks_like_ipa detector
scriptconv.translit decompose_hangul (Hangul blocks → jamo, compatibility or conjoining), hira_to_kana/kana_to_hira — all orthographic only

Documentation

  • docs/scripts.md — Script registry, detection, language mapping, label normalisation
  • docs/notation.md — Notation enum, per-pair converter reference, round-trip guarantees
  • docs/translit.md — Hangul decomposition arithmetic and scope boundary

Examples

Runnable scripts in examples/:

File Demonstrates
01_detect_script.py Mixed-script text triage
02_lang_to_script.py Language tag → ISO-15924 mapping
03_arpabet_roundtrip.py CMUdict-style line → IPA and back
04_xsampa.py X-SAMPA ↔ IPA, multi-char longest-first cases
05_buckwalter.py Arabic ↔ Buckwalter both directions
06_lexique.py French Lexique codes → IPA
07_hangul_decompose.py Hangul syllable blocks → jamo letters
08_script_distribution.py Character counts per script + base direction
09_script_to_langs.py Reverse lookup: script → languages
10_new_labels.py New normalize_script_tag labels (japanese, jamo, cjk…)
11_cli.py CLI interface: detect, distribution, direction, decompose, lang
12_kirshenbaum.py Kirshenbaum (ASCII-IPA) ↔ IPA, and ARPABET → Kirshenbaum routing
13_script_runs.py Per-script segmentation of mixed-script text
14_kana_transliteration.py Hiragana ↔ Katakana
15_cotovia.py Cotovía (Galician TTS notation) ↔ IPA
16_rfe.py RFE (Spanish/Romance philology alphabet) ↔ IPA

Fidelity guarantees

Transcoding faithfulness depends on the target notation's inventory. IPA is the hub; notation↔notation goes through IPA. The table below states, for each notation, whether a round-trip is exact and what happens to a symbol the table does not know.

Every converter (and convert()) accepts a codecs-style errors= policy for symbols outside its table: "pass" keeps the symbol (the default everywhere except ipa_to_arpa), "replace" substitutes the notation's placeholder (?; the historical ipa_to_arpa default, tunable via unknown=), "ignore" drops it, and "strict" raises UnknownSymbolError naming the symbol, its position, and the notation. The "Unknown-token behaviour" column below describes the per-converter default.

Notation to_ipafrom_ipa round-trip from_ipato_ipa round-trip Unknown-token behaviour
ARPABET Lossless with stress=True (digits ↔ IPA ˈ/ˌ before the stressed vowel; residues: extended-ARPABET AX normalises to CMUdict's AH0 spelling, and AH0 R fuses to the r-colored AXR0 — stable from the IPA side). Default stress=False drops digits and merges AH0AX Lossy — ARPABET is an English-only inventory, so any IPA symbol outside it becomes the unknown placeholder arpa_to_ipa: passed through unchanged. ipa_to_arpa: diacritics and suprasegmentals are dropped; other out-of-inventory symbols follow errors= (default "replace"?)
X-SAMPA Exact for all canonical symbols Exact except aliases (f\→ɸ, &→æ) normalise to their canonical spelling Passed through unchanged
Buckwalter ↔ Arabic Exact (the ^ shadda alias normalises to canonical ~; precomposed lam-alef ligatures decompose to two chars, visually identical) Exact Passed through unchanged
Lexique ↔ IPA Exact except the °/3 schwa pair (both → ə; reverse always → °) Exact Passed through unchanged
Kirshenbaum ↔ IPA Exact Lossy — restricted ASCII inventory; IPA outside it passes through Passed through unchanged
Cotovía ↔ IPA Exact except the three L/Z/jj symbols for ʎ normalise to L Lossy — Galician/Spanish inventory; IPA outside it passes through Passed through unchanged
RFE ↔ IPA Exact except ñ/ for ɲ normalise to ñ Lossy — core Spanish/Romance inventory; IPA outside it passes through Passed through unchanged

This table is also available programmatically via NOTATION_INFO (NotationInfo records with lossless_to_ipa, lossless_from_ipa, token_separated, and a reference citation per notation).

Notes:

  • The voiced velar stop is stored as script ɡ (U+0261) across all tables; ipa_to_arpa also accepts ASCII g (U+0067) on input.
  • Only ipa_to_arpa substitutes for unknowns today (because ARPABET is a restricted inventory); every other converter passes unknowns through. See docs/notation.md for the per-symbol detail.

License and attribution

scriptconv is released under the Apache-2.0 license.

Derived tables used internally:

Table Source License
ARPABET ↔ IPA chorusai/arpa2ipa Apache-2.0
Buckwalter ↔ Arabic Tim Buckwalter's Arabic transliteration scheme — (factual 1:1 mapping)
Lexique phoneme codes New, B. & Pallier, C. — Manuel de Lexique 3 v3.11, Tableau 2; chrplr/openlexicon CC BY-SA 4.0
Kirshenbaum ↔ IPA Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng — (factual symbol mapping)
Cotovía ↔ IPA Universidade de Vigo GTM Cotovía TTS project (fonemas.cpp) — (factual symbol mapping)
RFE ↔ IPA RFE phonetic alphabet (Revista de Filología Española, 1915) — (factual symbol mapping)
Hangul jamo tables stannam/hangul_to_ipa

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scriptconv-0.0.3a13.tar.gz (738.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scriptconv-0.0.3a13-py3-none-any.whl (719.5 kB view details)

Uploaded Python 3

File details

Details for the file scriptconv-0.0.3a13.tar.gz.

File metadata

  • Download URL: scriptconv-0.0.3a13.tar.gz
  • Upload date:
  • Size: 738.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for scriptconv-0.0.3a13.tar.gz
Algorithm Hash digest
SHA256 70cce23cfb53eae4eec25c14e782c7040a625fb6a967bf333284ff534e225956
MD5 e2ec7368b7f4718f372223a8c0b832bc
BLAKE2b-256 f597845c4e4cfc9a4285f69fa860c610f523fcb259eb77db82699340a555e3a9

See more details on using hashes here.

File details

Details for the file scriptconv-0.0.3a13-py3-none-any.whl.

File metadata

  • Download URL: scriptconv-0.0.3a13-py3-none-any.whl
  • Upload date:
  • Size: 719.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for scriptconv-0.0.3a13-py3-none-any.whl
Algorithm Hash digest
SHA256 99d1a44dba546024d0b7ba1125eb7cf48aef798b633ed71a7e09774d94e8b30b
MD5 c0fd708161f641de02c92a9a915f60dc
BLAKE2b-256 608872603eb1c2ed2dd4851ab78506e662915cc9ba9ae034823689c12045080b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page