Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

orthography2ipa

orthography2ipa turns the spelling of a language into IPA, and it measures how languages relate to each other. Each language is a cited JSON spec in orthography2ipa/data/. A shared engine with no language-specific code turns the specs into transcriptions and into ranked pronunciation lattices. The library ships no trained weights.

The registry holds thousands of language codes, from major standard languages to dialects, creoles and reconstructed proto-languages. Most of them are stubs. Run orthography2ipa list for the live list, or browse the language explorer.

Install

uv pip install --prerelease=allow orthography2ipa

The runtime dependencies are numpy, langcodes and ovos-spec-tools. The extras are hf (Hugging Face lexicon sources), validation (pydantic schema checks), portuguese (the silabificador syllabifier) and test. To work on the repository, install it from a clone:

git clone https://github.com/TigreGotico/orthography2ipa
cd orthography2ipa
uv venv --python 3.11 .venv
uv pip install --python .venv --prerelease=allow -e '.[test]'

Quick start

import orthography2ipa
from orthography2ipa import G2P

orthography2ipa.transcribe("olá mundo", "pt")       # 'oˈla ˈmũdu'
orthography2ipa.transcribe("hello world", "en")     # 'ˈhɛləʊ ˈwɔːld'

result = G2P("pt-PT").transcribe_detailed("um café", search="beam", beam_width=4)
result.ipa                    # 'ˈũ kɐˈfɛ'
result.words[1].candidates    # (IPAPath('kɐfɛ', score=0.0), IPAPath('kafɛ', score=1.0), ...)

A code resolves to a registered spec. A bare tag gives the reference variety, and an unregistered regional tag gives the nearest spec:

orthography2ipa.resolve("pt")       # 'pt-PT'
orthography2ipa.resolve("en-NZ")    # 'en-GB'

en = orthography2ipa.get("en-GB")
en.graphemes["th"]     # ['θ', 'ð']: the phonemes a spelling can stand for
en.allophones["t"]     # ['t', 'tʰ', 'ʔ', 'ɾ']: how a phoneme can surface
en.family              # 'Indo-European > Germanic > Northwest Germanic > West Germanic'
en.quality             # <QualityTier.RESEARCH: 'research'>

The command line does the same work. Each subcommand takes --json:

orthography2ipa transcribe pt "olá mundo"                 # /oˈla ˈmũdu/
orthography2ipa transcribe en-GB "through" --search beam --beam-width 8
orthography2ipa info pt-BR
orthography2ipa list --family Ibero-Romance
orthography2ipa distance pt-BR pt-PT

docs/reference/cli.md holds the full --help output, and docs/reference/api.md lists every exported name.

The pronunciation lattice

When a spelling is ambiguous, the engine keeps every reading. For each grapheme it gives the IPA options with a -log P cost:

from orthography2ipa import get
from orthography2ipa.phonetok import PhonetokTokenizer

tok = PhonetokTokenizer(get("en-GB"))
for slot in tok.ipa_lattice("cough"):
    print(slot.grapheme, [(c.ipa, c.cost) for c in slot.candidates])
# c [('k', 0.0), ('s', 1.0)]
# ough [('ɔː', 0.0), ('əʊ', 1.0), ('ʌf', 2.0), ('ɒf', 3.0), ('aʊ', 4.0), ('uː', 5.0)]

G2P.word_confidence tells a downstream engine where the rules are unsure. G2P("en-GB").word_confidence("bar") is 1.0 and word_confidence("cough") is 0.6321. A downstream engine refines the lattice with a LatticeRescorer, which re-costs the candidates of a slot:

from orthography2ipa.phonetok import Candidate
from orthography2ipa.rescorer import LatticeRescorer

class RoughOugh(LatticeRescorer):
    def rescore(self, slot, context):
        if slot.grapheme != "ough":
            return slot.candidates
        others = [c for c in slot.candidates if c.ipa != "ʌf"]
        return [Candidate("ʌf", 0.0)] + [Candidate(c.ipa, c.cost + 1.0) for c in others]

