local export = {}
local m_string_utils = require("Module:string utilities")
local gsub = m_string_utils.gsub
local lower = m_string_utils.lower
local split = mw.text.split
local entering_tones = {
= "7", = "8", = "9"
}
local ipa_preprocess = {
= {"a", "ă"}, = {"yu", "y"}, = {"ăă", "a"}, = {"uk", "ŭk"}, = {"ik", "ĭk"},
= {"ou", "ŏu"}, = {"eoi", "eoy"}, = {"ung", "ŭng"}, = {"ing", "ĭng"}, = {"ei", "ĕi"},
}
local ipa_initial = {
= "p", = "pʰ", = "m", = "f",
= "t", = "tʰ", = "n", = "l",
= "k", = "kʰ", = "ŋ", = "kʷ", = "kʷʰ",
= "t͡ʃ", = "t͡ʃʰ", = "ʃ",
= "t͡s", = "t͡sʰ", = "s",
= "h", = "w", = "j",
= ""
}
local ipa_nucleus = {
= "aː", = "ɐ",
= "ɛː", = "e",
= "iː", = "ɪ",
= "ɔː", = "o",
= "œː", = "ɵ",
= "uː", = "ʊ",
= "yː"
}
local ipa_coda = {
= "i̯", = "u̯", = "y̯",
= "m", = "n", = "ŋ",
= "p̚", = "t̚", = "k̚",
= ""
}
local ipa_tone = {
= "<span style=\"cursor:help\" title=\"or 53\">⁵⁵</span>",
= "³⁵",
= "³³",
= "<span style=\"cursor:help\" title=\"or 11\">²¹</span>",
= "¹³",
= "²²",
= "⁵",
= "³",
= "²",
= ""
}
local ipa_tone_sandhi = {
= "⁻", = "⁻", = ""
}
local ipa_syllabic = {
= "m̩", = "ŋ̍"
}
local acute_accents = {
= "á", = "é", = "í", = "ó", = "ú"
}
local grave_accents = {
= "à", = "è", = "ì", = "ò", = "ù"
}
local macrons = {
= "ā", = "ē", = "ī", = "ō", = "ū"
}
local yale_final = {
= "沒有耶魯拼音", = "a",
= "沒有耶魯拼音", = "沒有耶魯拼音", = "沒有耶魯拼音", = "沒有耶魯拼音", = "沒有耶魯拼音",
= "沒有耶魯拼音", = "沒有耶魯拼音",
= "沒有耶魯拼音", = "沒有耶魯拼音",
= "eu", = "沒有耶魯拼音", = "沒有耶魯拼音", = "eung", = "沒有耶魯拼音", = "沒有耶魯拼音", = "euk",
= "eui", = "eun", = "eut",
= ""
}
local canton_pinyin_regex = {
= "y", = "oe", = "oey", = "dz%1", = "ts%1",
)()"]=function(a,b) return a .. entering_tones end,
)()$"]=function(a,b) return a .. entering_tones end
}
local function yale_tone(final,b)
if b == "4" or b == "5" or b == "6" then
final = gsub(final, "(?g?)$", "h%1", 1)
end
if b == "1" then final = gsub(final, "", macrons, 1) end
if b == "4" then final = gsub(final, "", grave_accents, 1) end
if b == "2" or b == "5" then final = gsub(final, "", acute_accents, 1) end
return final
end
function export.jyutping_to_ipa(text)
if type(text) == "table" then text = text.args end
if text:find("") then error("Invalid tone in Jyutping.") end
if text:find("") then error("Please do not capitalize the Jyutping.") end
if text:find("%-") then error("Please do not hyphenate the Jyutping.") end
if text:find("") then error("Error in the Jyutping transcription.") end
if text:find("h") then error("'zh'/'ch'/'sh' are non-valid Jyutping, use 'z'/'c'/'s' instead.") end
if text:find("y") then error("Wrong usage of 'y' in Jyutping.") end
if text:find("oei") then error("Invalid rime oei in Jyutping.") end
if text:find("eong") then error("Invalid rime eong in Jyutping") end
if text:find("eok") then error("Invalid rime eok in Jyutping") end
text = text:lower()
text = gsub(text, "jy()", "j%1")
text = gsub(text, "%.%.%.", " ")
text = gsub(gsub(text, ",", "隔"), "隔 ", ", ")
local reading = split(text, "隔")
local function retrieve_ipa1(a,b,c,d,e)
return ipa_initial .. ipa_syllabic .. ipa_tone .. ipa_tone_sandhi .. ipa_tone
end
local function retrieve_ipa2(a,b,c,d,e,f)
return (ipa_initial or error(("Unrecognised initial: \"%s\""):format(a))) ..
(ipa_nucleus or error(("Unrecognised nucleus: \"%s\""):format(b))) ..
(ipa_coda or error(("Unrecognised coda: \"%s\""):format(c))) ..
(ipa_tone or error(("Unrecognised tone: \"%s\""):format(d))) ..
ipa_tone_sandhi ..
(ipa_tone or error(("Unrecognised tone: \"%s\""):format(f)))
end
local function get_entering_tone(a,b) return a .. entering_tones end
for i = 1,#reading do
reading = gsub(gsub(reading, "()", "%1 "), "", "")
local syllable = split(reading:lower(), " ")
if #syllable == 1 then
require('Module:debug').track('yue-pron/'..(syllable))
end
for i = 1,#syllable do
syllable = gsub(syllable, "()yu", "%1hyu")
syllable = gsub(syllable, "()oe", "%1hoe")
syllable = gsub(syllable, "()eo", "%1heo")
if (not syllable:find("^??+?g???$") and not syllable:find("^h?g???$")) and syllable:find("") then
error("Incorrect Jyutping format. Please check!")
end
syllable = gsub(syllable, "^(h?)(g?)()(?)(?)$", retrieve_ipa1)
syllable = gsub(syllable, "()()", get_entering_tone)
syllable = gsub(syllable, "()()$", get_entering_tone)
for regex_idx,regex_pair in ipairs(ipa_preprocess) do
syllable = gsub(syllable,regex_pair,regex_pair)
end
syllable = gsub(syllable, "spăn", "span")
syllable = gsub(syllable,
"(??)(?)(?g?)()(?)(?)",
retrieve_ipa2)
end
reading = table.concat(syllable, " ")
end
return table.concat(reading, "/, /")
end
function export.jyutping_to_yale(text)
if type(text) == "table" then text = text.args end
text = gsub(text, "jy()", "j%1")
text = gsub(text, ",", "隔"):gsub("隔 ", ", ")
local reading = split(text, "隔")
local function yale_tone2(a, b) return yale_tone((yale_final or a), b) end
for i = 1,#reading do
reading = gsub(reading, "%-", "")
reading = gsub(reading, "()", "%1 ")
local syllables = split(lower(reading), " ",true)
for j = 1,#syllables do
local text = syllables
text = gsub(text, "",{ = "1", = "3", = "6"})
text = gsub(text, "^m$",{ = "{{懸停|或m̀|m̄}}", = "ḿ", = "m", = "m̀h", = "ḿh", = "mh"})
text = gsub(text, "^ng$",{ = "{{懸停|或ǹg|n̄g}}", = "ńg", = "ng", = "ǹgh", = "ńgh", = "ngh"})
text = gsub(text, "jy?", "y")
text = gsub(text, "",{ = "j", = "ch"})
text = gsub(text, "(???)()", yale_tone2)
text = gsub(text, "(yu?)()", yale_tone)
text = gsub(text, "",{ = "{{懸停|或à|ā}}", = "{{懸停|或è|ē}}", = "{{懸停|或ì|ī}}", = "{{懸停|或ò|ō}}", = "{{懸停|或ù|ū}}"})
text = gsub(text, "{{懸停|或(+)|(+)}}", '<span style="cursor:help" title="or %1">%2</span>')
syllables = text
end
reading = table.concat(syllables, " ")
if reading:find("沒有耶魯拼音") then
reading = "colloquial sounds not defined"
end
end
return table.concat(reading, ", ")
end
function export.jyutping_to_cantonese_pinyin(text)
if type(text) == "table" then text = text.args end
text = gsub(text, "jy()", "j%1")
text = gsub(gsub(text, ",", "隔"), "隔 ", ", ")
local reading = split(text, "隔")
for i=1,#reading do
if reading:find("oe") then
reading = "沒有教院式拼音"
end
for regex, replace in pairs(canton_pinyin_regex) do
reading = gsub(reading, regex, replace)
end
if reading:find("沒有教院式拼音") then
reading = "colloquial sounds not defined"
end
end
return table.concat(reading, ", ")
end
function export.jyutping_to_guangdong(text)
if type(text) == 'table' then text = text.args end
local palatal = { ='j', ='q', ='x' }
local function palatalize(a,b) return palatal .. b end
local final = { ='b', ='g', ='d' }
local function get_final(a,b) return final .. b end
text = gsub(gsub(text, ",", "隔"), "隔 ", ", ")
local reading = split(text, "隔")
for i, item in ipairs(reading) do
item = gsub(item, 'yu', 'ü')
item = gsub(item, 'eoi', 'êü')
item = gsub(item, 'j', 'y')
item = gsub(item, 'oe', '沒有廣東拼音')
item = gsub(item, '', 'ê')
item = gsub(item, 'o', '沒有廣東拼音')
item = gsub(item, 'e', '沒有廣東拼音')
item = gsub(item, 'e', 'é')
item = gsub(item, 'u', '沒有廣東拼音')
item = gsub(item, '()()', palatalize)
item = gsub(item, '()ü', '%1u')
item = gsub(item, 'a+', { ='a', ='e' } )
item = gsub(item, '()w', '%1u')
item = gsub(item, '()u', '%1o')
item = gsub(item, '()(%d)', get_final)
item = gsub(item, 'e', '沒有廣東拼音')
if item:find('沒有廣東拼音') then
item = 'colloquial sounds not defined'
end
reading = item
end
return table.concat(reading, ", ")
end
function export.jyutping_format(text)
if type(text) == "table" then text = text.args end
if text:find("%[%[") then
return "just a lengthy text to ensure it works"
end
text = split(gsub(gsub(text, ",", "隔"), "隔 ", ", "), "隔")
for i, to_be_processed in ipairs(text) do
text = gsub(to_be_processed, "%-()", "%1")
end
return text
end
function export.hoisanva_to_ipa(text)
local hsv_initial = {
= "p", = "pʰ", = "ᵐb", = "f", = "v",
= "t", = "tʰ", = "ⁿd", = "l", = "ɬ",
= "k", = "kʰ", = "ᵑɡ",
= "t͡s", = "t͡sʰ",
= "j", = "s", = "h", = ""
}
local hsv_final = {
= "a", = "ai", = "au", = "am",
= "an", = "aŋ", = "ap̚", = "at̚",
= "ak̚",
= "i", = "iu", = "im", = "in",
= "ip̚", = "it̚",
= "iɛ", = "iau", = "iam", = "iaŋ",
= "iap̚", = "iak̚",
= "u", = "ui", = "un", = "ut̚",
= "ə", = "ei", = "eu", = "em", = "en",
= "ɵŋ", = "ep̚", = "et̚", = "ɵk̚", = "ɵt̚",
= "ᵘɔ", = "ᵘɔi", = "ᵘɔn", = "ɔŋ",
= "ᵘɔt̚", = "ɔk̚",
= "m̩"
}
local hsv_tone = { "³³", "⁵⁵", "²²", "²¹", "³²" }
local gsplit = mw.text.gsplit
local result = {}
for word in gsplit(text, ",") do
local initial, final, tone, tone_ch, word_result = "", "", "", "", {}
for syllable in gsplit(word, " ") do
initial, final, tone, tone_ch = syllable:match("^(*)(*)()(??%*?)$")
if final == "" then final, initial = initial, "" end
if not hsv_initial or not hsv_final or not hsv_tone or (tone == "2" and tone_ch == "*") then
error("Syllable '" .. syllable .. "' is not a valid syllable for IPA conversion.")
end
table.insert(word_result,
hsv_initial .. hsv_final .. hsv_tone ..
(tone_ch ~= "" and "⁻" or "") ..
(tone_ch == "*" and hsv_tone or (tone_ch:find("^%-") and hsv_tone or "")) ..
(tone_ch:sub(-1, -1) == "*" and "⁵" or ""))
end
table.insert(result, table.concat(word_result, " "))
end
return "/" .. table.concat(result, "/, /") .. "/"
end
function export.jyutping_headword(frame)
local params = {
= {},
}
local args = require("Module:parameters").process(frame:getParent().args, params, nil, "yue-pron", "jyutping_headword")
local head = args.head or mw.title.getCurrentTitle().text
local yue = require("Module:languages").getByCode("yue")
local Latn = require("Module:scripts").getByCode("Latn")
head = head:gsub("%d?%d?", "<sup>%0</sup>")
return require("Module:headword").full_headword{lang = yue, sc = Latn, heads = {head}, pos_category = "jyutping"}
end
return export