Documentation for this module may be created at Module:th-pron/doc

local export = {}

local gsub = mw.ustring.gsub
local sub = mw.ustring.sub
local match = mw.ustring.match

local iConv = {
	["ก"] = { ["paiboon"] = "g", ["ipa"] = "k", ["type"] = "mid" },
	["จ"] = { ["paiboon"] = "j", ["ipa"] = "t͡ɕ", ["type"] = "mid" },
	["ด"] = { ["paiboon"] = "d", ["ipa"] = "d", ["type"] = "mid" },
	["ฎ"] = { ["paiboon"] = "d", ["ipa"] = "d", ["type"] = "mid" },
	["ฏ"] = { ["paiboon"] = "dt", ["ipa"] = "t", ["type"] = "mid" },
	["ต"] = { ["paiboon"] = "dt", ["ipa"] = "t", ["type"] = "mid" },
	["บ"] = { ["paiboon"] = "b", ["ipa"] = "b", ["type"] = "mid" },
	["ป"] = { ["paiboon"] = "bp", ["ipa"] = "p", ["type"] = "mid" },
	["อ"] = { ["paiboon"] = "", ["ipa"] = "ʔ", ["type"] = "mid" },
	
	["ง"] = { ["paiboon"] = "ng", ["ipa"] = "ŋ", ["type"] = "low" },
	["ณ"] = { ["paiboon"] = "n", ["ipa"] = "n", ["type"] = "low" },
	["น"] = { ["paiboon"] = "n", ["ipa"] = "n", ["type"] = "low" },
	["ม"] = { ["paiboon"] = "m", ["ipa"] = "m", ["type"] = "low" },
	["ญ"] = { ["paiboon"] = "y", ["ipa"] = "j", ["type"] = "low" },
	["ย"] = { ["paiboon"] = "y", ["ipa"] = "j", ["type"] = "low" },
	["ร"] = { ["paiboon"] = "r", ["ipa"] = "r", ["type"] = "low" },
	["ล"] = { ["paiboon"] = "l", ["ipa"] = "l", ["type"] = "low" },
	["ฬ"] = { ["paiboon"] = "l", ["ipa"] = "l", ["type"] = "low" },
	["ว"] = { ["paiboon"] = "w", ["ipa"] = "w", ["type"] = "low" },
	
	["ค"] = { ["paiboon"] = "k", ["ipa"] = "kʰ", ["type"] = "low" }, 
	["ฅ"] = { ["paiboon"] = "k", ["ipa"] = "kʰ", ["type"] = "low" },
	["ฆ"] = { ["paiboon"] = "k", ["ipa"] = "kʰ", ["type"] = "low" },
	["ข"] = { ["paiboon"] = "k", ["ipa"] = "kʰ", ["type"] = "high" },
	["ฃ"] = { ["paiboon"] = "k", ["ipa"] = "kʰ", ["type"] = "high" },
	["ช"] = { ["paiboon"] = "ch", ["ipa"] = "t͡ɕʰ", ["type"] = "low" },
	["ฌ"] = { ["paiboon"] = "ch", ["ipa"] = "t͡ɕʰ", ["type"] = "low" },
	["ฉ"] = { ["paiboon"] = "ch", ["ipa"] = "t͡ɕʰ", ["type"] = "high" },
	["ฑ"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "low" },
	["ฒ"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "low" },
	["ท"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "low" },
	["ธ"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "low" },
	["ฐ"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "high" },
	["ถ"] = { ["paiboon"] = "t", ["ipa"] = "tʰ", ["type"] = "high" },
	["พ"] = { ["paiboon"] = "p", ["ipa"] = "pʰ", ["type"] = "low" },
	["ภ"] = { ["paiboon"] = "p", ["ipa"] = "pʰ", ["type"] = "low" },
	["ผ"] = { ["paiboon"] = "p", ["ipa"] = "pʰ", ["type"] = "high" },
	["ฟ"] = { ["paiboon"] = "f", ["ipa"] = "f", ["type"] = "low" },
	["ฝ"] = { ["paiboon"] = "f", ["ipa"] = "f", ["type"] = "high" },
	["ซ"] = { ["paiboon"] = "s", ["ipa"] = "s", ["type"] = "low" },
	["ศ"] = { ["paiboon"] = "s", ["ipa"] = "s", ["type"] = "high" },
	["ษ"] = { ["paiboon"] = "s", ["ipa"] = "s", ["type"] = "high" },
	["ส"] = { ["paiboon"] = "s", ["ipa"] = "s", ["type"] = "high" },
	["ฮ"] = { ["paiboon"] = "h", ["ipa"] = "h", ["type"] = "low" },
	["ห"] = { ["paiboon"] = "h", ["ipa"] = "h", ["type"] = "high" },
	
	["หง"] = { ["paiboon"] = "ng", ["ipa"] = "ŋ", ["type"] = "high" },
	["หน"] = { ["paiboon"] = "n", ["ipa"] = "n", ["type"] = "high" },
	["หม"] = { ["paiboon"] = "m", ["ipa"] = "m", ["type"] = "high" },
	["หญ"] = { ["paiboon"] = "y", ["ipa"] = "j", ["type"] = "high" },
	["หย"] = { ["paiboon"] = "y", ["ipa"] = "j", ["type"] = "high" },
	["หร"] = { ["paiboon"] = "r", ["ipa"] = "r", ["type"] = "high" },
	["หล"] = { ["paiboon"] = "l", ["ipa"] = "l", ["type"] = "high" },
	["หว"] = { ["paiboon"] = "w", ["ipa"] = "w", ["type"] = "high" },
	
	[""] = { ["paiboon"] = "[[Category:Entries with failed Thai transliterations]]", ["ipa"] = "", ["type"] = "" },
}

