local m_uk_translit = require("Module:uk-translit")
local export = {}
function export.pronunciation(word, accent)
if type(word) == "table" then
word, accent =
word.args or word:getParent().args,
word.args.accent or word:getParent().args.accent
end
if not word or (word == "") then
error("Please put the word as the first postional parameter!")
end
word = mw.ustring.lower(word)
-- single characters that map to IPA sounds
local phonetic_chars_map= {
= "ɑ", = "b", = "ʋ", = "ɦ", = "ɡ",
= "d", = "ɛ", = "jɛ", = "ʒ", = "z",
= "ɪ", = "i", = "ji", = "j", = "k",
= "l", = "m", = "n", = "ɔ", = "p",
= "r", = "s", = "t", = "u", = "f",
= "x", = "t͡s", = "t͡ʃ", = "ʃ", = "ʃt͡ʃ",
= "ʲ", = "ju", = "jɑ", = "j",
-- accented vowels
= "ˈ"
}
-- character sequences of two that map to IPA sounds
local phonetic_2chars_map = {
= "d͡ʒ", = "d͡z",
-- Dental plosives assimilate to following hissing/hushing consonants, which is not noted in the spelling.
= "d͡zs", = "d͡ʒʃ", = "d͡ʒt͡ʃ", = "d͡zt͡s",
= "t͡s", = "t͡ʃʃ", = "t͡ʃː", = "t͡sː",
}
-- character sequences of three that map to IPA sounds
local phonetic_3chars_map = {
= "d͡zʲ",
-- Dental plosives assimilate to following hissing/hushing consonants, which is not noted in the spelling.
= "t͡sʲː"
}
local phonetic = word
-- first apply consonant cluster simplifications that always occur orthographically
phonetic = mw.ustring.gsub(phonetic, "ntsʹk", "nʹsʹk")
phonetic = mw.ustring.gsub(phonetic, "stsʹk", "sʹk")
phonetic = mw.ustring.gsub(phonetic, "ntst", "nst")
phonetic = mw.ustring.gsub(phonetic, "stč", "šč")
phonetic = mw.ustring.gsub(phonetic, "std", "zd")
phonetic = mw.ustring.gsub(phonetic, "sts", "sː")
phonetic = mw.ustring.gsub(phonetic, "stsʹk", "sʹk")
phonetic = mw.ustring.gsub(phonetic, "^zš", "šː")
phonetic = mw.ustring.gsub(phonetic, "zš", "žš")
phonetic = mw.ustring.gsub(phonetic, "^zč", "šč")
phonetic = mw.ustring.gsub(phonetic, "zč", "žč")
-- then long consonants that are orthographically geminated.
phonetic = mw.ustring.gsub(phonetic, "()%1", "%1ː")
phonetic = mw.ustring.gsub(phonetic, "(+)žž", "%1žː") -- джж sequence encode diphonemic дж
phonetic = mw.ustring.gsub(phonetic, "(+)zz", "%1zː") -- дзз sequence encode diphonemic дз
phonetic = mw.ustring.gsub(phonetic, "()%1", "%1ː")
phonetic = mw.ustring.gsub(phonetic, "dždž", "džː")
phonetic = mw.ustring.gsub(phonetic, "dzdz", "dzː")
-- remap apostrophe to '!' so that it doesn't conflict with IPA stress mark
phonetic = mw.ustring.gsub(phonetic, "'", "!")
-- replace multiple letter sequences
for key, replacement in pairs(phonetic_3chars_map) do
phonetic = mw.ustring.gsub(phonetic, key, replacement)
end
for key, replacement in pairs(phonetic_2chars_map) do
phonetic = mw.ustring.gsub(phonetic, key, replacement)
end
-- replace single letters of the alphabet
phonetic = mw.ustring.gsub(phonetic, '.', phonetic_chars_map)
-- add IPA stress mark and remove the acute
phonetic = mw.ustring.gsub(phonetic, "()","ˈ%1")
phonetic = mw.ustring.gsub(phonetic, "()","")
-- add accent if the word is monosyllabic and not "|accent=off"
local _, numberOfVowels = mw.ustring.gsub(phonetic, "", "")
if (numberOfVowels == 1) and (accent ~= "off") then
phonetic = mw.ustring.gsub(phonetic, "()", "ˈ%1")
end
-- palatalizable consonants before /i/ or /j/ become palatalized
phonetic = mw.ustring.gsub(phonetic, "()(?)(?)i", "%1ʲ%2%3i")
phonetic = mw.ustring.gsub(phonetic, "()(?)j", "%1ʲ%2")
-- eliminate garbage sequences of resulting from -тьс- cluster followed by
phonetic = mw.ustring.gsub(phonetic, "ʲːj", "ʲː")
-- consonant simplification: ст + ц' → . We do it here because of palatalization.
-- Due to the т +ц → rule length is present. According to Орфоепскі словник p. 13,
-- both forms are proper, without length in normal (colloquial) speech and with length
-- in slow speech, so we parenthesize the length as optional.
phonetic = mw.ustring.gsub(phonetic, "st͡sʲ(?)", "sʲt͡sʲ(%1)")
-- assimilation: voiceless + voiced = voiced + voiced
-- should /ʋ/ be included as voiced? Орфоепічний словник doesn't voice initial cluster of шв (p. 116)
phonetic = mw.ustring.gsub(phonetic, "p(+)", "b%1")
phonetic = mw.ustring.gsub(phonetic, "f(+)", "v%1")
phonetic = mw.ustring.gsub(phonetic, "t(+)", "d%1")
phonetic = mw.ustring.gsub(phonetic, "tʲ(+)", "dʲ%1")
phonetic = mw.ustring.gsub(phonetic, "s(+)", "z%1")
phonetic = mw.ustring.gsub(phonetic, "sʲ(+)", "zʲ%1")
phonetic = mw.ustring.gsub(phonetic, "ʃ(+)", "ʒ%1")
phonetic = mw.ustring.gsub(phonetic, "k(+)", "ɡ%1")
phonetic = mw.ustring.gsub(phonetic, "x(+)", "ɦ%1")
phonetic = mw.ustring.gsub(phonetic, "t͡s(+)", "d͡z%1")
phonetic = mw.ustring.gsub(phonetic, "t͡sʲ(+)", "d͡zʲ%1")
phonetic = mw.ustring.gsub(phonetic, "t͡ʃ(+)", "d͡ʒ%1")
phonetic = mw.ustring.gsub(phonetic, "ʃt͡ʃ(+)", "ʒd͡ʒ%1")
-- In the sequence of two consonants, of which the second is soft, the first is pronounced soft too
-- unless the first consonant is a labial, namely б, п, в, ф, м.
phonetic = mw.ustring.gsub(phonetic, "()(.)ʲ", "%1ʲ%2ʲ")
phonetic = mw.ustring.gsub(phonetic, "()t͡sʲ", "%1ʲt͡sʲ")
phonetic = mw.ustring.gsub(phonetic, "()d͡zʲ", "%1ʲd͡zʲ")
phonetic = mw.ustring.gsub(phonetic, "t͡s(.)ʲ", "t͡sʲ%1ʲ")
phonetic = mw.ustring.gsub(phonetic, "d͡z(.)ʲ", "d͡zʲ%1ʲ")
phonetic = mw.ustring.gsub(phonetic, "d͡zt͡sʲ", "d͡zʲt͡sʲ")
phonetic = mw.ustring.gsub(phonetic, "t͡sd͡zʲ", "t͡sʲd͡zʲ")
-- Hushing consonants ж, ч, ш assimilate to the following hissing consonants, giving a long hissing consonant:
-- + → , + → , + → , + →
phonetic = mw.ustring.gsub(phonetic, "ʒt͡sʲ", "zʲt͡sʲ")
phonetic = mw.ustring.gsub(phonetic, "t͡ʃt͡sʲ", "t͡sʲː")
phonetic = mw.ustring.gsub(phonetic, "ʃt͡sʲ", "sʲt͡sʲ")
phonetic = mw.ustring.gsub(phonetic, "ʃsʲ", "sʲː")
-- Hissing consonants before hushing consonants within a word assimilate - on зш and зч word-initially and
-- word-medially see above.
-- + → , + → , + →
-- + →
phonetic = mw.ustring.gsub(phonetic, "zʒ", "ʒː")
phonetic = mw.ustring.gsub(phonetic, "sʃ", "ʃː")
phonetic = mw.ustring.gsub(phonetic, "zt͡s", "ʒt͡s")
phonetic = mw.ustring.gsub(phonetic, "zd͡ʒ", "ʒd͡ʒ")
-- cleanup: excessive palatalization: CʲCʲCʲ → CCʲCʲ
phonetic = mw.ustring.gsub(phonetic, "(+)ʲ(+)ʲ(+)ʲ", "%1%2ʲ%3ʲ")
-- unstressed /ɑ/ has an allophone
phonetic = mw.ustring.gsub(phonetic, "(+)ɑ", "%1ɐ")
phonetic = mw.ustring.gsub(phonetic, "^ɑ", "ɐ")
-- unstressed /u/ has an allophone
phonetic = mw.ustring.gsub(phonetic, "(+)u", "%1ʊ")
phonetic = mw.ustring.gsub(phonetic, "^u", "ʊ")
-- unstressed /ɔ/ has by assimilation an allophone before a stressed syllable with /u/ or /i/
phonetic = mw.ustring.gsub(phonetic, "ɔ(+)ˈ(+)", "o%1ˈ%2")
-- one allophone covers unstressed /ɛ/ and /ɪ/
phonetic = mw.ustring.gsub(phonetic, "()ɛ", "%1e")
phonetic = mw.ustring.gsub(phonetic, "^ɛ", "e")
phonetic = mw.ustring.gsub(phonetic, "()ɪ", "%1e")
phonetic = mw.ustring.gsub(phonetic, "^ɪ", "e")
-- /ʋ/ has an allophone in a syllable coda
phonetic = mw.ustring.gsub(phonetic, "(+)ʋ", "%1u̯")
-- /ʋ/ has an allophone before /ɔ, u/and voiced consonants (not after a vowel)
phonetic = mw.ustring.gsub(phonetic, "ʋ(?)(+)", "w%1%2")
-- /ʋ/ has an allophone before before voiceless consonants (not after a vowel)
phonetic = mw.ustring.gsub(phonetic, "ʋ(+)", "ʍ%1")
-- in a syllable-final position (i.e. the first position of a syllable coda) /j/ has an allophone :
phonetic = mw.ustring.gsub(phonetic, "(+)j(?)(+)", "%1i̯%2%3")
phonetic = mw.ustring.gsub(phonetic, "(+)j$", "%1i̯")
-- also at the beginning of a word before a consonant
phonetic = mw.ustring.gsub(phonetic, "^j(+)", "i̯%1")
-- remove old orthographic apostrophe
phonetic = mw.ustring.gsub(phonetic, "!", "")
-- stress mark in correct place
phonetic = mw.ustring.gsub(phonetic, "(+)ˈ", "ˈ%1")
phonetic = mw.ustring.gsub(phonetic, "(̯)ˈ(?)", "ˈ%1%2")
phonetic = mw.ustring.gsub(phonetic, "ˈ(l??)()", "%1ˈ%2")
phonetic = mw.ustring.gsub(phonetic, "ˈ(r??)()", "%1ˈ%2")
phonetic = mw.ustring.gsub(phonetic, "ˈ(m??)()", "%1ˈ%2")
phonetic = mw.ustring.gsub(phonetic, "ˈ(n??)()", "%1ˈ%2")
return (phonetic)
end
return export