Skip to main content

Dialect-aware Portuguese (Lusophone) text-to-IPA phonemizer

Project description

TugaPhone — Dialect-aware Portuguese Phonemizer

TugaPhone is a Python library that phonemizes arbitrary Portuguese text across major Lusophone dialects (pt-PT, pt-BR, pt-AO, pt-MZ, pt-TL). It uses a curated phonetic lexicon plus a rule-based fallback to deliver plausible phoneme transcriptions while preserving dialectal variation.

Choveu muito ontem à noite.
pt-PT-x-porto → ˈʃɔ·vew mˈũj·tu õ·ˈtẽ ˈa nˈuoj·tɨ 
pt-PT → ˈʃɔ·vew mˈũj·tu õ·ˈtẽ ˈa nˈoj·tɨ 
pt-BR → ˈʃɔ·vew mwˈĩ·tʊ õ·ˈtẽ ˈa nˈoj·tʃɪ 
pt-AO → ˈʃɔ·vew mˈũjn·tʊ õ·ˈtẽ ˈa nˈoj·tɨ 
pt-MZ → ˈʃɔ·vew mˈũj·tu õ·ˈtẽ ˈa nˈɔj·tɨ 
pt-TL → ˈʃɔ·vew mˈuj·tʊ õ·ˈtẽ ˈa nˈojtʰ 

🚀 Features

  • Multi-dialect support: European Portuguese (pt-PT), Brazilian Portuguese (pt-BR), Angolan (pt-AO), Mozambican (pt-MZ), and Timorese (pt-TL)
  • Regional accent modeling: Additional micro-dialects like Porto, Minho, Braga, Trás-os-Montes, and more
  • Hybrid approach: Combines a curated phonetic lexicon (Portuguese Phonetic Lexicon) with rule-based G2P fallback
  • Context-aware: Takes part-of-speech tags into account for homograph disambiguation
  • Number normalization: Automatically converts digits to their Portuguese spoken forms with proper gender agreement
  • Syllabification: Rule-based syllable boundary detection (~99.6% accuracy on benchmark)
  • Stress detection: Automatic stress placement following Portuguese phonological rules
  • IPA output: Full International Phonetic Alphabet transcription with stress markers and syllable boundaries

📦 Installation

pip install tugaphone

🧰 Usage

Companion libraries

The follow libraries are dependencies of tugaphone and might be useful on their own

Basic Phonemization

from tugaphone import TugaPhonemizer

ph = TugaPhonemizer()

sentences = [
    "O gato dorme.",
    "Tu falas português muito bem.",
    "O comboio chegou à estação.",
    "A menina comeu o pão todo.",
    "Vou pôr a manteiga no frigorífico."
]

for s in sentences:
    print(f"Sentence: {s}")
    for code in ["pt-PT", "pt-BR", "pt-AO", "pt-MZ", "pt-TL"]:
        phones = ph.phonemize_sentence(s, code)
        print(f"  {code}{phones}")
    print("-----")

Regional Dialects

from tugaphone import TugaPhonemizer
from tugaphone.regional import PortoDialect, MinhoDialect, BragaDialect

ph = TugaPhonemizer()

sentence = "O Porto é uma cidade bonita."

# Standard European Portuguese
print(f"pt-PT: {ph.phonemize_sentence(sentence, 'pt-PT')}")

# Porto accent (rising diphthongs, rhotic realization)
print(f"Porto: {ph.phonemize_sentence(sentence, regional_dialect=PortoDialect)}")

# Minho accent (vowel resistance, open vowels)
print(f"Minho: {ph.phonemize_sentence(sentence, regional_dialect=MinhoDialect)}")

Number Normalization

from tugaphone.number_utils import normalize_numbers

# Automatic gender agreement
print(normalize_numbers("vou comprar 1 casa"))    # uma casa
print(normalize_numbers("vou comprar 2 casas"))   # duas casas
print(normalize_numbers("vou adotar 1 cão"))      # um cão
print(normalize_numbers("vou adotar 2 cães"))     # dois cães

# Ordinals
print(normalize_numbers("1º lugar"))              # primeiro lugar
print(normalize_numbers("1ª vez"))                # primeira vez

# Large numbers with scale differences
print(normalize_numbers("897654356789098", "pt-PT"))  # long-scale (biliões)
print(normalize_numbers("897654356789098", "pt-BR"))  # short-scale (trilhões)

Advanced: Tokenization and Features

from tugaphone.tokenizer import Sentence
from tugaphone.dialects import EuropeanPortuguese

sentence = Sentence("O cão comeu o pão.", dialect=EuropeanPortuguese())

print(f"IPA: {sentence.ipa}")

# Access word-level details
for word in sentence.words:
    print(f"\nWord: {word.surface}")
    print(f"  Syllables: {'.'.join(word.syllables)}")
    print(f"  Stress: syllable {word.stressed_syllable_idx}")
    print(f"  IPA: {word.ipa}")
    
    # Access grapheme-level details
    for grapheme in word.graphemes:
        if grapheme.is_diphthong:
            print(f"  Diphthong: {grapheme.surface}{grapheme.ipa}")