local vConv = {
	["paiboon"] = {
		["open"] = {
			["ะ"] = "a", [""] = "a", ["ิ"] = "i", ["ึ"] = "ʉ", ["ุ"] = "u", ["เะ"] = "e", ["แะ"] = "ɛ", 
			["โะ"] = "o", ["เาะ"] = "ɔ", ["็"] = "ɔ", ["เิ"] = "ə", ["เอะ"] = "ə",
		
			["า"] = "aa", ["ี"] = "ii", ["ู"] = "uu", ["ือ"] = "ʉʉ", ["เ"] = "ee", ["แ"] = "ɛɛ",
			["โ"] = "oo", ["อ"] = "ɔɔ", ["ร"] = "ɔɔn", ["เอ"] = "əə",
		
			["เียะ"] = "ia", ["เือะ"] = "ʉa", ["ัวะ"] = "ua",
			["เีย"] = "iia", ["เือ"] = "ʉʉa", ["ัว"] = "uua",
			
			["ิว"] = "iu", ["เ็ว"] = "eo", ["แ็ว"] = "ɛo", ["เา"] = "ao",
			["เว"] = "eeo", ["แว"] = "ɛɛo", ["าว"] = "aao", ["เอว"] = "əəo", ["โว"] = "oow",
			["เียว"] = "iao",
		
			["ัย"] = "ai", ["ใ"] = "ai", ["ไ"] = "ai", ["ไย"] = "ai", ["็อย"] = "ɔi", ["ุย"] = "ui",
			["าย"] = "aai", ["อย"] = "ɔɔi", ["โย"] = "ooi", ["เย"] = "əəi", ["ูย"] = "uui",
			["วย"] = "uai", ["เือย"] = "ʉai",
		
			["ำ"] = "am",
		},

		["closed"] = {
			["ั"] = "a", ["รร"] = "a", ["ิ"] = "i", ["ึ"] = "ʉ", ["ุ"] = "u",
			["เ"] = "ee", ["เ็"] = "e", ["แ็"] = "ɛ", ["แ"] = "ɛɛ", 
			[""] = "o", ["็อ"] = "ɔ", ["เิ็"] = "ə",
			
			["า"] = "aa", ["ี"] = "ii", ["ื"] = "ʉʉ", ["ู"] = "uu", ["ู"] = "uu",
			["โ"] = "oo", ["อ"] = "ɔɔ", ["เิ"] = "əə", ["เอ"] = "əə",
		
			["เีย"] = "iia", ["เือ"] = "ʉʉa", ["ว"] = "uua",
			["ไ"] = "ai",
		}
	},

	["ipa"] = {
		["open"] = {
			["ะ"] = "ä(ʔ)", [""] = "ä", ["ิ"] = "i", ["ึ"] = "ɯ", ["ุ"] = "u", ["เะ"] = "eʔ", ["แะ"] = "ɛʔ", 
			["โะ"] = "oʔ", ["เาะ"] = "ɔʔ", ["็"] = "ɔ", ["เิ"] = "ɤ", ["เอะ"] = "ɤʔ",
		
			["า"] = "äː", ["ี"] = "iː", ["ู"] = "uː", ["ือ"] = "ɯː", ["เ"] = "eː", ["แ"] = "ɛː",
			["โ"] = "oː", ["อ"] = "ɔː", ["ร"] = "ɔːn", ["เอ"] = "ɤː",
		
			["เียะ"] = "ia̯ʔ", ["เือะ"] = "ɯa̯ʔ", ["ัวะ"] = "ua̯ʔ",
			["เีย"] = "i(ː)a̯", ["เือ"] = "ɯ(ː)a̯", ["ัว"] = "u(ː)a̯",
			
			["ิว"] = "iw", ["เ็ว"] = "ew", ["แ็ว"] = "ɛw", ["เา"] = "äw",
			["เว"] = "eːw", ["แว"] = "ɛːw", ["าว"] = "äːw", ["เอว"] = "ɤːw", ["โว"] = "oːw",
			["เียว"] = "i(ː)a̯w",
		
			["ัย"] = "äj", ["ใ"] = "äj", ["ไ"] = "äj", ["ไย"] = "äj", ["็อย"] = "ɔj", ["ุย"] = "ui",
			["าย"] = "äːj", ["อย"] = "ɔːj", ["โย"] = "oːj", ["เย"] = "ɤːj", ["ูย"] = "uːj",
			["วย"] = "u(ː)a̯j", ["เือย"] = "ɯ(ː)a̯j",
		
			["ำ"] = "äm",
		},

		["closed"] = {
			["ั"] = "ä", ["รร"] = "ä", ["ิ"] = "i", ["ึ"] = "ɯ", ["ุ"] = "u",
			["เ"] = "eː", ["เ็"] = "e", ["แ็"] = "ɛ", ["แ"] = "ɛː", 
			[""] = "o", ["็อ"] = "ɔ", ["เิ็"] = "ɤ",
			
			["า"] = "äː", ["ี"] = "iː", ["ื"] = "ɯː", ["ู"] = "uː", ["ู"] = "uː",
			["โ"] = "oː", ["อ"] = "ɔː", ["เิ"] = "ɤː", ["เอ"] = "ɤː",
		
			["เีย"] = "i(ː)a̯", ["เือ"] = "ɯ(ː)a̯", ["ว"] = "u(ː)a̯",
			["ไ"] = "äj", 
		}
	}
}

