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.15a2

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.15a2
File Size Uploaded Provenance Actions
orthography2ipa-7.111.15a2.tar.gz 5.9 MB Without provenance Details for orthography2ipa-7.111.15a2.tar.gz

Built distribution (wheel)

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

Total release size: 15.2 MB

Release files / orthography2ipa-7.111.15a2.tar.gz

Download URL orthography2ipa-7.111.15a2.tar.gz
Size 5.9 MB
Tags Source
SHA-256 checksum
How to use checksums
e1ca93abc5234582952697f755e59188d9f22eb211c91925d1c48f00d4220daa
BLAKE2b-256 checksum
How to use checksums
d4b777467294b2787c765dd0b8cda1bfa23eaffbc32307ce283c0548e69569d2
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.15a2-py3-none-any.whl

Download URL orthography2ipa-7.111.15a2-py3-none-any.whl
Size 9.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3ccf3998179b3b63cb92a0b14235e8b0cebaf18dbc093b6867583345d3f43cb8
BLAKE2b-256 checksum
How to use checksums
9b9febf9ec95cc191fe6c1555d706c0be3b6f3c2e7ee8682043f6b2c9ffa463e
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.15a2

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