📖 Documentation

Supported Dialects

Dialect Code Region Characteristics
pt-PT European Portuguese (Lisbon) Heavy vowel reduction, fricative palatalization, uvular /r/
pt-BR Brazilian Portuguese (Rio) Less vowel reduction, t/d palatalization, l-vocalization
pt-AO Angolan Portuguese (Luanda) Moderate vowel reduction, alveolar trill /r/, Bantu substrate
pt-MZ Mozambican Portuguese (Maputo) Similar to European with regional variation, Bantu influence
pt-TL Timorese Portuguese (Dili) Conservative pronunciation, Tetum substrate influence

Regional Accents (Experimental)

TugaPhone includes experimental support for sub-regional Portuguese accents:

  • PortoDialect: Rising diphthongs (o → uo), rhotic realization
  • MinhoDialect: Reduced vowel centralization, open vowel preference
  • BragaDialect: Palatal epenthesis (abelha → abeilha)
  • TrasMontanoDialect: Palatal affrication, s-voicing, final nasal denasalization
  • FafeDialect: Nasal diphthongization (gente → geinte)

Note: These are based on documented phonological features but should be considered approximate. Real-world variation is more complex.

Part-of-Speech Tagging

TugaPhone uses POS tags to disambiguate homographs:

from tugaphone import TugaPhonemizer

ph = TugaPhonemizer(postag_engine="spacy")  # or "brill", "auto"

# "para" has different pronunciations as preposition vs. verb
print(ph.phonemize_sentence("Vou para casa."))      # preposition
print(ph.phonemize_sentence("Ele para o carro."))   # verb

Supported engines:

  • spacy: Requires spacy and Portuguese model (most accurate)
  • brill: Requires brill-postaggers (lighter, faster)
  • lexicon: Uses built-in lexicon lookup (limited coverage)
  • auto: Falls back through available engines
  • dummy: Simple rule-based fallback (no dependencies)

🏗️ Architecture

TugaPhone uses a hierarchical tokenization model:

Sentence → Words → Graphemes → Characters

Each level applies context-sensitive phonological rules:

  1. Character level: Vowel quality, consonant allophones
  2. Grapheme level: Digraphs (ch, nh), diphthongs (ai, ou)
  3. Word level: Stress assignment, syllabification
  4. Sentence level: Prosodic boundaries (future: liaison, phrasal stress)

The phonemization process:

  1. Normalize text (numbers → words)
  2. POS tagging (for homograph disambiguation)
  3. Lexicon lookup (for known words)
  4. Rule-based G2P fallback (for unknown words)
  5. Dialect-specific transformations (regional accents)

⚠️ Limitations & Future Work

Current Limitations

  • Lexicon coverage: Many words (especially names, foreign words, neologisms) rely solely on rule-based fallback
  • Sparse coverage: African and Timorese dialects have less lexicon data than European/Brazilian
  • Lexical variation: Dialect-specific vocabulary (e.g., "trem" vs "comboio") is not handled; text is assumed orthographically consistent
  • Regional accents: Sub-regional dialects are experimental and approximate
  • Prosody: Sentence-level features (liaison, phrasal stress, intonation) are simplified
  • Homograph disambiguation: Limited to POS-based rules; doesn't handle semantic context

🤝 Contributing

Contributions are welcome! Areas where help is especially needed:

  • Lexicon expansion: Especially for pt-AO, pt-MZ, pt-TL
  • Regional accent validation: Native speaker verification of dialectal features
  • Test cases: Edge cases, challenging words, dialectal examples
  • Documentation: Usage examples, linguistic explanations

📄 License

This project is licensed under the Apache License 2.0. See LICENSE for details.

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

tugaphone-0.3.0a1.tar.gz (69.1 kB view details)

Uploaded Source

Built Distribution

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

tugaphone-0.3.0a1-py3-none-any.whl (65.2 kB view details)

Uploaded Python 3

File details

Details for the file tugaphone-0.3.0a1.tar.gz.

File metadata

  • Download URL: tugaphone-0.3.0a1.tar.gz
  • Upload date:
  • Size: 69.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tugaphone-0.3.0a1.tar.gz
Algorithm Hash digest
SHA256 34fa113607783aee1632242c725183df91e858d330fc767a193e8ff551408144
MD5 0684e0b97d0946120853a7481c4dc635
BLAKE2b-256 1694d4361578d120115dbb3ff9fb46d2a06e8bc754b9f0c1a422d7eedd48c4be

See more details on using hashes here.

File details

Details for the file tugaphone-0.3.0a1-py3-none-any.whl.

File metadata

  • Download URL: tugaphone-0.3.0a1-py3-none-any.whl
  • Upload date:
  • Size: 65.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tugaphone-0.3.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5ff3e44913c45b65b8b5ce06c620ad632103d836347d781b2abcb7ab8f98419
MD5 18b17a5b8a926e8d88dfd1984c92cfba
BLAKE2b-256 df66183c69ac7d8df769b8ad0a8159663ddc95dd8585b9f4309d0a9a5d7d8d31

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