local unromLong = {
	["เีย"] = true, ["เือ"] = true, ["ัว"] = true, ["ว"] = true,
	["เือย"] = true, ["วาย"] = true, ["เอว"] = true,
	["เียว"] = true,
}

local liveExc = {
	["ัย"] = true, ["ใ"] = true, ["ไ"] = true, ["ไย"] = true,
	["ุย"] = true, ["วย"] = true,
	["เา"] = true, ["ิว"] = true, ["เ็ว"] = true, ["แ็ว"] = true,
	["ำ"] = true,
}

-- ย,ว are not included.
-- ช,ซ,ส,ฟ,ล are changed for loanwords.
-- ห,อ,ฮ can never be codas.
local cConv = {
	["paiboon"] = {
		["ก"] = "k", ["ข"] = "k", ["ฃ"] = "k", ["ค"] = "k", ["ฅ"] = "k", ["ฆ"] = "k",
		["จ"] = "t", ["ฉ"] = "t", ["ช"] = "ch", ["ซ"] = "s", ["ฌ"] = "t",
		["ฎ"] = "t", ["ฏ"] = "t", ["ฐ"] = "t", ["ฑ"] = "t", ["ฒ"] = "t",
		["ด"] = "t", ["ต"] = "t", ["ถ"] = "t", ["ท"] = "t", ["ธ"] = "t",
		["ศ"] = "t", ["ษ"] = "t", ["ส"] = "s",
		["บ"] = "p", ["ป"] = "p", ["ผ"] = "p", ["ฝ"] = "p", ["พ"] = "p", ["ฟ"] = "f", ["ภ"] = "p",
	
		["ง"] = "ng",
		["ญ"] = "n", ["ณ"] = "n", ["น"] = "n", ["ร"] = "n", ["ล"] = "l", ["ฬ"] = "n",
		["ม"] = "m",
	},

	["ipa"] = {
		["ก"] = "k̚", ["ข"] = "k̚", ["ฃ"] = "k̚", ["ค"] = "k̚", ["ฅ"] = "k̚", ["ฆ"] = "k̚",
		["จ"] = "t̚", ["ฉ"] = "t̚", ["ช"] = "t͡ɕʰ", ["ซ"] = "s", ["ฌ"] = "t̚",
		["ฎ"] = "t̚", ["ฏ"] = "t̚", ["ฐ"] = "t̚", ["ฑ"] = "t̚", ["ฒ"] = "t̚",
		["ด"] = "t̚", ["ต"] = "t̚", ["ถ"] = "t̚", ["ท"] = "t̚", ["ธ"] = "t̚",
		["ศ"] = "t̚", ["ษ"] = "t̚", ["ส"] = "s",
		["บ"] = "p̚", ["ป"] = "p̚", ["ผ"] = "p̚", ["ฝ"] = "p̚", ["พ"] = "p̚", ["ฟ"] = "f", ["ภ"] = "p̚",
	
		["ง"] = "ŋ",
		["ญ"] = "n", ["ณ"] = "n", ["น"] = "n", ["ร"] = "n", ["ล"] = "l", ["ฬ"] = "n",
		["ม"] = "m",
	},
}

