""" IPA Data Module — Shared phoneme data for all IPA Hugging Face Spaces. Contains: - Full IPA consonant inventory with articulatory features - Full IPA vowel inventory with height/backness/rounding - Spanish phoneme annotations and example words - Chart layout constants (place/manner ordering, vowel trapezoid coordinates) """ # ============================================================================= # CONSONANT CHART DATA # ============================================================================= # Column order for the consonant chart (place of articulation) CONSONANT_PLACES = [ "bilabial", "labiodental", "dental", "alveolar", "postalveolar", "retroflex", "palatal", "velar", "uvular", "pharyngeal", "glottal", ] # Row order for the consonant chart (manner of articulation) CONSONANT_MANNERS = [ "plosive", "nasal", "trill", "tap/flap", "fricative", "lateral fricative", "approximant", "lateral approximant", ] # Full IPA consonant data # Each entry: symbol -> {place, manner, voicing, name, spanish, spanish_example, espeak_code, languages} CONSONANTS = { # === PLOSIVES === "p": { "place": "bilabial", "manner": "plosive", "voicing": "voiceless", "name": "voiceless bilabial plosive", "spanish": True, "spanish_example": "padre", "espeak_code": "p", "languages": ["English", "Spanish", "French", "German", "Mandarin"], }, "b": { "place": "bilabial", "manner": "plosive", "voicing": "voiced", "name": "voiced bilabial plosive", "spanish": True, "spanish_example": "boca", "espeak_code": "b", "languages": ["English", "Spanish", "French", "Arabic"], }, "t": { "place": "alveolar", "manner": "plosive", "voicing": "voiceless", "name": "voiceless alveolar plosive", "spanish": True, "spanish_example": "taza", "espeak_code": "t", "languages": ["English", "Spanish", "French", "German"], }, "d": { "place": "alveolar", "manner": "plosive", "voicing": "voiced", "name": "voiced alveolar plosive", "spanish": True, "spanish_example": "dedo", "espeak_code": "d", "languages": ["English", "Spanish", "French", "Italian"], }, "t\u0288": { # ʈ "place": "retroflex", "manner": "plosive", "voicing": "voiceless", "name": "voiceless retroflex plosive", "spanish": False, "spanish_example": None, "espeak_code": "t.", "languages": ["Hindi", "Swedish", "Norwegian"], }, "\u0256": { # ɖ "place": "retroflex", "manner": "plosive", "voicing": "voiced", "name": "voiced retroflex plosive", "spanish": False, "spanish_example": None, "espeak_code": "d.", "languages": ["Hindi", "Tamil", "Swedish"], }, "c": { "place": "palatal", "manner": "plosive", "voicing": "voiceless", "name": "voiceless palatal plosive", "spanish": False, "spanish_example": None, "espeak_code": "c", "languages": ["Hungarian", "Turkish", "Greek"], }, "\u025f": { # ɟ "place": "palatal", "manner": "plosive", "voicing": "voiced", "name": "voiced palatal plosive", "spanish": False, "spanish_example": None, "espeak_code": "J", "languages": ["Hungarian", "Turkish", "Latvian"], }, "k": { "place": "velar", "manner": "plosive", "voicing": "voiceless", "name": "voiceless velar plosive", "spanish": True, "spanish_example": "casa", "espeak_code": "k", "languages": ["English", "Spanish", "French", "German", "Mandarin"], }, "\u0261": { # ɡ "place": "velar", "manner": "plosive", "voicing": "voiced", "name": "voiced velar plosive", "spanish": True, "spanish_example": "gato", "espeak_code": "g", "languages": ["English", "Spanish", "French", "German"], }, "q": { "place": "uvular", "manner": "plosive", "voicing": "voiceless", "name": "voiceless uvular plosive", "spanish": False, "spanish_example": None, "espeak_code": "q", "languages": ["Arabic", "Quechua", "Inuktitut"], }, "\u0262": { # ɢ "place": "uvular", "manner": "plosive", "voicing": "voiced", "name": "voiced uvular plosive", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Somali", "Inuktitut"], }, "\u0294": { # ʔ "place": "glottal", "manner": "plosive", "voicing": "voiceless", "name": "glottal stop", "spanish": False, "spanish_example": None, "espeak_code": "?", "languages": ["English (uh-oh)", "Arabic", "Hawaiian", "German"], }, # === NASALS === "m": { "place": "bilabial", "manner": "nasal", "voicing": "voiced", "name": "voiced bilabial nasal", "spanish": True, "spanish_example": "madre", "espeak_code": "m", "languages": ["English", "Spanish", "French", "German", "Mandarin"], }, "\u0271": { # ɱ "place": "labiodental", "manner": "nasal", "voicing": "voiced", "name": "voiced labiodental nasal", "spanish": False, "spanish_example": None, "espeak_code": "M", "languages": ["English (comfort)", "Italian", "Dutch"], }, "n": { "place": "alveolar", "manner": "nasal", "voicing": "voiced", "name": "voiced alveolar nasal", "spanish": True, "spanish_example": "noche", "espeak_code": "n", "languages": ["English", "Spanish", "French", "German", "Mandarin"], }, "\u0273": { # ɳ "place": "retroflex", "manner": "nasal", "voicing": "voiced", "name": "voiced retroflex nasal", "spanish": False, "spanish_example": None, "espeak_code": "n.", "languages": ["Hindi", "Swedish", "Norwegian"], }, "\u0272": { # ɲ "place": "palatal", "manner": "nasal", "voicing": "voiced", "name": "voiced palatal nasal", "spanish": True, "spanish_example": "niño (ñ)", "espeak_code": "n^", "languages": ["Spanish", "French (cognac)", "Italian", "Portuguese"], }, "\u014b": { # ŋ "place": "velar", "manner": "nasal", "voicing": "voiced", "name": "voiced velar nasal", "spanish": True, "spanish_example": "tengo (before g/k)", "espeak_code": "N", "languages": ["English (sing)", "Spanish", "German", "Mandarin"], }, "\u0274": { # ɴ "place": "uvular", "manner": "nasal", "voicing": "voiced", "name": "voiced uvular nasal", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Japanese", "Inuktitut"], }, # === TRILLS === "\u0299": { # ʙ "place": "bilabial", "manner": "trill", "voicing": "voiced", "name": "voiced bilabial trill", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Nias", "Titan"], }, "r": { "place": "alveolar", "manner": "trill", "voicing": "voiced", "name": "voiced alveolar trill", "spanish": True, "spanish_example": "perro", "espeak_code": "r", "languages": ["Spanish", "Italian", "Russian", "Arabic"], }, "\u0280": { # ʀ "place": "uvular", "manner": "trill", "voicing": "voiced", "name": "voiced uvular trill", "spanish": False, "spanish_example": None, "espeak_code": "R", "languages": ["French", "German", "Dutch"], }, # === TAPS / FLAPS === "\u2c71": { # ⱱ "place": "labiodental", "manner": "tap/flap", "voicing": "voiced", "name": "voiced labiodental flap", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Mono", "some Central African languages"], }, "\u027e": { # ɾ "place": "alveolar", "manner": "tap/flap", "voicing": "voiced", "name": "voiced alveolar tap", "spanish": True, "spanish_example": "pero", "espeak_code": "*", "languages": ["Spanish", "Japanese", "Korean", "Portuguese"], }, "\u027d": { # ɽ "place": "retroflex", "manner": "tap/flap", "voicing": "voiced", "name": "voiced retroflex flap", "spanish": False, "spanish_example": None, "espeak_code": "*.", "languages": ["Hindi", "Urdu", "Hausa"], }, # === FRICATIVES === "\u0278": { # ɸ "place": "bilabial", "manner": "fricative", "voicing": "voiceless", "name": "voiceless bilabial fricative", "spanish": False, "spanish_example": None, "espeak_code": "F", "languages": ["Japanese (fu)", "Ewe"], }, "\u03b2": { # β "place": "bilabial", "manner": "fricative", "voicing": "voiced", "name": "voiced bilabial fricative", "spanish": True, "spanish_example": "lobo (allophone of /b/)", "espeak_code": "B", "languages": ["Spanish (allophone)", "Ewe", "Japanese"], }, "f": { "place": "labiodental", "manner": "fricative", "voicing": "voiceless", "name": "voiceless labiodental fricative", "spanish": True, "spanish_example": "fuego", "espeak_code": "f", "languages": ["English", "Spanish", "French", "German"], }, "v": { "place": "labiodental", "manner": "fricative", "voicing": "voiced", "name": "voiced labiodental fricative", "spanish": False, "spanish_example": None, "espeak_code": "v", "languages": ["English", "French", "German", "Russian"], }, "\u03b8": { # θ "place": "dental", "manner": "fricative", "voicing": "voiceless", "name": "voiceless dental fricative", "spanish": True, "spanish_example": "zapato (Castilian)", "espeak_code": "T", "languages": ["English (think)", "Spanish (Castilian)", "Greek"], }, "\u00f0": { # ð "place": "dental", "manner": "fricative", "voicing": "voiced", "name": "voiced dental fricative", "spanish": True, "spanish_example": "dedo (allophone of /d/)", "espeak_code": "D", "languages": ["English (the)", "Spanish (allophone)", "Icelandic"], }, "s": { "place": "alveolar", "manner": "fricative", "voicing": "voiceless", "name": "voiceless alveolar fricative", "spanish": True, "spanish_example": "sol", "espeak_code": "s", "languages": ["English", "Spanish", "French", "German", "Mandarin"], }, "z": { "place": "alveolar", "manner": "fricative", "voicing": "voiced", "name": "voiced alveolar fricative", "spanish": False, "spanish_example": None, "espeak_code": "z", "languages": ["English", "French", "Italian", "Russian"], }, "\u0283": { # ʃ "place": "postalveolar", "manner": "fricative", "voicing": "voiceless", "name": "voiceless postalveolar fricative", "spanish": False, "spanish_example": None, "espeak_code": "S", "languages": ["English (ship)", "French (chat)", "German (schön)"], }, "\u0292": { # ʒ "place": "postalveolar", "manner": "fricative", "voicing": "voiced", "name": "voiced postalveolar fricative", "spanish": False, "spanish_example": None, "espeak_code": "Z", "languages": ["English (measure)", "French (je)", "Portuguese"], }, "\u0282": { # ʂ "place": "retroflex", "manner": "fricative", "voicing": "voiceless", "name": "voiceless retroflex fricative", "spanish": False, "spanish_example": None, "espeak_code": "s.", "languages": ["Mandarin (sh)", "Polish", "Sanskrit"], }, "\u0290": { # ʐ "place": "retroflex", "manner": "fricative", "voicing": "voiced", "name": "voiced retroflex fricative", "spanish": False, "spanish_example": None, "espeak_code": "z.", "languages": ["Mandarin (r-)", "Polish", "Russian"], }, "\u00e7": { # ç "place": "palatal", "manner": "fricative", "voicing": "voiceless", "name": "voiceless palatal fricative", "spanish": False, "spanish_example": None, "espeak_code": "C", "languages": ["German (ich)", "Greek", "Japanese (hi)"], }, "\u029d": { # ʝ "place": "palatal", "manner": "fricative", "voicing": "voiced", "name": "voiced palatal fricative", "spanish": True, "spanish_example": "mayo (some dialects)", "espeak_code": "j", "languages": ["Spanish (some dialects)", "Greek", "Irish"], }, "x": { "place": "velar", "manner": "fricative", "voicing": "voiceless", "name": "voiceless velar fricative", "spanish": True, "spanish_example": "jota", "espeak_code": "x", "languages": ["Spanish", "German (Bach)", "Russian", "Arabic"], }, "\u0263": { # ɣ "place": "velar", "manner": "fricative", "voicing": "voiced", "name": "voiced velar fricative", "spanish": True, "spanish_example": "lago (allophone of /g/)", "espeak_code": "Q", "languages": ["Spanish (allophone)", "Greek", "Irish"], }, "\u03c7": { # χ "place": "uvular", "manner": "fricative", "voicing": "voiceless", "name": "voiceless uvular fricative", "spanish": False, "spanish_example": None, "espeak_code": "X", "languages": ["German (some dialects)", "Hebrew", "Welsh"], }, "\u0281": { # ʁ "place": "uvular", "manner": "fricative", "voicing": "voiced", "name": "voiced uvular fricative", "spanish": False, "spanish_example": None, "espeak_code": "g\"", "languages": ["French (r)", "German (r)", "Dutch"], }, "\u0127": { # ħ "place": "pharyngeal", "manner": "fricative", "voicing": "voiceless", "name": "voiceless pharyngeal fricative", "spanish": False, "spanish_example": None, "espeak_code": "H", "languages": ["Arabic (ح)", "Hebrew", "Somali"], }, "\u0295": { # ʕ "place": "pharyngeal", "manner": "fricative", "voicing": "voiced", "name": "voiced pharyngeal fricative", "spanish": False, "spanish_example": None, "espeak_code": "Q\"", "languages": ["Arabic (ع)", "Hebrew", "Somali"], }, "h": { "place": "glottal", "manner": "fricative", "voicing": "voiceless", "name": "voiceless glottal fricative", "spanish": True, "spanish_example": "huevo (some dialects)", "espeak_code": "h", "languages": ["English", "German", "Japanese", "Arabic"], }, "\u0266": { # ɦ "place": "glottal", "manner": "fricative", "voicing": "voiced", "name": "voiced glottal fricative", "spanish": False, "spanish_example": None, "espeak_code": "h\\", "languages": ["Dutch", "Czech", "Ukrainian"], }, # === LATERAL FRICATIVES === "\u026c": { # ɬ "place": "alveolar", "manner": "lateral fricative", "voicing": "voiceless", "name": "voiceless alveolar lateral fricative", "spanish": False, "spanish_example": None, "espeak_code": "l#", "languages": ["Welsh (ll)", "Zulu", "Navajo"], }, "\u026e": { # ɮ "place": "alveolar", "manner": "lateral fricative", "voicing": "voiced", "name": "voiced alveolar lateral fricative", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Mongolian", "Zulu"], }, # === APPROXIMANTS === "\u028b": { # ʋ "place": "labiodental", "manner": "approximant", "voicing": "voiced", "name": "voiced labiodental approximant", "spanish": False, "spanish_example": None, "espeak_code": "v#", "languages": ["Dutch", "Finnish", "Hindi"], }, "\u0279": { # ɹ "place": "alveolar", "manner": "approximant", "voicing": "voiced", "name": "voiced alveolar approximant", "spanish": False, "spanish_example": None, "espeak_code": "r\\", "languages": ["English (red)", "some Dutch dialects"], }, "\u027b": { # ɻ "place": "retroflex", "manner": "approximant", "voicing": "voiced", "name": "voiced retroflex approximant", "spanish": False, "spanish_example": None, "espeak_code": "r\\.", "languages": ["Tamil", "American English (r)"], }, "j": { "place": "palatal", "manner": "approximant", "voicing": "voiced", "name": "voiced palatal approximant", "spanish": True, "spanish_example": "yo (some dialects)", "espeak_code": "j\\", "languages": ["English (yes)", "Spanish", "French", "German"], }, "w": { "place": "velar", "manner": "approximant", "voicing": "voiced", "name": "voiced labial-velar approximant", "spanish": True, "spanish_example": "huevo", "espeak_code": "w", "languages": ["English", "Spanish", "French", "Mandarin"], }, # === LATERAL APPROXIMANTS === "l": { "place": "alveolar", "manner": "lateral approximant", "voicing": "voiced", "name": "voiced alveolar lateral approximant", "spanish": True, "spanish_example": "luna", "espeak_code": "l", "languages": ["English", "Spanish", "French", "German"], }, "\u026d": { # ɭ "place": "retroflex", "manner": "lateral approximant", "voicing": "voiced", "name": "voiced retroflex lateral approximant", "spanish": False, "spanish_example": None, "espeak_code": "l.", "languages": ["Tamil", "Hindi", "Norwegian"], }, "\u028e": { # ʎ "place": "palatal", "manner": "lateral approximant", "voicing": "voiced", "name": "voiced palatal lateral approximant", "spanish": True, "spanish_example": "calle (traditional)", "espeak_code": "l^", "languages": ["Spanish (traditional)", "Italian", "Portuguese", "Catalan"], }, "\u029f": { # ʟ "place": "velar", "manner": "lateral approximant", "voicing": "voiced", "name": "voiced velar lateral approximant", "spanish": False, "spanish_example": None, "espeak_code": "L", "languages": ["Mid-Waghi", "some PNG languages"], }, } # ============================================================================= # VOWEL CHART DATA # ============================================================================= # Vowel height levels (top to bottom) VOWEL_HEIGHTS = ["close", "near-close", "close-mid", "mid", "open-mid", "near-open", "open"] # Vowel backness levels (left to right) VOWEL_BACKNESSES = ["front", "central", "back"] # Full IPA vowel data VOWELS = { # === CLOSE VOWELS === "i": { "height": "close", "backness": "front", "rounding": "unrounded", "name": "close front unrounded vowel", "spanish": True, "spanish_example": "sí", "espeak_code": "i", "languages": ["English (see)", "Spanish", "French", "German"], }, "y": { "height": "close", "backness": "front", "rounding": "rounded", "name": "close front rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "y", "languages": ["French (tu)", "German (über)", "Finnish", "Mandarin (ü)"], }, "\u0268": { # ɨ "height": "close", "backness": "central", "rounding": "unrounded", "name": "close central unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "i\"", "languages": ["Russian (ы)", "Polish", "Romanian"], }, "\u0289": { # ʉ "height": "close", "backness": "central", "rounding": "rounded", "name": "close central rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "u\"", "languages": ["Swedish", "Norwegian", "some English dialects"], }, "\u026f": { # ɯ "height": "close", "backness": "back", "rounding": "unrounded", "name": "close back unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "u-", "languages": ["Turkish", "Japanese", "Korean"], }, "u": { "height": "close", "backness": "back", "rounding": "rounded", "name": "close back rounded vowel", "spanish": True, "spanish_example": "tú", "espeak_code": "u", "languages": ["English (boot)", "Spanish", "French", "German"], }, # === NEAR-CLOSE VOWELS === "\u026a": { # ɪ "height": "near-close", "backness": "front", "rounding": "unrounded", "name": "near-close front unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "I", "languages": ["English (bit)", "German"], }, "\u028f": { # ʏ "height": "near-close", "backness": "front", "rounding": "rounded", "name": "near-close front rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "Y", "languages": ["German (hübsch)", "Swedish"], }, "\u028a": { # ʊ "height": "near-close", "backness": "back", "rounding": "rounded", "name": "near-close back rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "U", "languages": ["English (book)", "German"], }, # === CLOSE-MID VOWELS === "e": { "height": "close-mid", "backness": "front", "rounding": "unrounded", "name": "close-mid front unrounded vowel", "spanish": True, "spanish_example": "mesa", "espeak_code": "e", "languages": ["Spanish", "French (été)", "German (Beet)", "Italian"], }, "\u00f8": { # ø "height": "close-mid", "backness": "front", "rounding": "rounded", "name": "close-mid front rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "Y\"", "languages": ["French (peu)", "German (schön)", "Danish", "Finnish"], }, "\u0258": { # ɘ "height": "close-mid", "backness": "central", "rounding": "unrounded", "name": "close-mid central unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Korean", "Paicî"], }, "\u0275": { # ɵ "height": "close-mid", "backness": "central", "rounding": "rounded", "name": "close-mid central rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Swedish", "Australian English"], }, "\u0264": { # ɤ "height": "close-mid", "backness": "back", "rounding": "unrounded", "name": "close-mid back unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "o-", "languages": ["Korean", "Vietnamese", "Thai"], }, "o": { "height": "close-mid", "backness": "back", "rounding": "rounded", "name": "close-mid back rounded vowel", "spanish": True, "spanish_example": "como", "espeak_code": "o", "languages": ["Spanish", "French (beau)", "German (Boot)", "Italian"], }, # === MID VOWEL === "\u0259": { # ə (schwa) "height": "mid", "backness": "central", "rounding": "unrounded", "name": "mid central vowel (schwa)", "spanish": False, "spanish_example": None, "espeak_code": "@", "languages": ["English (about)", "French (le)", "German (bitte)"], }, # === OPEN-MID VOWELS === "\u025b": { # ɛ "height": "open-mid", "backness": "front", "rounding": "unrounded", "name": "open-mid front unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "E", "languages": ["English (bed)", "French (fête)", "Italian"], }, "\u0153": { # œ "height": "open-mid", "backness": "front", "rounding": "rounded", "name": "open-mid front rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "W", "languages": ["French (peur)", "German (Hölle)"], }, "\u025c": { # ɜ "height": "open-mid", "backness": "central", "rounding": "unrounded", "name": "open-mid central unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "3", "languages": ["English (bird - British)"], }, "\u025e": { # ɞ "height": "open-mid", "backness": "central", "rounding": "rounded", "name": "open-mid central rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Irish", "some English dialects"], }, "\u028c": { # ʌ "height": "open-mid", "backness": "back", "rounding": "unrounded", "name": "open-mid back unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "V", "languages": ["English (but)", "Korean"], }, "\u0254": { # ɔ "height": "open-mid", "backness": "back", "rounding": "rounded", "name": "open-mid back rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "O", "languages": ["English (thought)", "French (mort)", "Italian"], }, # === NEAR-OPEN VOWELS === "\u00e6": { # æ "height": "near-open", "backness": "front", "rounding": "unrounded", "name": "near-open front unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "a#", "languages": ["English (cat)", "Danish", "Arabic"], }, "\u0250": { # ɐ "height": "near-open", "backness": "central", "rounding": "unrounded", "name": "near-open central vowel", "spanish": False, "spanish_example": None, "espeak_code": "a\"", "languages": ["German (bitter)", "Portuguese", "some English dialects"], }, # === OPEN VOWELS === "a": { "height": "open", "backness": "front", "rounding": "unrounded", "name": "open front unrounded vowel", "spanish": True, "spanish_example": "casa", "espeak_code": "a", "languages": ["Spanish", "French (patte)", "Italian", "German"], }, "\u0276": { # ɶ "height": "open", "backness": "front", "rounding": "rounded", "name": "open front rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": None, "languages": ["Danish", "some German dialects"], }, "\u0251": { # ɑ "height": "open", "backness": "back", "rounding": "unrounded", "name": "open back unrounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "A", "languages": ["English (father)", "French (pâte)", "Persian"], }, "\u0252": { # ɒ "height": "open", "backness": "back", "rounding": "rounded", "name": "open back rounded vowel", "spanish": False, "spanish_example": None, "espeak_code": "A.", "languages": ["British English (lot)", "Hungarian"], }, } # ============================================================================= # VOWEL TRAPEZOID COORDINATES (for SVG rendering) # ============================================================================= # SVG viewBox: 0 0 500 400 # The trapezoid is narrower at top (close) and wider at bottom (open) # x increases left-to-right (front → back), y increases top-to-bottom (close → open) VOWEL_TRAPEZOID_COORDS = { # (x, y) positions on the trapezoid SVG # Close row ("close", "front"): (80, 40), ("close", "central"): (250, 40), ("close", "back"): (420, 40), # Near-close row ("near-close", "front"): (110, 95), ("near-close", "back"): (400, 95), # Close-mid row ("close-mid", "front"): (130, 145), ("close-mid", "central"): (255, 145), ("close-mid", "back"): (380, 145), # Mid row ("mid", "central"): (260, 200), # Open-mid row ("open-mid", "front"): (170, 250), ("open-mid", "central"): (265, 250), ("open-mid", "back"): (360, 250), # Near-open row ("near-open", "front"): (195, 305), ("near-open", "central"): (270, 305), # Open row ("open", "front"): (215, 355), ("open", "back"): (340, 355), } # ============================================================================= # HELPER FUNCTIONS # ============================================================================= def get_consonant_at(place, manner, voicing): """Get the IPA symbol for a consonant at a specific position in the chart.""" for symbol, data in CONSONANTS.items(): if data["place"] == place and data["manner"] == manner and data["voicing"] == voicing: return symbol return None def get_vowel_at(height, backness, rounding): """Get the IPA symbol for a vowel at a specific position in the chart.""" for symbol, data in VOWELS.items(): if data["height"] == height and data["backness"] == backness and data["rounding"] == rounding: return symbol return None def get_spanish_consonants(): """Return all consonants that appear in Spanish.""" return {sym: data for sym, data in CONSONANTS.items() if data["spanish"]} def get_spanish_vowels(): """Return all vowels that appear in Spanish.""" return {sym: data for sym, data in VOWELS.items() if data["spanish"]} def get_all_spanish_phonemes(): """Return all Spanish phonemes (consonants + vowels).""" return {**get_spanish_consonants(), **get_spanish_vowels()} def get_phoneme_info(symbol): """Look up any IPA symbol and return its full data.""" if symbol in CONSONANTS: return {"type": "consonant", **CONSONANTS[symbol]} if symbol in VOWELS: return {"type": "vowel", **VOWELS[symbol]} return None