local export = {}
local count = require("Module:string utilities").count
local gsub = mw.ustring.gsub
local gsplit = mw.text.gsplit
local lower = mw.ustring.lower
local match = mw.ustring.match
local trim = mw.text.trim
--[[
Sourced from A grammatical overview of Santa Mongolian by Kenneth Lynn Field (1997),
东乡语汉语词典 (Dongxiang-Chinese Dictionary) by Ma Guozhong (马国忠) (2001)
]]--
-- List of valid phonemes
local phons = {
-- list of valid consonant phonemes
= {
= "p", = "pʰ", = "m", = "f",
= "t", = "tʰ", = "n", = "l", = "r",
= "k", = "kʰ", = "q", = "qʰ",
= "x", = "ʁ", = "h",
= "t͡ɕ", = "t͡ɕʰ", = "ɕ",
= "t͡ʂ", = "t͡ʂʰ", = "ʂ",
= "t͡s", = "t͡sʰ", = "s",
= "w", = "j"
},
-- list of valid vowel phomemes
= {
= "jɑw", = "wɑj",
= "ɑj", = "əj", = "ɑw", = "əw", = "ɯ",
= "jɑ", = "jə", = "ju", = "wəj", = "wɑ",
= "ɑ", = "o", = "ə", = "i", = "u"
},
-- list of phonetic diphthong representations
= {
= { "i̯ɑu̯", "i̯ou̯" }, = { "u̯ɑi̯", "u̯ɛi̯" },
= { "ɑi̯", "ɛi̯" }, = "ə̝i̯", = { "ɑu̯", "ou̯" }, = { "əu̯", "ɤu̯" },
= "i̯ɑ", = "i̯ɛ", = "i̯u", = "u̯(ə̝)i̯", = "u̯ɑ"
}
}
-- List of valid graphemes
local graphs = {
cons_g = "??", -- list of valid consonant graphemes
vowel_g = "+" -- list of valid vowel graphemes
}
-- Returns the number of syllables in a given string
local function count_syll(text)
return count(text, "ɚ") + count(text, "+")
end
-- Returns a string with two unique substitutions given a table with two items
local function sub_multiple(text, string, subs)
local foo, foo_sub = gsub(text, string, subs)
local bar, bar_sub = gsub(text, string, subs)
if foo_sub == 0 and bar_sub == 0 then
return text
else
return foo .. " ~ " .. bar
end
end
-- Handles ambiguous syllable-final n
local function n_final(text)
local n = match(text, "n+")
if n and count(text, n) > 1 then
error("ŋ is ambiguous. Please provide the full respelling.")
elseif text == "ŋ" then
text = mw.title.getCurrentTitle().text
text = gsub(text, "n", "ŋ")
end
return text
end
-- Automatically adds stress mark to the final syllable of a word if no stress mark is present
local function stress_word(word)
if not match(word, "ˈ") and count_syll(word) > 1 then
if match(word, "ɚ ") then
word = gsub(word, "(" .. graphs.cons_g .. "ɚ) ", "ˈ%1 ")
else
word = gsub(word, "(" .. graphs.cons_g .. graphs.vowel_g .. "*) ", "ˈ%1 ")
end
end
return word
end
-- Adjusts the text including respelling the term
local function adjust(text, etyl)
text = lower(text) -- make text lowercase
text = " " .. text .. " " -- make all word borders have a space
text = gsub(text, "'", "ˈ") -- convert apostrophe to a stress mark
text = gsub(text, "gvi", "gvii") -- i after gv is pronounced as ii
text = gsub(text, "(hi)", "%1i") -- same after gh, kh and h
text = gsub(text, "er()", "ɚ%1") -- "er" is a unique syllable in its own right
if etyl == "zh" or etyl == "ar" then text = gsub(text, "r", "ʐ") end -- r is pronounced as ʐ in words of Chinese and Arabic origin
return text
end
-- Convert the text to a phonemic IPA transcription
function export.IPA_m(text, etyl)
text = n_final(text) -- handle syllable-final n
text = adjust(text, etyl) -- adjust the text by respelling
text = gsub(text, "* ", function(word) -- handle stress marks
return gsub(stress_word(word), graphs.cons_g, phons.cons_m):gsub(graphs.vowel_g, phons.vowel_m) -- and convert graphemes to phonemes
end)
return trim(text)
end
-- Convert the text to a phonetic IPA transcription from the phonemic transcription
function export.IPA_t(text, etyl)
text = n_final(text) -- handle syllable-final n
text = adjust(text, etyl) -- adjust the text by respelling
text = gsub(text, "* ", function(word) -- handle stress marks
return gsub(stress_word(word), graphs.cons_g, phons.cons_m) -- and convert graphemes to phonemes (consonants only)
end)
-- diphthongs
for k, v in pairs(phons.diph_t) do
if type(v) == "table" then
text = sub_multiple(text, k, v)
else
text = gsub(text, k, v)
end
end
-- a
text = gsub(text, "a(ˈ?)n", "æ%1n") -- /ɑ/ before /n/ is
text = gsub(text, "a", "ɑ") -- otherwise
-- e
text = gsub(text, "e(ˈ?)ŋ", "ɤ%1ŋ") -- stressed /ə/ before /ŋ/ is
text = gsub(text, "ˈ(" .. graphs.cons_g .. ")e", "ˈ%1ɛ") -- otherwise stressed /ə/ is
text = gsub(text, "e", "ə")
-- i
text = gsub(text, "(h)i", "%1ɨ") -- /i/ is after retroflex consonants
text = gsub(text, "()i", "%1ɪ") -- /i/ is after alveolar affricates and fricatives
-- o
text = gsub(text, "* ", function(word) -- /o/ is labialised as only if it appears once in a word
return count(word, "o") == 1 and gsub(word, "o", "ʷo") or word
end)
-- devoiced vowels
-- vowels before /n, ŋ/ are nasalised
text = gsub(text, "(.̯?)(ˈ?)", "%1̃%2")
return trim(text)
end
function export.show(frame)
local args = frame:getParent().args -- get the arguments
local etyl = args.etyl -- get the etymology
local text = mw.title.getCurrentTitle().text -- get current page title
local results = {} -- store the results
if args then
for _, param in ipairs(args) do
if param ~= "" then
table.insert(results, {pron = "/" .. export.IPA_m(param, etyl) .. "/"})
end
end
else
table.insert(results, {pron = "/" .. export.IPA_m(text, etyl) .. "/"})
end
return "*" .. require("Module:IPA").format_IPA_full { lang = require("Module:languages").getByCode("sce"), items = results }
end
return export