local tFromMark = {
	["่"] = { ["high"] = "low",     ["mid"] = "low",     ["low"] = "falling" },
	["้"] = { ["high"] = "falling", ["mid"] = "falling", ["low"] = "high" },
	["๊"] = { ["high"] = "high",    ["mid"] = "high",    ["low"] = "high" },
	["๋"] = { ["high"] = "rising",  ["mid"] = "rising",  ["low"] = "rising" },
}

local tNoMark = {
	["dead-short"] = { ["high"] = "low",    ["mid"] = "low",  ["low"] = "high" },
	["dead-long"]  = { ["high"] = "low",    ["mid"] = "low",  ["low"] = "falling" },
	["live"]       = { ["high"] = "rising", ["mid"] = "mid",  ["low"] = "mid" },
}

local tRomMarks = {
	["high"] = "́", ["mid"] = "", ["low"] = "̀",
	["rising"] = "̌", ["falling"] = "̂",
}

local tLevels = {
	["high"] = "˦˥", ["mid"] = "˧", ["low"] = "˨˩",
	["rising"] = "˩˩˦", ["falling"] = "˥˩",
}

function export.translit(text, lang, sc, mode, source)
	for word in mw.ustring.gmatch(text, "[ก-๛]+") do
		local orig_word, class, tMark, tone, long, coda = word, "", false, false, false, false
		if match(word, "[่้๊๋].?[่้๊๋]") then
			return nil
		end
		
		local function syllable(v1, main, glide, v2, coda)
			tMark = match(v2, "[่้๊๋]")
			v2 = gsub(v2, "[่้๊๋]", "")
			if match(main, "^ห.$") then
				local pattern = "^([รลว]?)([ิึุ็ีืัำู]?[าอรยว]?[วยร]?ะ?)([คฅฆกขฃพฟภบปชฌฑฒทธจฎฏดตฐถศษสมญณนรลฬง]?)$"
				if match(sub(main, 2, 2)..glide..v2..coda, pattern) then
					glide, v2, coda = match(sub(main, 2, 2)..glide..v2..coda, pattern)
					main = "ห"
				end
			end
			if glide == "ล" and v2..coda == "" then
				coda = glide
				glide = ""
			end
			openness = coda ~= "" and "closed" or "open"
			if vConv[mode][openness][v1..glide..v2] then
				orig_v = v1..glide..v2
				vowel, glide = vConv[mode][openness][v1..glide..v2], ""
			else
				orig_v = v1..v2
				vowel = vConv[mode][openness][v1 .. v2] or (v1 .. v2)
				glide = (iConv[gsub(glide, "ฺ", "")] or iConv[""])[mode]
			end
			main = gsub(main, "ฺ", "")
			initial, class = "", ""
			if iConv[main] then
				initial, class = iConv[main][mode], iConv[main]["type"]
			else
				return nil
			end
			length = (match(vowel, "([aiʉueɛoɔə])%1") or match(vowel, "ː") or unromLong[orig_v]) and "long" or "short"
			life = (match(coda, "[มญณนรลฬง]") or (match(orig_v, "ย$") and match(vowel, "i$")) or
				coda..length == "long" or liveExc[orig_v]) and "live" or "dead"
			coda = cConv[mode][coda] or coda
			tone = tMark and tFromMark[tMark][class] or (tNoMark[life.."-"..length] or tNoMark[life])[class]
			if mode == "paiboon" then
				vowel = gsub(vowel, "^([^aiʉueɛoɔə]*)([aiʉueɛoɔə])", "%1%2" .. tRomMarks[tone])
			else
				coda = coda .. tLevels[tone]
			end
			return initial .. glide .. vowel .. coda
		end
			
		word = gsub(word, "^([เแโใไ]?)(ห?ฺ?[กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ])(ฺ?[รลว]?)([ิึุ็ีืัู]?็?[่้๊๋]?[าอรยวำ]?[วยร]?ะ?)([คฅฆกขฃพฟภบปชฌฑฒทธจฎฏดตฐถศษสมญณนรลฬง]?)$", syllable)

		text = gsub(text, orig_word, word, 1)
	end
	text = mode == "ipa" and gsub(text, "-", ".") or text
	if match(text, "[ก-๛]") then
		if source == "translit-module" then
			return nil
		else
			return "[[Category:Entries with failed Thai transliterations]]"
		end
	else
		return mw.ustring.toNFC(text)
	end