tok.ipa_best("tough")                         # 'tɔː'
tok.ipa_best("tough", rescorer=RoughOugh())   # 'tʌf'

arbtok (Arabic), tugaphone (Portuguese), g2p_barranquenho and mwl_phonemizer build on this library. docs/lattice.md explains when to write a rescorer and when to keep a separate tokenizer. G2P.features(text) exports the lattice as features for a CRF or another ML model (docs/features.md).

Distance between languages

Two languages can be close on one axis and far apart on another, so each axis has its own measure:

Axis Question API
Phonological Do they use the same sounds? inventory_distance, allophone_overlap, phonological_distance
Reading Given the same text, do they sound alike? grapheme_divergence
Spelling Given the same sound, do they write it alike? spelling_divergence
Script Are the writing systems alike? script_distance, orthographic_distance
Genealogical Do they descend from the same ancestors? ancestry_similarity, ancestry_chain
Temporal Were they spoken at the same time? timespan, which decays ancestry weights
Geographic Are they spoken in the same place? geographic_distance
from orthography2ipa import get
from orthography2ipa.distance import phonological_distance, spelling_divergence

pt, es = get("pt-PT"), get("es-ES")
phonological_distance(pt, es).combined       # 0.2166: sounds only, never spelling
spelling_divergence(pt, es).mean_distance    # 0.2697

docs/distance.md describes every axis and its limits.

Benchmarks

The engine is scored against every gold set the harness can load, with no cap on the number of words. The scoreboard gives the PER, the word count and the provenance of each gold set. docs/comparison.md compares the same rows with espeak-ng, epitran and gruut. Some languages win and some lose.

A row whose gold is the output of espeak-ng or epitran measures agreement with that tool, not correctness. A row whose gold a language model wrote has no error model. Neither kind can qualify a spec for the production tier, and neither can block one. docs/benchmarks.md defines the reliability tiers.

AI transparency

Large language models (Anthropic Claude) wrote most specs, under the direction of a human maintainer. No small project can recruit a native-speaker linguist for thousands of languages. The choice was between an AI-written spec and no spec. Every mapping must trace to a published description: a reference grammar, a peer-reviewed paper or a university dataset. The engine stays language-agnostic, so a spec cannot hide logic. The tests check the structure, and the benchmarks score the output against external data.

A cited spec that a model wrote is still not native-speaker validation, and the quality tier records that. If you speak a language and its spec is wrong, open an issue with a citation or a native-speaker judgment. Corrections have priority over all other work here.

Documentation

License

Apache 2.0

Metadata

Release files for orthography2ipa 7.111.15a4

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

Source distribution (sdist)

Source distribution for orthography2ipa 7.111.15a4
File Size Uploaded Provenance Actions
orthography2ipa-7.111.15a4.tar.gz 5.8 MB Without provenance Details for orthography2ipa-7.111.15a4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for orthography2ipa 7.111.15a4
File Interpreter ABI Platform Actions
orthography2ipa-7.111.15a4-py3-none-any.whl Python 3 none any Details for orthography2ipa-7.111.15a4-py3-none-any.whl

Total release size: 15.1 MB

Release files / orthography2ipa-7.111.15a4.tar.gz

Download URL orthography2ipa-7.111.15a4.tar.gz
Size 5.8 MB
Tags Source
SHA-256 checksum
How to use checksums
8c0d97f7a6fa3bb3b42e2fb72d64d62190ffe615556d1e09761ff80a0ed557fe
BLAKE2b-256 checksum
How to use checksums
03f8559e5f50527de685ad52e025100bb64f11bd375c6578d2a6709641e65901
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / orthography2ipa-7.111.15a4-py3-none-any.whl

Download URL orthography2ipa-7.111.15a4-py3-none-any.whl
Size 9.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
ee181845eff4093885582ae4d555fd8be656935f8819949421722142b9d9eedf
BLAKE2b-256 checksum
How to use checksums
5226e03ae90eb12383dde23a688ffc0c22e0b2662aa725b76478b915246d1725
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for orthography2ipa 7.111.15a4

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release
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