Source code for cltk.phonology.non.transcription

"""Old Norse transcription module. Sources:
- https://fr.wikipedia.org/wiki/%C3%89criture_du_vieux_norrois
- Altnordisches Elementarbuch by Friedrich Ranke and Dietrich Hofmann

"""

from typing import Union

from cltk.phonology.non.syllabifier import BACK_TO_FRONT_VOWELS
from cltk.phonology.non.utils import (
    AbstractConsonant,
    AbstractPosition,
    Backness,
    Consonant,
    Height,
    Length,
    Manner,
    Place,
    Rank,
    Rule,
    Vowel,
)

__author__ = ["Clément Besnier <clem@clementbesnier.fr>"]


[docs]class OldNorsePhonology(Vowel): """Class that applies position-dependent phonological transformation""" U_UMLAUT = {"a": "ö", "ö": "u"}
[docs] @staticmethod def phonetic_i_umlaut(sound: Vowel) -> Vowel: """ >>> umlaut_a = OldNorsePhonology.phonetic_i_umlaut(a) >>> umlaut_a.ipar 'ɛ' >>> umlaut_au = OldNorsePhonology.phonetic_i_umlaut(DIPHTHONGS_IPA_class["au"]) >>> umlaut_au.ipar 'ɐy' :param sound: vowel :return: transformed vowel """ if sound.is_equal(a): return ee elif sound.is_equal(a.lengthen()): return ee.lengthen() elif sound.is_equal(o): return oee elif sound.is_equal(o.lengthen()): return oee.lengthen() elif sound.is_equal(u): return y elif sound.is_equal(u.lengthen()): return y.lengthen() if sound.is_equal(DIPHTHONGS_IPA_class["au"]): return DIPHTHONGS_IPA_class["ey"]
[docs] @staticmethod def orthographic_i_umlaut(sound: str) -> str: """ >>> OldNorsePhonology.orthographic_i_umlaut("a") 'e' >>> OldNorsePhonology.orthographic_i_umlaut("ý") 'ý' :param sound: vowel :return: transformed vowel """ if sound in BACK_TO_FRONT_VOWELS: return BACK_TO_FRONT_VOWELS[sound] else: return sound
[docs] @staticmethod def phonetic_u_umlaut(sound: Vowel) -> Vowel: """ >>> umlaut_a = OldNorsePhonology.phonetic_u_umlaut(a) >>> umlaut_a.ipar 'ø' >>> umlaut_o = OldNorsePhonology.phonetic_u_umlaut(o) >>> umlaut_o.ipar 'u' >>> umlaut_e = OldNorsePhonology.phonetic_u_umlaut(e) >>> umlaut_e.ipar 'e' :param sound: vowel :return: transformed vowel """ if sound.is_equal(a): return oee # or oe elif sound.is_equal(o): return u else: return sound
[docs] @staticmethod def orthographic_u_umlaut(sound: str) -> str: """ >>> OldNorsePhonology.orthographic_u_umlaut("a") 'ö' >>> OldNorsePhonology.orthographic_u_umlaut("e") 'e' :param sound: a vowel :return: transformed vowel """ if sound in OldNorsePhonology.U_UMLAUT: return OldNorsePhonology.U_UMLAUT[sound] else: return sound
a = Vowel(Height.open, Backness.front, False, Length.short, "a") ee = Vowel(Height.open_mid, Backness.front, False, Length.short, "ɛ") e = Vowel(Height.close_mid, Backness.front, False, Length.short, "e") oee = Vowel(Height.close_mid, Backness.front, True, Length.short, "ø") oe = Vowel(Height.open_mid, Backness.front, True, Length.short, "œ") i = Vowel(Height.close, Backness.front, False, Length.short, "i") y = Vowel(Height.close, Backness.front, True, Length.short, "y") ao = Vowel(Height.open, Backness.back, True, Length.short, "ɒ") oo = Vowel(Height.open_mid, Backness.back, True, Length.short, "ɔ") o = Vowel(Height.close_mid, Backness.back, True, Length.short, "o") u = Vowel(Height.close, Backness.back, True, Length.short, "u") b = Consonant(Place.bilabial, Manner.stop, True, "b", False) d = Consonant(Place.alveolar, Manner.stop, True, "d", False) f = Consonant(Place.labio_dental, Manner.fricative, False, "f", False) g = Consonant(Place.velar, Manner.stop, True, "g", False) gh = Consonant(Place.velar, Manner.fricative, True, "ɣ", False) h = Consonant(Place.glottal, Manner.fricative, False, "h", False) j = Consonant(Place.palatal, Manner.fricative, True, "j", False) k = Consonant(Place.velar, Manner.stop, False, "k", False) l = Consonant(Place.alveolar, Manner.lateral, True, "l", False) m = Consonant(Place.bilabial, Manner.nasal, True, "m", False) n = Consonant(Place.labio_dental, Manner.nasal, True, "n", False) p = Consonant(Place.bilabial, Manner.stop, False, "p", False) r = Consonant(Place.alveolar, Manner.trill, True, "r", False) s = Consonant(Place.alveolar, Manner.fricative, False, "s", False) t = Consonant(Place.alveolar, Manner.stop, False, "t", False) v = Consonant(Place.labio_dental, Manner.fricative, True, "v", False) # θ = Consonant(Place.dental, Manner.frictative, False, "θ") th = Consonant(Place.dental, Manner.fricative, False, "θ", False) # ð = Consonant(Place.dental, Manner.frictative, True, "ð") dh = Consonant(Place.dental, Manner.fricative, True, "ð", False) OLD_NORSE_PHONOLOGY = [ a, ee, e, oe, i, y, ao, oo, u, a.lengthen(), e.lengthen(), i.lengthen(), o.lengthen(), u.lengthen(), y.lengthen(), b, d, f, g, h, k, l, m, n, p, r, s, t, v, th, dh, ] # IPA Dictionary DIPHTHONGS_IPA = {"ey": "ɐy", "au": "ɒu", "øy": "ɐy", "ei": "ei"} # Diphthongs # Wrong diphthongs implementation but not that bad for now DIPHTHONGS_IPA_class = { "ey": Vowel(Height.open, Backness.front, True, Length.long, "ɐy"), "au": Vowel(Height.open, Backness.back, True, Length.long, "ɒu"), "øy": Vowel(Height.open, Backness.front, True, Length.long, "ɐy"), "ei": Vowel(Height.open, Backness.front, True, Length.long, "ɛi"), } IPA = { "a": "a", # Short vowels "e": "ɛ", "i": "i", "o": "ɔ", "ǫ": "ɒ", "ö": "ø", "ø": "ø", "u": "u", "y": "y", "á": "aː", # Long vowels "æ": "ɛː", "œ": "œ:", "é": "eː", "í": "iː", "ó": "oː", "ú": "uː", "ý": "y:", # Consonants "b": "b", "d": "d", "f": "f", "g": "g", "h": "h", "j": "j", "k": "k", "l": "l", "m": "m", "n": "n", "p": "p", "r": "r", "s": "s", "t": "t", "v": "v", "x": "ks", "z": "ts", "þ": "θ", "ð": "ð", } IPA_class = { "a": a, # Short vowels "e": ee, "i": i, "o": oo, "ǫ": ao, "ø": oee, "u": u, "y": y, "á": a.lengthen(), # Long vowels "æ": ee.lengthen(), "ö": oe, "œ": oe.lengthen(), "é": e.lengthen(), "í": i.lengthen(), "ó": o.lengthen(), "ú": u.lengthen(), "ý": y.lengthen(), # Consonants "b": b, "d": d, "f": f, "g": g, "h": h, "j": j, "k": k, "l": l, "m": m, "n": n, "p": p, "r": r, "s": s, "t": t, "v": v, "x": k + s, "z": t + s, "þ": th, "ð": dh, } GEMINATE_CONSONANTS = { "bb": "bː", "dd": "dː", "ff": "fː", "gg": "gː", "kk": "kː", "ll": "lː", "mm": "mː", "nn": "nː", "pp": "pː", "rr": "rː", "ss": "sː", "tt": "tː", "vv": "vː", } # Some Old Norse rules # The first rule which matches is retained rule_th = [ Rule(AbstractPosition(Rank.first, None, []), th, th), Rule(AbstractPosition(Rank.inner, [], [AbstractConsonant(voiced=True)]), th, th), Rule(AbstractPosition(Rank.inner, [AbstractConsonant(voiced=True)], []), th, th), Rule(AbstractPosition(Rank.inner, [], []), th, dh), Rule(AbstractPosition(Rank.last, [], None), th, dh), ] rule_f = [ Rule(AbstractPosition(Rank.first, None, []), f, f), Rule(AbstractPosition(Rank.inner, [], [AbstractConsonant(voiced=False)]), f, f), Rule(AbstractPosition(Rank.inner, [AbstractConsonant(voiced=False)], []), f, f), Rule(AbstractPosition(Rank.inner, [], []), f, v), Rule(AbstractPosition(Rank.last, [], None), f, v), ] rule_g = [ Rule(AbstractPosition(Rank.first, None, None), g, g), Rule(AbstractPosition(Rank.inner, [n.to_abstract()], None), g, g), Rule(AbstractPosition(Rank.inner, None, [AbstractConsonant(voiced=False)]), g, k), Rule(AbstractPosition(Rank.inner, [], []), g, gh), Rule(AbstractPosition(Rank.last, [], None), g, gh), ] old_norse_rules = [] old_norse_rules.extend(rule_f) old_norse_rules.extend(rule_g) old_norse_rules.extend(rule_th)
[docs]def measure_old_norse_syllable(syllable: list) -> Union[Length, None]: """ Old Norse syllables are considered as: - short if - long if - overlong if >>> measure_old_norse_syllable([m, a.lengthen(), l]).name 'long' >>> measure_old_norse_syllable([a, l]).name 'short' >>> measure_old_norse_syllable([s, t, ee, r, k, r]).name 'long' >>> measure_old_norse_syllable([m, o.lengthen()]).name 'long' :param syllable: list of Vowel and Consonant instances :return: instance of Length (short, long or overlong) """ index = 0 while index < len(syllable) and not isinstance(syllable[index], Vowel): index += 1 if index == len(syllable): return None else: long_vowel_number = 0 short_vowel_number = 0 geminated_consonant_number = 0 simple_consonant_number = 0 for c in syllable[index:]: if isinstance(c, Vowel): if c.length == Length.long: long_vowel_number += 1 elif c.length == Length.short: short_vowel_number += 1 elif isinstance(c, Consonant): if c.geminate: geminated_consonant_number += 1 else: simple_consonant_number += 1 if ( long_vowel_number == 0 and short_vowel_number == 1 and simple_consonant_number <= 1 and geminated_consonant_number == 0 ): return Length.short elif ( ( short_vowel_number == 1 and (simple_consonant_number > 1 or geminated_consonant_number > 0) ) or long_vowel_number > 0 and simple_consonant_number <= 1 and geminated_consonant_number == 0 ): return Length.long elif long_vowel_number > 0 and ( simple_consonant_number > 1 or geminated_consonant_number > 0 ): return Length.overlong
[docs]def normalize_for_syllabifier(text: str) -> str: """ >>> normalize_for_syllabifier("almaːtːiɣr") 'almatiɣr' :param text: text to normalize for syllabification :return: normalized text for syllabification """ text = text.replace("ː", "") return text