end

function annotate(main_text, annotation)
	return "<span style=\"border-bottom: 1px dotted #000; cursor:help\" " ..
		"title=\"" .. annotation .. "\">" .. main_text .. "</span>"
end

-- modified ISO 11940 (so that sound values are more apparent)
local charTable = {
	["ก"] = "k", ["ข"] = "kʰ", ["ฃ"] = "x", ["ค"] = "g", ["ฅ"] = "ɣ", ["ฆ"] = "gʰ", ["ง"] = "ŋ",
	["จ"] = "t͡ɕ", ["ฉ"] = "t͡ɕʰ", ["ช"] = "d͡ʑ", ["ซ"] = "z", ["ฌ"] = "d͡ʑʰ", ["ญ"] = "ɲ", 
	["ฎ"] = "ᶑ", ["ฏ"] = "ʈ", ["ฐ"] = "ʈʰ", ["ฑ"] = "ɖ", ["ฒ"] = "ɖʰ", ["ณ"] = "ɳ",
	["ด"] = "ɗ", ["ต"] = "t", ["ถ"] = "tʰ", ["ท"] = "d", ["ธ"] = "dʰ", ["น"] = "n",
	["บ"] = "ɓ", ["ป"] = "p", ["ผ"] = "pʰ", ["ฝ"] = "f", ["พ"] = "b", ["ฟ"] = "v", ["ภ"] = "bʰ", ["ม"] = "m",
	["ย"] = "y", ["ร"] = "r", ["ฤ"] = "ṛ", ["ล"] = "l", ["ฦ"] = "ḷ", ["ว"] = "w",
	["ศ"] = "ɕ", ["ษ"] = "ʂ", ["ส"] = "s", ["ห"] = "h", ["ฬ"] = "ɭ", ["อ"] = "ɒ", ["ฮ"] = "ʔ",
	
	["ะ"] = "a", ["ั"] = "ạ", ["า"] = "ā", ["ำ"] = "å", ["ิ"] = "i", ["ี"] = "ī",
	["ึ"] = "ụ", ["ื"] = "ụ̄", ["ุ"] = "u", ["ู"] = "ū", ["ๅ"] = "ɨ", ["ฺ"] = "̥", ["฿"] = "฿", -- uses spacing marks
	["เ"] = "Front-e</span>",
	["แ"] = "Front-æ</span>",
	["โ"] = "Front-o</span>",
	["ใ"] = "Front-au</span>",
	["ไ"] = "Front-ai</span>", 
	
	["่"] = "ˋ", ["้"] = "ˆ", ["๊"] = "ˊ", ["๋"] = "ˇ", -- uses spacing marks
	
	["ฯ"] = "ǂ", ["ๆ"] = "«", ["็"] = "˘", -- uses spacing marks
	["์"] = annotate("ʻ","CANCEL"), ["ํ"] = "˚", ["๎"] = "~", ["๏"] = "§", -- uses spacing marks
	["๚"] = "ǁ", ["๛"] = "»",
	
	["๐"] = "0", ["๑"] = "1", ["๒"] = "2", ["๓"] = "3", ["๔"] = "4", 
	["๕"] = "5", ["๖"] = "6", ["๗"] = "7", ["๘"] = "8", ["๙"] = "9", 
	
	[" "] = "&nbsp;&nbsp;", -- for visibility
	["-"] = "&ndash;", -- for visibility
}
		
