pip install ipaparser
from ipaparser import IPA
print([str(symbol) for symbol in IPA('[ˈpʰɹɛʔt͡sɫ̩]') if 'consonant' in symbol.features()])['pʰ', 'ɹ', 'ʔ', 't͡s', 'ɫ̩']The IPA class can be used to parse IPA transcriptions. It behaves as a wrapper around a list of symbols:
from ipaparser import IPA
print([
len(IPA('[aɪ pʰiː eɪ]')),
# 8
list(IPA('[aɪ pʰiː eɪ]')),
# [IPASymbol('a'),
# IPASymbol('ɪ'),
# IPASymbol(' '),
# IPASymbol('pʰ'),
# IPASymbol('iː'),
# IPASymbol(' '),
# IPASymbol('e'),
# IPASymbol('ɪ')]
IPA('[aɪ pʰiː eɪ]')[0],
# IPASymbol('a')
IPA('[aɪ pʰiː eɪ]')[-1],
# IPASymbol('ɪ')
IPA('[aɪ pʰiː eɪ]')[3:5],
# IPA('[pʰiː]')
])You can control some aspects of how parsing is performed by additionally passing a configuration:
from ipaparser import IPA, IPAConfig
print([
list(IPA('[aɪ pʰiː eɪ]', IPAConfig(combined=[('a', 'ɪ'), ('e', 'ɪ')]))),
# [IPASymbol('a͡ɪ'),
# IPASymbol(' '),
# IPASymbol('pʰ'),
# IPASymbol('iː'),
# IPASymbol(' '),
# IPASymbol('e͡ɪ')]
])Objects of the IPA class provide basic information about their transcription type:
from ipaparser import IPA
from ipaparser.definitions import TranscriptionType
print([
IPA('[aɪ pʰiː eɪ]').type,
# <TranscriptionType.PHONETIC: 'phonetic'>
IPA('/ˌaɪ.piːˈeɪ/').type == TranscriptionType.PHONEMIC,
# True
IPA('[aɪ pʰiː eɪ]').left_bracket,
# '['
IPA('[aɪ pʰiː eɪ]').right_bracket,
# ']'
])IPA objects can be compared with other IPA objects as well as with strings:
from ipaparser import IPA
print([
IPA('[aɪ pʰiː eɪ]') == IPA('[aɪ pʰiː eɪ]'),
# True
IPA('[aɪ pʰiː eɪ]') == '[aɪ pʰiː eɪ]',
# True
IPA(transcription := '[ú]') == transcription,
# False: `IPA` performs unicode normalizations on strings
IPA('[aɪ pʰiː eɪ]') == IPA('[eɪ pʰiː aɪ]'),
# False
IPA('[aɪ pʰiː eɪ]') == IPA('/aɪ pʰiː eɪ/'),
# False
IPA('[aɪ pʰiː eɪ]').as_string(),
# '[aɪ pʰiː eɪ]'
str(IPA('[aɪ pʰiː eɪ]')),
# '[aɪ pʰiː eɪ]'
])You can concatenate multiple IPA objects as well as append or prepend symbols to them:
from ipaparser import IPA, IPASymbol
print([
IPA('[aɪ pʰiː]') + IPASymbol(' ') + IPA('[eɪ]'),
# IPA('[aɪ pʰiː eɪ]')
IPA('[aɪ]') * 3,
# IPA('[aɪaɪaɪ]')
])IPASymbol represents an individual unit of IPA transcriptions: either a sound (like a, t͡s, or ᶢǁʱ), a break (like . or a space), a suprasegmental letter (stress mark, tone number, etc.), or an unknown grapheme.
from ipaparser import IPA, IPASymbol
print([
IPA('[aɪ pʰiː]')[0].is_sound(),
# True
IPA('[aɪ pʰiː]')[2].is_sound(),
# False
IPA('[aɪ pʰiː]')[2].is_break(),
# True
IPASymbol('˦').is_suprasegmental(),
# True
IPASymbol('˦').is_known(),
# True
IPASymbol('*').is_known(),
# False
])Just as with the IPA constructor, you can additionally pass to IPASymbol a configuration:
from ipaparser import IPAConfig, IPASymbol
print([
IPASymbol('g:').is_known(),
# False
IPASymbol('g:', IPAConfig(substitutions=True)),
# IPASymbol('ɡː')
IPASymbol('g:', IPAConfig(substitutions=True)).is_known(),
# True
])Symbols can be queried for their features:
from ipaparser import IPASymbol
from ipaparser.features import Aspiration, Backness, Height, Manner, SoundType
print([
IPASymbol('pʰ').features(),
# frozenset({<Aspiration.ASPIRATED: 'aspirated'>,
# <Place.BILABIAL: 'bilabial'>,
# <SoundType.CONSONANT: 'consonant'>,
# <PlaceCategory.LABIAL: 'labial'>,
# <SoundSubtype.SIMPLE_CONSONANT: 'simple consonant'>,
# <SymbolType.SOUND: 'sound'>,
# <Manner.STOP: 'stop'>})
IPASymbol('a').features({Backness, Height}),
# frozenset({<Backness.FRONT: 'front'>,
# <Height.OPEN: 'open'>})
IPASymbol('s').features(Manner),
# frozenset({<Manner.FRICATIVE: 'fricative'>,
# <Manner.SIBILANT: 'sibilant'>})
IPASymbol('b').features('voicing'), # shortcut to `ipaparser.features.Voicing`
# frozenset({<Voicing.VOICED: 'voiced'>})
IPASymbol(' ').features(),
# frozenset({<SymbolType.BREAK: 'break'>,
# <BreakType.SPACE: 'space'>})
IPASymbol('*').features(),
# None
IPASymbol('pʰ').has_feature(Aspiration.ASPIRATED),
# True
IPASymbol('a').has_feature('vowel'), # shortcut to `ipaparser.features.SoundType.VOWEL`
# True
IPASymbol('b').has_feature(SoundType.VOWEL),
# False
IPASymbol('*').has_feature(SoundType.VOWEL),
# False
])Some sounds may be requested for alternative interpretations:
- Nonsyllabic front/back close vowels (
i̯,y̑,ɯ̯,u̯) can be reinterpreted as palatal/velar approximants (j,ɥ,ɰ,w). - “Ambiguous” as to the exact place of articulation consonants such as
t,n,ǁ, etc., which are treated as alveolar by default, can be reinterpreted as dental or as postalveolar. - Ad-hoc grapheme combinations used in the IPA (e.g.,
äfor the open central unrounded vowel) can be alternatively treated literally (so thatäbecomes a centralized open front unrounded vowel).
from ipaparser import IPASymbol
from ipaparser.features import Place, SoundType
print([
IPASymbol('i̯').features(SoundType),
# frozenset({<SoundType.VOWEL: 'vowel'>})
IPASymbol('i̯').features(role=SoundType.CONSONANT),
# frozenset({<Manner.APPROXIMANT: 'approximant'>,
# <SoundType.CONSONANT: 'consonant'>,
# <PlaceCategory.DORSAL: 'dorsal'>,
# <Place.PALATAL: 'palatal'>,
# <SoundSubtype.SIMPLE_CONSONANT: 'simple consonant'>,
# <SymbolType.SOUND: 'sound'>,
# <Voicing.VOICED: 'voiced'>})
IPASymbol('i̯').features(role='consonant') == IPASymbol('j').features(),
# True
IPASymbol('t').features(Place),
# frozenset({<Place.ALVEOLAR: 'alveolar'>})
IPASymbol('t').features(Place, role=Place.POSTALVEOLAR),
# frozenset({<Place.POSTALVEOLAR: 'postalveolar'>})
IPASymbol('t').features(Place, role=Place.DENTAL),
# frozenset({<Place.DENTAL: 'dental'>})
IPASymbol('t').features(Place, role=Place.BILABIAL),
# None
IPASymbol('ɹ̠̊˔').features(),
# frozenset({<SoundType.CONSONANT: 'consonant'>,
# <PlaceCategory.CORONAL: 'coronal'>,
# <Manner.FRICATIVE: 'fricative'>,
# <Place.POSTALVEOLAR: 'postalveolar'>,
# <SoundSubtype.SIMPLE_CONSONANT: 'simple consonant'>,
# <SymbolType.SOUND: 'sound'>})
IPASymbol('ɹ̠̊˔').features(role=Place.ALVEOLAR),
# frozenset({<Place.ALVEOLAR: 'alveolar'>,
# <Manner.APPROXIMANT: 'approximant'>,
# <SoundType.CONSONANT: 'consonant'>,
# <PlaceCategory.CORONAL: 'coronal'>,
# <Articulation.RAISED: 'raised'>,
# <Articulation.RETRACTED: 'retracted'>,
# <SoundSubtype.SIMPLE_CONSONANT: 'simple consonant'>,
# <SymbolType.SOUND: 'sound'>})
])Symbols preserve information about their constituents:
from ipaparser import IPASymbol
from ipaparser.features import Manner
print([
IPASymbol('ts').features(Manner),
# frozenset({<Manner.AFFRICATE: 'affricate'>,
# <Manner.SIBILANT: 'sibilant'>})
IPASymbol('ts').components,
# (IPASymbol('t'), IPASymbol('s'))
IPASymbol('ts').left,
# IPASymbol('t')
IPASymbol('ts').left.features(Manner),
# frozenset({<Manner.STOP: 'stop'>})
IPASymbol('ts').right.features(Manner),
# frozenset({<Manner.FRICATIVE: 'fricative'>,
# <Manner.SIBILANT: 'sibilant'>})
IPASymbol('t͡s').components == IPASymbol('ts').components,
# True
IPASymbol('t').components,
# None
IPASymbol('d͢').is_known(),
# False
IPASymbol('d͢').components,
# (IPASymbol('d'),)
IPASymbol('d͢').components[0].is_known(),
# True
])IPASymbol objects can be compared with other symbols as well as with strings:
from ipaparser import IPASymbol
print([
IPASymbol('ts') == IPASymbol('ts'),
# True
IPASymbol('ts') == 'ts',
# True
IPASymbol(symbol := 'ú') == symbol,
# False: `IPASymbol` performs unicode normalizations on strings
IPASymbol('ts').features() == IPASymbol('t͡s').features(),
# True
IPASymbol('ts') == IPASymbol('t͡s'),
# False: underlying strings are compared, not features
IPASymbol('ts').as_string(),
# 'ts'
str(IPASymbol('ts')),
# 'ts'
])IPAConfig can be used to control some aspects of how transcriptions and individual symbols are parsed. The following parameters are available for configuration:
| Parameter | Type(s) | Default | Description |
|---|---|---|---|
substitutions |
bool |
False |
Whether to perform normalizing substitutions that allow to properly handle commonly observed simplifications in IPA notation such as the Latin letter g being used instead of the IPA’s dedicated character ɡ or a colon in place of the length mark ː. |
brackets |
BracketStrategystr |
BracketStrategy.KEEP'keep' |
What to do with content in brackets denoting optional pronunciation, such as in [bə(j)ɪz⁽ʲ⁾ˈlʲivɨj]:
|
combined |
Iterable[tuple[str, ...]] |
() |
Sound sequences to be treated as though they were connected by a tie, e.g., [('t', 's'), ('d̠', 'ɹ̠˔'), ('a', 'ɪ'), ('u̯', 'e', 'i̯')].Note that, say, ('a', 'ɪ') will not match 'aɪ̯', and likewise ('a', 'ɪ̯') will not match 'aɪ'. |
from ipaparser import IPA, IPAConfig, IPASymbol
from ipaparser.definitions import BracketStrategy
print([
IPA('/ɹɪˈdʒɔɪndʒə(ɹ)/', IPAConfig(brackets=BracketStrategy.STRIP, combined=[('d', 'ʒ'), ('ɔ', 'ɪ')])),
# IPA('/ɹɪˈd͡ʒɔ͡ɪnd͡ʒə/')
IPASymbol('o(:)', IPAConfig(substitutions=True, brackets='expand'))
# IPASymbol('oː')
])Call this function to eagerly load and preprocess supporting data so that the first parse is a little faster. Compare:
from timeit import timeit
from ipaparser import IPA
print([
timeit(lambda: IPA('[aɪ pʰiː eɪ]'), number=1),
# 0.007
timeit(lambda: IPA('[ˈpʰɹɛʔt͡sɫ̩]'), number=1),
# 0.0004
])from timeit import timeit
from ipaparser import IPA, load
load()
print([
timeit(lambda: IPA('[aɪ pʰiː eɪ]'), number=1),
# 0.0002
timeit(lambda: IPA('[ˈpʰɹɛʔt͡sɫ̩]'), number=1),
# 0.0004
])For usage, see IPAConfig.
| Value | String representation |
|---|---|
BracketStrategy.KEEP |
keep |
BracketStrategy.EXPAND |
expand |
BracketStrategy.STRIP |
strip |
For usage, see IPA transcription type.
| Value | String representation | Brackets |
|---|---|---|
TranscriptionType.PHONETIC |
phonetic |
[...] |
TranscriptionType.PHONEMIC |
phonemic |
/.../ |
TranscriptionType.LITERAL |
literal |
⟨...⟩ |
from ipaparser import IPA, IPAConfig, IPASymbol
from ipaparser.exceptions import (
BracketStrategyError,
CombinedLengthError,
CombinedSoundError,
EnclosingError,
FeatureError,
FeatureKindError,
IncompatibleTypesError,
)
try:
config = IPAConfig(brackets='custom')
except BracketStrategyError as e:
print(str(e)) # 'custom' is not a valid strategy; use one of the following: 'keep'/'expand'/'strip'
print(e.value) # 'custom'
try:
config = IPAConfig(combined=[('t', 's'), ('e',)])
except CombinedLengthError as e:
print(str(e)) # A sound sequence to be combined must contain at least 2 elements (got 1: 'e')
print(e.sequence) # ('e',)
try:
config = IPAConfig(combined=[('t', 's'), ('i', '̯ɐ')])
except CombinedSoundError as e:
print(str(e)) # A sound to be combined must start with a non-combining character (got ' ̯ɐ')
print(e.sound) # '̯ɐ'
try:
config = IPAConfig(combined=[('t', 's'), ('i', '')])
except CombinedSoundError as e:
print(str(e)) # A sound to be combined cannot be empty
print(e.sound) # ''
try:
ipa = IPA('aɪ pʰiː eɪ')
except EnclosingError as e:
print(str(e)) # 'aɪ pʰiː eɪ' is not properly delimited (like [so] or /so/)
print(e.transcription) # 'aɪ pʰiː eɪ'
try:
is_vowel = IPASymbol('a').has_feature('vocalic')
except FeatureError as e:
print(str(e)) # Invalid feature: 'vocalic'
print(e.value) # 'vocalic'
try:
features = IPASymbol('a').features('sonority')
except FeatureKindError as e:
print(str(e)) # Invalid feature kind: 'sonority'
print(e.value) # 'sonority'
try:
concatenated = IPA('[a]') + IPA('/b/')
except IncompatibleTypesError as e:
print(str(e)) # '[a]' and '/b/' have incompatible types and cannot be concatenated
print(e.left) # '[a]'
print(e.right) # '/b/'| Kind | Feature | Examples | Sources |
|---|---|---|---|
Airflow'airflow' |
EGRESSIVE_AIRFLOW'egressive airflow' |
↑ |
[1] |
INGRESSIVE_AIRFLOW'ingressive airflow' |
↓ |
||
Articulation'articulation' |
APICAL'apical' |
s̺, z̺, ɾ̺ |
[1] |
LAMINAL'laminal' |
s̻, z̻, n̻ |
||
ADVANCED'advanced' |
ɯ̟ᵝ, o̞˖, ʎ̟ |
||
RETRACTED'retracted' |
a̠, ð̩˕˗ˠˀ, i̠ |
||
CENTRALIZED'centralized' |
æ̈, ɑ̈ː, ö |
||
MID_CENTRALIZED'mid-centralized' |
e̽, ɯ̥̽, ɤ̽ |
||
RAISED'raised' |
ɛ̝, ʎ̥˔, e̝ˀ |
||
LOWERED'lowered' |
ʏ̞, ò˕, ɛ̞̃ |
||
Aspiration'aspiration' |
ASPIRATED'aspirated' |
tʰ, kʰː, ǀʰ |
[1], [2] |
UNASPIRATED'unaspirated' |
ʔ˭, p˭ |
||
PREASPIRATED'preaspirated' |
ʰt͡s, ʰkʰʲ, ʰp |
||
Backness'backness' |
FRONT'front' |
a, ɛ̀ː, ǽ |
[1] |
NEAR_FRONT'near-front' |
ɪ, ʏ˞, ɪˑ |
||
CENTRAL'central' |
ə, ʉ́, ɘ̯ |
||
NEAR_BACK'near-back' |
ʊ, ʊ́, ʊ̂ |
||
BACK'back' |
o, ü, ɯ̟̃ᵝ |
||
BacknessCategory'backness category' |
ABOUT_FRONT'about front' |
a, ɪ̙́, ʏ˞ |
|
ABOUT_CENTRAL'about central' |
ə, ʉ́, ɘ̯ |
||
ABOUT_BACK'about back' |
o, ʊ̥, ü |
||
BreakType'break type' |
SPACE'space' |
|
[1] |
HYPHEN'hyphen' |
- |
||
LINKING'linking' |
‿ |
||
SYLLABLE_BREAK'syllable break' |
. |
||
MINOR_BREAK'minor break' |
| |
||
MAJOR_BREAK'major break' |
‖ |
||
EQUIVALENCE'equivalence' |
~, ⁓ |
||
ELLIPSIS'ellipsis' |
… |
||
Height'height' |
CLOSE'close' |
i, ṳ̌ː, ʉ̀ |
[1] |
NEAR_CLOSE'near-close' |
ɪ, ʏ˞, ʊ̯ˑ |
||
CLOSE_MID'close-mid' |
e, ɤː, o̟ |
||
MID'mid' |
ə, ɚː, ɤ̞ |
||
OPEN_MID'open-mid' |
ɛ, ɔ̃ː, ɜ˞ |
||
NEAR_OPEN'near-open' |
ɐ, ǽ, ɐ̆ |
||
OPEN'open' |
a, ɒ̯̽ˀ, ɑ̃ː |
||
HeightCategory'height category' |
ABOUT_CLOSE'about close' |
i, ʏ˞, ʊ̯ˑ |
|
ABOUT_MID'about mid' |
ə, ɘ̯, ɜˑ |
||
ABOUT_OPEN'about open' |
a, æːˀ, ɑ̆ |
||
Intonation'intonation' |
GLOBAL_RISE'global rise' |
↗ |
[1] |
GLOBAL_FALL'global fall' |
↘ |
||
Length'length' |
EXTRA_SHORT'extra-short' |
n̆, ø̆, ŏ |
[1] |
HALF_LONG'half-long' |
äˑ, e̞ˑ, øˑ |
||
LONG'long' |
aː, l̺ː, ɞː |
||
EXTRA_LONG'extra-long' |
øːˑ, ɛːː, ɨˤːː |
||
Manner'manner' |
AFFRICATE'affricate' |
t͡s, d͡zː, q͡χʷ |
[1] |
APPROXIMANT'approximant' |
l, w̥ʰ, ɻ̊ |
||
FRICATIVE'fricative' |
s, ʂ͜ʲ, xʼ |
||
LATERAL'lateral' |
l, t͡ɬʼ, ŋ͜ǁ |
||
NASAL'nasal' |
n, mʷ, ɳ̩ |
||
SIBILANT'sibilant' |
s, ʑː, t͡ʃʲ |
||
STOP'stop' |
k, tʲʰː, qˤ |
||
TAP_FLAP'tap/flap' |
ɾ, ɽ̃, ɺ |
||
TRILL'trill' |
r, ʀ̟, ʙ |
||
CLICK'click' |
ǃ, ᵑǀʱ, ǁ |
||
EJECTIVE'ejective' |
tʼ, ɬˤʼ, kʼʷ |
||
IMPLOSIVE'implosive' |
ɓ, ʄ, ɗʲ |
||
Phonation'phonation' |
BREATHY'breathy' |
bʱ, ṳ̌, ᵑǀʱ |
[1], [2] |
CREAKY'creaky' |
æ̰ˀ, ɑ̰́ː, j̰ |
||
WHISPERY'whispery' |
ạ, ạ̀, x̣ |
||
Place'place' |
BILABIAL'bilabial' |
m, b̥ˀ, p͡f |
[1] |
LABIODENTAL'labiodental' |
f, ᶬv, ʋ̥ |
||
LINGUOLABIAL'linguolabial' |
n̼, θ̼ |
||
DENTAL'dental' |
t̪, ðˠ, ɡ̊ǀ |
||
ALVEOLAR'alveolar' |
n, t͜ɬ, lʱ |
||
POSTALVEOLAR'postalveolar' |
ʃ, d͡ʒʲ, t̠̚ |
||
RETROFLEX'retroflex' |
ʂ, ʈⁿ, ɽʷ |
||
PALATAL'palatal' |
j, ɟʱ, kǂʰ |
||
VELAR'velar' |
k, ɡ̞, xʼ |
||
UVULAR'uvular' |
ʁ, q͡χʷ, ʀ̥ |
||
PHARYNGEAL_EPIGLOTTAL'pharyngeal/epiglottal' |
ħ, ʕː, ħʷ |
||
GLOTTAL'glottal' |
ʔ, ɦʲ, hː |
||
PlaceCategory'place category' |
LABIAL'labial' |
m, ᶬv, b̥ˀ |
[1] |
CORONAL'coronal' |
n, t͡ʃʲ, ɻ̊ |
||
DORSAL'dorsal' |
k, q͡χʷ, ʎ̥˔ |
||
LARYNGEAL'laryngeal' |
ʔ, ʕː, h̃ |
||
Release'release' |
NO_AUDIBLE_RELEASE'no audible release' |
t̚, ʔ̚, d̪̚ |
[1] |
NASAL_RELEASE'nasal release' |
tⁿ, t̪ⁿ, ʈⁿ |
||
LATERAL_RELEASE'lateral release' |
tˡ, bˡ, ᵐbˡ |
||
VOICELESS_DENTAL_FRICATIVE_RELEASE'voiceless dental fricative release' |
tᶿ |
||
VOICELESS_ALVEOLAR_SIBILANT_FRICATIVE_RELEASE'voiceless alveolar sibilant fricative release' |
tˢ, kˢ, tˢʰ |
||
VOICELESS_VELAR_FRICATIVE_RELEASE'voiceless velar fricative release' |
kˣ |
||
Roundedness'roundedness' |
ROUNDED'rounded' |
o, ṳ̌ː, ʉ̀ |
[1] |
RoundednessModifier'roundedness modifier' |
MORE_ROUNDED'more rounded' |
ʌ̹, ə̹, ɔ̹ |
[1], [2] |
LESS_ROUNDED'less rounded' |
w̜, ɒ̜˔ː, ɔ̜ˑ |
||
COMPRESSED'compressed' |
ɯ̟ᵝ, ɨ̃ᵝ, ɰᵝ |
||
LABIAL_SPREADING'labial spreading' |
u͍, u͍ː, w͍ |
||
SecondaryModifier'secondary modifier' |
ADVANCED_TONGUE_ROOT'advanced tongue root' |
ɨ̘, ɤ̘, í̘ː |
[1], [2], [3], [4], [5] |
RETRACTED_TONGUE_ROOT'retracted tongue root' |
ɪ̙̞, ɒ̙̀, ʊ̙́ |
||
R_COLORED'r-colored' |
ɚ, ɝˑ, ɑ˞ |
||
NASALIZED'nasalized' |
ĩ, õ̤, ɯ̟̃ᵝ |
||
PRENASALIZED'prenasalized' |
ⁿdˠ, n͡t, ᶬv |
||
VOICELESSLY_PRENASALIZED'voicelessly prenasalized' |
m̥͡bʷ |
||
PRESTOPPED'prestopped' |
ᵈn, ᵇm, ᵈl |
||
PREGLOTTALIZED'preglottalized' |
ˀt, ˀd |
||
SecondaryPlace'secondary place' |
LABIALIZED'labialized' |
w, sʷː, ʍ |
[1] |
PALATALIZED'palatalized' |
tʲ, ʃᶣ, k̚ʲ |
||
VELARIZED'velarized' |
ɫ, l̩ˠ, mˠ |
||
PHARYNGEALIZED'pharyngealized' |
t̪ˤ, bˤ, ɑˤː |
||
GLOTTALIZED'glottalized' |
æ̰ˀ, ɔˀ, yˀ |
||
SoundSubtype'sound subtype' |
SIMPLE_CONSONANT'simple consonant' |
n, ʑː, t͡ʃʲ |
[1], [2], [3], [4], [5] |
DOUBLY_ARTICULATED_CONSONANT'doubly articulated consonant' |
ŋ͡m, k͡p̚, ɡ͡b |
||
CONTOUR_CLICK'contour click' |
ᵏǃ͡χʼ, ǃ͡qʰ |
||
SIMPLE_VOWEL'simple vowel' |
a, ə̹, ɯ̟̃ᵝ |
||
DIPHTHONG'diphthong' |
ʉ͜i, u͡ɛ, e͡ɪ |
||
TRIPHTHONG'triphthong' |
œ̞͡ɐ̯͡u̯ |
||
SoundType'sound type' |
CONSONANT'consonant' |
n, k͡p̚, ᵏǃ͡χʼ |
|
VOWEL'vowel' |
a, ɔ͜y, ø̯ |
||
Strength'strength' |
STRONG'strong' |
t͡s͈, n͈, l͈ |
[1] |
WEAK'weak' |
v͉ |
||
StressSubtype'stress subtype' |
REGULAR_PRIMARY_STRESS'regular primary stress' |
ˈ |
[1], [2] |
EXTRA_STRONG_PRIMARY_STRESS'extra-strong primary stress' |
ˈˈ |
||
REGULAR_SECONDARY_STRESS'regular secondary stress' |
ˌ |
||
EXTRA_WEAK_SECONDARY_STRESS'extra-weak secondary stress' |
ˌˌ |
||
StressType'stress type' |
PRIMARY_STRESS'primary stress' |
ˈ, ˈˈ |
[1], [2] |
SECONDARY_STRESS'secondary stress' |
ˌ, ˌˌ |
||
SuprasegmentalType'suprasegmental type' |
STRESS'stress' |
ˈ, ˌ, ˈˈ |
[1], [2] |
TONE'tone' |
˥, ⁴, ¹ |
||
INTONATION'intonation' |
↘, ↗ |
||
AIRFLOW'airflow' |
↓, ↑ |
||
Syllabicity'syllabicity' |
SYLLABIC'syllabic' |
n̩, ŋ̍, r̩̂ |
[1], [2] |
NONSYLLABIC'nonsyllabic' |
i̯, ʏ̯ː, ɪ̯ˑ |
||
ANAPTYCTIC'anaptyctic' |
ᵊ |
||
SymbolType'symbol type' |
SOUND'sound' |
a, ɡʲʷ, ʰk |
|
BREAK'break' |
., -, ‿ |
||
SUPRASEGMENTAL'suprasegmental' |
ˈ, ꜜ, ⁻ |
||
Tone'tone' |
EXTRA_HIGH_TONE'extra-high tone' |
ɹ̩̋, ő, a̋ |
[1], [2] |
HIGH_TONE'high tone' |
í, ɑ̃́, ɯ́ᵝː |
||
MID_TONE'mid tone' |
ā, ɵ̄, īː |
||
LOW_TONE'low tone' |
à, ù̘, æ̀ː |
||
EXTRA_LOW_TONE'extra-low tone' |
ɨ̏ː, ȁ |
||
RISING_TONE'rising tone' |
ǎ, ěː, m̩̌ |
||
FALLING_TONE'falling tone' |
êː, û, ɔ̂ |
||
HIGH_MID_RISING_TONE'high/mid rising tone' |
a᷄ː, a᷄, u᷄ |
||
LOW_RISING_TONE'low rising tone' |
i᷅ː, a᷅ː, ɛ᷅ |
||
HIGH_FALLING_TONE'high falling tone' |
a᷇, u᷇ː, u᷇ |
||
LOW_MID_FALLING_TONE'low/mid falling tone' |
ɪ᷆, e᷆ː, ə᷆ |
||
PEAKING_TONE'peaking tone' |
a̤᷈ː, e̤᷈ː, ṳ᷈ː |
||
DIPPING_TONE'dipping tone' |
a᷉ |
||
ToneLetter'tone letter' |
HIGH_TONE_LETTER'high tone letter' |
˥ |
[1] |
HALF_HIGH_TONE_LETTER'half-high tone letter' |
˦, ˦ˀ |
||
MID_TONE_LETTER'mid tone letter' |
˧, ꜔, ˧ˀ |
||
HALF_LOW_TONE_LETTER'half-low tone letter' |
˨, ˨ˀ |
||
LOW_TONE_LETTER'low tone letter' |
˩, ˩̰ˀ, ˩̤ |
||
ToneNumber'tone number' |
TONE_0'tone 0' |
⁰ |
[1], [2] |
TONE_1'tone 1' |
¹ |
||
TONE_2'tone 2' |
² |
||
TONE_3'tone 3' |
³ |
||
TONE_4'tone 4' |
⁴ |
||
TONE_5'tone 5' |
⁵ |
||
TONE_6'tone 6' |
⁶ |
||
TONE_7'tone 7' |
⁷ |
||
TONE_NUMBER_SEPARATOR'tone number separator' |
⁻ |
||
ToneStep'tone step' |
UPSTEP'upstep' |
ꜛ |
[1] |
DOWNSTEP'downstep' |
ꜜ |
||
ToneType'tone type' |
TONE_LETTER'tone letter' |
˥, ˦, ˨ |
[1], [2], [3] |
TONE_NUMBER'tone number' |
⁵, ¹, ² |
||
TONE_STEP'tone step' |
ꜜ, ꜛ |
||
Voicing'voicing' |
VOICED'voiced' |
n, bˤ, ɡʰ |
[1], [2] |
DEVOICED'devoiced' |
u̥, ɯ̟̊, ĭ̥ |
You can iterate through the supported features using the tuple FEATURE_KINDS. Feature kinds (such as Height, Manner, or Voicing) are all string-based enums subclassed off of the base class Feature. Feature kinds themselves have the type Type[Feature], aliased FeatureKind. The .kind_values() method can be called to retrieve supported string representations of the feature kind.
from ipaparser.features import Feature, FEATURE_KINDS, FeatureKind
kind: FeatureKind
for kind in FEATURE_KINDS:
print(kind)
# <enum 'Airflow'>, <enum 'Articulation'>, ..., <enum 'ToneType'>, <enum 'Voicing'>
print(kind.kind_values())
# ('Airflow', 'airflow'), ('Articulation', 'articulation'), ..., ('ToneType', 'tone type'), ('Voicing', 'voicing')
feature: Feature
for feature in kind:
print(feature)
# Airflow.EGRESSIVE_AIRFLOW, Airflow.INGRESSIVE_AIRFLOW, Articulation.APICAL, ..., Voicing.DEVOICED
print(feature.value)
# 'egressive airflow', 'ingressive airflow', 'apical', ..., 'devoiced'FeatureSet (which can be imported from ipaparser.features) is an alias for frozenset[Feature]. The return type of IPASymbol.features() is hence Optional[FeatureSet].
Finally, the .derived() and .extend() methods of individual features may be called to obtain basic hierarchical relationships between features:
from ipaparser.features import Place, ToneLetter
print(Place.ALVEOLAR.derived()) # get the most specific derived feature
# PlaceCategory.CORONAL
print(ToneLetter.HIGH_TONE_LETTER.extend()) # all the derived features, including the caller
# frozenset({<ToneLetter.HIGH_TONE_LETTER: 'high tone letter'>,
# <ToneType.TONE_LETTER: 'tone letter'>,
# <SuprasegmentalType.TONE: 'tone'>,
# <SymbolType.SUPRASEGMENTAL: 'suprasegmental'>})