function getCharSeq(text)
	local result = {}
	for character in mw.text.gsplit(text, "") do
		local charDetail = charTable[character] or nil
		if charDetail and charDetail[2] then
			table.insert(result, annotate(charDetail[1], charDetail[2]))
		else
			table.insert(result, charDetail)
		end
	end
	function tidyChar(text)
		text = gsub(text, "%+ %+", " &nbsp;")
		text = gsub(text, "%+%-%+", "&thinsp;—&thinsp;")
		text = gsub(text, "Front%-", "<span style=\"border:1px dotted gray; border-radius:50%; cursor:help\" title=\"Vowel sign appearing in front of the initial consonant.\">")
		return text
	end
	return "<br><small>" .. tidyChar(table.concat(result, "&thinsp;")) .. "</small>" -- thin space
end

local nSet = {
	["redup"] = annotate("Reduplication", "This word exhibits reduplication in pronunciation, i.e. one written consonant is used as the final consonant of a syllable as well as the initial consonant of the next syllable."),
	["short"] = annotate("Short", "The vowel in this word is pronounced irregularly short."),
	["unortho"] = annotate("Unorthographical", "This phonetic respelling violates Thai alphabet rules to indicate an irregular pronunciation."),
}

function export.show(frame)
	local lang, sc = "th", "Thai"
	local args = frame:getParent().args
	local pagename = args.pagename or mw.title.getCurrentTitle().text
	local p, note = {}, {}
	
	if args["note"] then
		for ind_note in mw.text.gsplit(args["note"], ",") do
			table.insert(note, nSet[ind_note])
		end
	end

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		table.insert(p, pagename)
	end
	
	if match(table.concat(p, "/"), "็[ก-๛]*[่้๊๋]") or match(table.concat(p, "/"), "[่้๊๋][ก-๛]*็") then
		table.insert(note, nSet["unortho"])
		if not match(args["note"] or "", "short") then
			table.insert(note, nSet["short"])
		end
	end

	headFmt = '{| cellpadding=10 style="border-spacing: 2px; border: 1px solid darkgray; text-align:center"'
	midFmt = '\n|-\n! bgcolor="#fafeff" style="border-bottom: 1px solid lightgray;border-right: 1px solid lightgray"|'
	lastFmt = '\n|-\n!bgcolor="#fafeff" style="border-right: 1px solid lightgray"|'
	normCellFmt = '\n|'
	preCellFmt = '\n| style="border-right: 1px solid lightgray"|'
	orthoCellFmt = '\n|colspan="' .. #p .. '" style="border-bottom: 1px solid lightgray"|'
	footFmt = '\n|}'
	
	function formatThai(text, mode)
		return (match(text, "-$")
			and '<span style="background-color:#ffffe6"><small>[ទម្រង់សមាស]</small></span><br>'
			or '') .. '<span lang="th" class="Thai">' .. text .. '</span>'
	end
	
	local result = { ["charPhon"] = {}, ["paiboon"] = {}, ["ipa"] = {}, ["homophone"] = {}, ["file"] = {} }
	local m_hom_data = require("Module:th-hom/data")
	local m_hom = require("Module:th-hom").makeList
	local m_fileData = require("Module:th-pron/files")
	for _, system in ipairs( { "charPhon", "paiboon", "ipa", "homophone", "file" } ) do
		for i, spelling in ipairs(p) do
			local before = {
				["paiboon"] = "<span class=\"tr\">",
				["ipa"] = "<span class=\"IPA\">/",
				["homophone"] = '<div class="vsSwitcher vsToggleCategory-glosses"><span class="vsToggleElement">&nbsp;</span><div class="vsShow" style="display:none"></div><div class="vsHide">',
				["file"] = "[[File:",
			}
			local after = {
				["paiboon"] = "</span>",
				["ipa"] = "/</span>",
				["homophone"] = "</div></div>",
			}
			local function fileAfter(text)
				length = ((mw.ustring.len(gsub(text, "[^ %-]", "")) + 1) * 25 + 50)
				return "|" .. (length > 200 and 200 or length) .. 
					"px|center]][[Category:បច្ចេកសព្ទសៀមមានតំណសំលេង]]"
			end
			table.insert(result[system], (i < #p and preCellFmt or normCellFmt) ..
				(system == "charPhon"
					and formatThai(spelling, true) .. getCharSeq(spelling)
					or (system ~= "homophone"
						and (system ~= "file" 
							and before[system] .. export.translit(spelling, lang, sc, system) .. after[system]
							or (m_fileData[spelling]
								and before[system] .. m_fileData[spelling] .. fileAfter(spelling)
								or "" ))
						or (m_hom_data[spelling] and (#m_hom_data[spelling] > 3 
							and before[system] .. gsub(m_hom(spelling), ", ", "<br>") .. after[system]
							or gsub(m_hom(spelling), ", ", "<br>")) or "" ))))
		end
	end
	inclHom = match(table.concat(result["homophone"]), "សៀម") or false
	inclFile = match(table.concat(result["file"]), "បច្ចេកសព្ទ") or false
	
	return
		headFmt ..
		
		((mw.title.getCurrentTitle().nsText ~= "" and not args.pagename)
			
			and (midFmt .. "''[[w:Thai alphabet|Phonemic]]''" ..
				(#note > 0 and "<br><small>{" .. table.concat(note, "; ") .. "}</small>" or ""))
			
			or (pagename == table.concat(p)
			
				and (midFmt .. "''[[w:អក្សរសៀម|អក្ខរាវិរុទ្ធ/សទ្ទតា]]''")
			
				or (midFmt .. "''[[w:អក្សរសៀម|អក្ខរាវិរុទ្ធ]]''" ..
					orthoCellFmt .. formatThai(pagename)) .. getCharSeq(pagename) ..
				
					midFmt .. "''[[w:អក្សរសៀម|សទ្ទតា]]''" ..
					(#note > 0 and "<br><small>{" .. table.concat(note, "; ") .. "}</small>" or ""))) ..
			
		table.concat(result["charPhon"]) ..
		
		midFmt .. "''[[Wiktionary:អក្ខរបរិវត្តន៍|ផៃប៊ូន]]''" ..
		table.concat(result["paiboon"]) ..
		
		((inclHom or inclFile) and midFmt or lastFmt) .. "(''[[w:បាងកង|បាងកក]]'') [[:en:Wiktionary:International Phonetic Alphabet|IPA]]<sup>([[ឧបសម្ព័ន្ធ:ការបញ្ចេញសំលេងភាសាសៀម|គន្លឹះ]])</sup>" ..
		table.concat(result["ipa"]) ..
		
		(inclHom and (inclFile and midFmt or lastFmt) .. "''សូរដូច''" .. table.concat(result["homophone"]) or "") ..
		
		(inclFile and lastFmt .. "''សំលេង''" .. table.concat(result["file"]) or "") ..
		
		footFmt
end

return export