local export = {}

local lang = require("Module:languages").getByCode("bn")
local sc = require("Module:scripts").getByCode("Beng")
local m_IPA = require("Module:IPA")
local m_a = require("Module:accent qualifier")

local gsub = mw.ustring.gsub
local gmatch = mw.ustring.gmatch
local find = mw.ustring.find

local correspondences = {
	["ṅ"] = "ŋ", ["g"] = "ɡ",
	["c"] = "t͡ʃ", ["j"] = "d͡ʒ",
	["ṭ"] = "ʈ", ["ḍ"] = "ɖ",
	["t"] = "t̪", ["d"] = "d̪",
	["y"] = "e̯", ["r"] = "ɾ", ["l"] = "l",
	["ś"] = "ʃ", ["h"] = "h", ["ḥ"] = "h",
	["ṛ"] = "ɽ",

	["y"] = "e̯", ["w"] = "o̯",

	["o"] = "ɔ", ["ô"] = "ɔ",
	["ī"] = "i", ["ō"] = "o",
	["ū"] = "u", ["ê"] = "æ",

	["õ"] = "ɔ̃", ["ō̃"] = "õ", ["ī̃"] = "ĩ", ["ū̃"] = "ũ", ["ễ"] = "æ̃",
}


local dhaka = {
	["c"] = "ṯɕ",	["ch"] = "ṯɕʰ", ["j"] = "ḏʑ", ["jh"] = "ḏʑʱ", ["r"] = "ɹ", ["ṛ"] = "ɹ", ["ṛh"] = "ɹ",

	["e"] = "e", ["ê"] = "ɛ", ["õ"] = "ɔ", ["ō̃"] = "o", ["ĩ"] = "i", ["ũ"] = "u", ["ẽ"] = "e", ["ễ"] = "ɛ", ["ã"] = "a",
}

local vanga = {
	["c"] = "ts", ["ch"] = "s", ["j"] = "dz", ["jh"] = "z", ["f"] = "ɸ", ["r"] = "ɾ", ["ṛ"] = "ɾ", ["ṛh"] = "ɾ",

	["e"] = "ɛ", ["ê"] = "ɛ", ["õ"] = "ɔ", ["ō̃"] = "o", ["ĩ"] = "i", ["ũ"] = "u", ["ẽ"] = "ɛ", ["ễ"] = "ɛ", ["ã"] = "a",
}

local eastern_vanga= {
	["c"] = "s", ["ch"] = "s", ["j"] = "z", ["jh"] = "z", ["k"] = "x", ["kh"] = "x", ["p"] = "ɸ", ["f"] = "ɸ", ["r"] = "ɹ", ["ṛ"] = "ɹ", ["ṛh"] = "ɹ",
}

local varendra = {
	["c"] = "s", ["ch"] = "ts", ["j"] = "z", ["jh"] = "dz", ["ṛ"] = "ɾ", ["ṛh"] = "ɾ",
}

local vowels = "aiuoōêɔɔ̃ɛeææ̃ãễẽĩõō̃ũ"
local vowel = "[aiuoōêɔɔ̃ɛeææ̃ãễẽĩõō̃ũ]"
local consonants = "[bcdd̪ḍɖfgjklmnṇprṛɾsṣśs̪ʃɕtt̪ṭʈzz̪ʑ]"
local weak = "([gjdḍbṛʑ])"
local aspirate = "([kctṭpɕ])"

local function find_consonants(text)
	local current = ""
	local cons = {}
	for cc in mw.ustring.gcodepoint(text .. " ") do
		local ch = mw.ustring.char(cc)
		if find(current .. ch, "^[kgṅcjñṭḍṇṁtdnpbmyrlvśṣshṛz]$") or find(current .. ch, "^[kgcjṭḍṇtdpbṛ]h$") then
			current = current .. ch
		else
			table.insert(cons, current)
			current = ch
		end
	end
	return cons
end

local identical = "knlsfz"
for character in gmatch(identical, ".") do
	correspondences[character] = character
end

local function transliterate(text)
	--return (lang:transliterate(text))
	return require("Module:bn-translit").tr(text, lang, sc)
end

function export.link(term)
	return require("Module:links").full_link{ term = term, lang = lang, sc = sc }
end

function export.toIPA(text, style)
	local translit = text
	if lang:findBestScript(text):isTransliterated() then
		translit = transliterate(text)
	end
	if not translit then
		error('The term "' .. text .. '" could not be transliterated.')
	end

	-- metathesis (Chatterji, 1921)
	translit = gsub(translit, "(" .. vowel .. ")hl", "%1lh")
	translit = gsub(translit, "(" .. vowel .. ")hm", "%1mh")
	translit = gsub(translit, "(" .. vowel .. ")hn", "%1nh")

	-- suppressing the above metathesis
	translit = gsub(translit, "h'l", "hl")
	translit = gsub(translit, "h'm", "hm")
	translit = gsub(translit, "h'n", "hn")

	-- some workarounds since [[Module:bn-translit]] is locked
	translit = gsub(translit, "ph", "f")
	translit = gsub(translit, "v", "bh")
	translit = gsub(translit, "ẏ", "y")
	translit = gsub(translit, "ẇ", "w")

	-- vowel harmony
	translit = gsub(translit, "o([bd̪hlmnrṛɹt̪])([iu])", "ó%1%2") -- Chatterji, 1926
	translit = gsub(translit, "o([bd̪hlnrṛɹt̪])o", "o%1ó")
	translit = gsub(translit, "ḍḍo", "ḍḍó") 
	translit = gsub(translit, "ṭṭo", "ṭṭó") 
	translit = gsub(translit, "ho$", "hó")
	translit = gsub(translit, "(" .. vowel .. ")h$", "%1")
	translit = gsub(translit, "(" .. vowel .. ")h ", "%1 ")

	translit = gsub(translit, "oi", "ói")
	translit = gsub(translit, "ou", "óu")

	translit = gsub(translit, "^(".. consonants .. ")o$", "%1ô")
	translit = gsub(translit, "o$", "ó")
	translit = gsub(translit, "õ$", "ó̃")

	translit = gsub(translit, "pro", "pró")
	translit = gsub(translit, "(" .. vowel .. ")(" .. consonants .. "h?)om$", "%1%2óm")
	translit = gsub(translit, "bon$", "bón")
	translit = gsub(translit, "ron$", "rón")

	translit = gsub(translit, "^(".. consonants .. ")o ", "%1ô ")
	translit = gsub(translit, " (".. consonants .. ")o$", " %1ô")

	translit = gsub(translit, "o ", "ó ")
	translit = gsub(translit, "õ ", "ó̃ ")

	translit = gsub(translit, "(" .. vowel .. ")(" .. consonants .. "h?)om ", "%1%2óm ")
	translit = gsub(translit, "bon ", "bón ")
	translit = gsub(translit, "ron ", "rón ")

	translit = gsub(translit, "^o", "ô")
	translit = gsub(translit, " o", " ô")

	translit = gsub(translit, "([lmn])ho", "%1hó")

	if style == "formal" then
		translit = gsub(translit, "ó", "ō")
	end

	if style == "desanskritized" then
		translit = gsub(translit, "ó", "ō")
		translit = gsub(translit, "ṛh", "ṛ")
	end

	if style == "colloquial" then
		translit = gsub(translit, "ó", "ō")
		translit = gsub(translit, "lh", "ll") -- Chatterji
		translit = gsub(translit, "mh", "mm") -- Chatterji
		translit = gsub(translit, "nh", "nn") -- Chatterji
		translit = gsub(translit, "ṛ", "r")
		translit = gsub(translit, "ṛh", "r")
		translit = gsub(translit, "śt", "st")
		translit = gsub(translit, "sṭ", "śṭ")
	end

	if style == "dhaka" then
		translit = gsub(translit, "ó", "ō")
		translit = gsub(translit, "([cjrṛ]h?)", dhaka)
		translit = gsub(translit, "(" .. vowel .. ")", dhaka)
		translit = gsub(translit, "ó̃", "ō")
	end

	if style == "dhaka_colloquial" then
		translit = gsub(translit, "ó", "ō")
		translit = gsub(translit, "lh", "ll")
		translit = gsub(translit, "mh", "mm")
		translit = gsub(translit, "nh", "nn")
		translit = gsub(translit, "śt", "st")
		translit = gsub(translit, "sṭ", "śṭ")

		translit = gsub(translit, "([cjprṛ]h?)", dhaka)
		translit = gsub(translit, "(" .. vowel .. ")", dhaka)
		translit = gsub(translit, "ō̃", "ō")
	end

	if style == "vanga" then
		translit = gsub(translit, "ó", "ô")
		translit = gsub(translit, "([cfjprṛ]h?)", vanga)
		translit = gsub(translit, "(" .. vowel .. ")", vanga)
		translit = gsub(translit, "śt", "st")
		translit = gsub(translit, "sṭ", "śṭ")
	end

	if style == "eastern_vanga" then
		translit = gsub(translit, "ó", "ô")
		translit = gsub(translit, "([cfjkprṛ]h?)", eastern_vanga)
		translit = gsub(translit, "(" .. vowel .. ")", vanga)
		translit = gsub(translit, "śt", "st")
		translit = gsub(translit, "sṭ", "śṭ")
	end

	if style == "varendra" then
		translit = gsub(translit, "ó", "ô")
		translit = gsub(translit, "śt", "st")
		translit = gsub(translit, "sṭ", "śṭ")
		translit = gsub(translit, "([cjṛ]h?)", varendra)
	end

	-- vowels
	translit = gsub(translit, "%-$", "")
	translit = gsub(translit, "^%-", "")
	translit = gsub(translit, ",", "")
	translit = gsub(translit, " ", "..")
	translit = gsub(translit, "%.ː", "ː.")
	translit = gsub(translit, "%.̃", "̃")

	translit = gsub(translit, "ay([eiu])", "a%1")
	translit = gsub(translit, "ey([aioōu])", "e%1")
	translit = gsub(translit, "êy([aeioōu])", "ê%1")
	translit = gsub(translit, "iy([aeoōu])", "i%1")
	translit = gsub(translit, "ĩy([aeoōu])", "ĩ%1")
	translit = gsub(translit, "ito$", "itō")
	translit = gsub(translit, "oy([eiōu])", "o%1")
	translit = gsub(translit, "õy([eiōu])", "õ%1")
	translit = gsub(translit, "ōw([aeoōu])", "ō%1")
	translit = gsub(translit, "ō̃w([aeoōu])", "ō̃%1")
	translit = gsub(translit, "uy([aeioō])", "u%1")
	translit = gsub(translit, "ũy([aeioō])", "ũ%1")

	local consonants_no_h = "[b-df-gj-np-tv-zśṣʃʒ]"

	translit = gsub(translit, aspirate .. "h", '%1ʰ')
	translit = gsub(translit, weak .. "h", '%1ʱ')

	translit = gsub(translit, "([kgcjṭḍtdpb])'h", "%1h")

	if style == "colloquial" then
		translit = gsub(translit, aspirate .. "h", '%1ʰ')
		translit = gsub(translit, weak .. "h", '%1ʱ')
	end

	local result = gsub(translit, ".", correspondences)

	result = gsub(result, "%.?%-", ".")

	result = gsub(result, "%.%.", "‿")

	if style == "dhaka" then
		result = gsub(result, "ḏʑ", "dʑ") 
		result = gsub(result, "ɖ", "d") -- Khan, 2010
		result = gsub(result, "ṯɕ", "tɕ")
		result = gsub(result, "ʈ", "t") -- Khan, 2010
	end

	if style == "dhaka_colloquial" then
		result = gsub(result, "ḏʑ", "dʑ") 
		result = gsub(result, "ɖ", "d") -- Khan, 2010
		result = gsub(result, "ṯɕ", "tɕ")
		result = gsub(result, "ʈ", "t") -- Khan, 2010
	end

	if style == "vanga" then
		result = gsub(result, "ɖ", "d")
		result = gsub(result, "ʈ", "t")
	end

	if style == "vanga_colloquial" then
		result = gsub(result, "ɖ", "d")
		result = gsub(result, "ʈ", "t")
	end

	if style == "eastern_vanga" then
		result = gsub(result, "ɖ", "d")
		result = gsub(result, "ʈ", "t")
	end

	if style == "eastern_vanga_colloquial" then
		result = gsub(result, "ɖ", "d")
		result = gsub(result, "ʈ", "t")
	end

	-- formatting
	result = gsub(result, "ː̃", "̃ː")
	result = gsub(result, "ː%.̃", "̃ː.")
	result = gsub(result, "%.$", "")

	result = gsub(result, "^ɾ", "r")

	-- force final ɔe̯
	result = gsub(result, "([ʒm])oe̯$", "%1ɔe̯")

	result = gsub(result, "d̪ʑ", "dʑ")
	result = gsub(result, "t̪ɕ", "tɕ")

	-- gemination
	result = gsub(result, "bb(ʱ?)", "b%1ː")
	result = gsub(result, "dd(ʱ?)", "d%1ː")
	result = gsub(result, "d͡d͡ʒʒ(ʱ?)", "d͡ʒ%1ː")
	result = gsub(result, "dʑdʑ(ʱ?)", "dʑ%1ː")
	result = gsub(result, "d̪d̪(ʱ?)", "d̪%1ː")
	result = gsub(result, "ɖɖ(ʱ?)", "ɖ%1ː")

	result = gsub(result, "ff", "fː")
	result = gsub(result, "ɡɡ(ʱ?)", "ɡ%1ː")

	result = gsub(result, "kk(ʰ?)", "k%1ː")
	result = gsub(result, "ll", "lː")

	result = gsub(result, "mm", "mː")
	result = gsub(result, "nn", "nː")

	result = gsub(result, "nd(ʱ?)ː", "nd%1")
	result = gsub(result, "nd͡ʒ(ʱ?)ː", "nd͡ʒ%1")
	result = gsub(result, "nd̪(ʱ?)ː", "nd̪%1")
	result = gsub(result, "nɖ(ʱ?)ː", "nɖ%1")
	result = gsub(result, "nt(ʰ?)ː", "nt%1")
	result = gsub(result, "nt͡ʃ(ʰ?)ː", "nt͡ʃ%1")
	result = gsub(result, "nt̪(ʰ?)ː", "nt̪%1")
	result = gsub(result, "nʈ(ʰ?)ː", "nʈ%1")
	result = gsub(result, "ŋɡ(ʱ?)ː", "ŋɡ%1")
	result = gsub(result, "ŋɡ$", "ŋ")
	result = gsub(result, "ŋɡ ", "ŋ ")
	result = gsub(result, "ŋk(ʰ?)ː", "ŋk%1")

	result = gsub(result, "pp(ʰ?)", "p%1ː")

	result = gsub(result, "ɾɾ", "ɾ")
	result = gsub(result, "ɹɹ", "ɹ")

	result = gsub(result, "ʃʃ", "ʃː")
	result = gsub(result, "ss", "sː")
	result = gsub(result, "tt(ʰ?)", "t%1ː")
	result = gsub(result, "t͡ʃt͡ʃ(ʰ?)", "t͡ʃ%1ː")
	result = gsub(result, "tɕtɕ(ʰ?)", "tɕ%1ː")
	result = gsub(result, "t̪t̪(ʰ?)", "t̪%1ː")
	result = gsub(result, "ʈʈ(ʰ?)", "ʈ%1ː")

	result = gsub(result, "a([eou])", "a%1̯")
	result = gsub(result, "iu", "iu̯")
	result = gsub(result, "i(" .. vowel .. ")", "i̯%1")
	result = gsub(result, "i̯u̯", "iu̯")
	result = gsub(result, "oa", "o̯a")
	result = gsub(result, "ɔe̯ɔ", "ɔe̯o")
	result = gsub(result, "ɔo", "ɔo̯")
	result = gsub(result, "o([iu])", "o%1̯")
	result = gsub(result, "u(" .. vowel .. ")", "u̯%1")

	result = gsub(result, "([aeou])i", "%1i̯")

	result = gsub(result, "^ui̯", "u̯i")

	result = gsub(result, "([eiou])̯̯", "%1̯")

	return result
end

function export.narrow_IPA(ipa)
	local vowel = "[aiuoêɔɔ̃ɛeææ̃ãẽĩõũ]"
	local consonants = "[bβcdd̪ɖfɸgɦjklmnprṛɾsśs̪ʃɕtt̪ʈvzz̪ʑ]"

	-- word-final deaspiration
	ipa = gsub(ipa, "bʱ$", "b")
	ipa = gsub(ipa, "ɖʱ$", "ɖ")
	ipa = gsub(ipa, "d͡ʒʱ$", "d͡ʒ")
	ipa = gsub(ipa, "dʑʱ$", "dʑ")
	ipa = gsub(ipa, "d̪ʱ$", "d̪")
	ipa = gsub(ipa, "ɡʱ$", "ɡ")
	ipa = gsub(ipa, "kʰ$", "k")
	ipa = gsub(ipa, "pʰ$", "p")
	ipa = gsub(ipa, "ʈʰ$", "ʈ")
	ipa = gsub(ipa, "t͡ʃʰ$", "t͡ʃ")
	ipa = gsub(ipa, "tɕʰ$", "tɕ")
	ipa = gsub(ipa, "t̪ʰ$", "t̪")

	-- deaspiration before t̪
	ipa = gsub(ipa, "kʰt̪", "kt̪")
	ipa = gsub(ipa, "pʰt̪", "pt̪")

	-- regressive assimilation
	ipa = gsub(ipa, "kz", "ɡz")
	ipa = gsub(ipa, "kd͡ʒ", "ɡd͡ʒ")
	ipa = gsub(ipa, "kdʑ", "ɡdʑ")

	ipa = gsub(ipa, "b‿p", "pː")
	ipa = gsub(ipa, "d‿t", "tː")
	ipa = gsub(ipa, "d͡ʒ‿t͡ʃ", "t͡ʃː")
	ipa = gsub(ipa, "d̪‿t̪", "t̪ː")
	ipa = gsub(ipa, "f‿b", "bː")
	ipa = gsub(ipa, "ɡ‿k", "kː")
	ipa = gsub(ipa, "k‿ɡ", "ɡː")
	ipa = gsub(ipa, "p‿b", "bː")
	ipa = gsub(ipa, "t‿d", "dː")
	ipa = gsub(ipa, "t͡ʃ‿d͡ʒ", "d͡ʒː")
	ipa = gsub(ipa, "t̪‿d̪", "d̪ː")
	ipa = gsub(ipa, "sː([t̪d̪])", "s̪%1")

	ipa = gsub(ipa, "d͡ʒ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "d͡ʒʱ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "dʑ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "dʑʱ(‿?)([d̪t̪])", "z̪%2")

	ipa = gsub(ipa, "^(" .. consonants .. ")ɾ(" .. vowel .. ")(" .. consonants .. ")ɾ", "%1ɾ%2%3ː") -- R syncope
	ipa = gsub(ipa, "([ɖd̪ʈt̪])([lɾɹ])", "%1ː%2")

	-- intervocalic e̯
	ipa = gsub(ipa, "(" .. vowel .. ")‿(" .. vowel .. ")", "%1e̯%2")

	ipa = gsub(ipa, "‿", "")

	-- long vowels
	ipa = gsub(ipa, "^(" .. vowel .. ")(" .. consonants .. ")$", "%1ː%2")
	ipa = gsub(ipa, "^(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2ː")
	ipa = gsub(ipa, "^(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2%3ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2%3ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2%3%4ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. ")(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2%3%4ː")
	ipa = gsub(ipa, "^(" .. consonants .. "ʰ?)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2ː%3")
	ipa = gsub(ipa, "^(" .. consonants .. "ʱ)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2ː%3")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2%3ː%4")

	-- half-long vowels
	ipa = gsub(ipa, "(" .. vowel .. ")$", "%1ˑ")
	ipa = gsub(ipa, "(" .. vowel .. ") ", "%1ˑ ")

	-- dental and retroflex laterals
	ipa = gsub(ipa, "l([t̪d̪])", "l̪%1")
	ipa = gsub(ipa, "l([ʈɖ])", "ɭ%1")

	-- dental and retroflex nasals
	ipa = gsub(ipa, "n([t̪d̪])", "n̪%1")
	ipa = gsub(ipa, "n̪([td])", "n%1")
	ipa = gsub(ipa, "n([ʈɖ])", "ɳ%1")

	-- dental and retroflex sibilants
	ipa = gsub(ipa, "s([t̪d̪])", "s̪%1")
	ipa = gsub(ipa, "([t̪d̪])s", "%1s̪")
	ipa = gsub(ipa, "s̪([td])", "s%1")
	ipa = gsub(ipa, "([td])s̪", "%1s")

	ipa = gsub(ipa, "z([t̪d̪])", "z̪%1")
	ipa = gsub(ipa, "([t̪d̪])z", "%1z̪")
	ipa = gsub(ipa, "z̪([td])", "z%1")
	ipa = gsub(ipa, "([td])z̪", "%1z")
	ipa = gsub(ipa, "ʃ([ʈɖ])", "ʂ%1")

	-- initial stress
	ipa = gsub(ipa, "^(" .. vowel .. ")", "ˈ%1")
	ipa = gsub(ipa, "^(" .. consonants .. ")", "ˈ%1")

	return ipa
end

local function colloquial_narrow_IPA(ipa)
	local vowel = "[aiuoêɔɔ̃ɛeææ̃ãẽĩõũ]"
	local consonants = "[bβcdd̪ɖfɸgɦjklmnprṛɾsśs̪ʃɕtt̪ʈvzz̪ʑ]"

	-- initial stress
	ipa = gsub(ipa, "^(" .. vowel .. ")", "ˈ%1")
	ipa = gsub(ipa, "^(" .. consonants .. ")", "ˈ%1")

	ipa = gsub(ipa, "bʱ", "v")
	ipa = gsub(ipa, "^v", "bʱ")
	ipa = gsub(ipa, " v", " bʱ")

	-- word-final deaspiration
	ipa = gsub(ipa, "ɖʱ$", "ɖ")
	ipa = gsub(ipa, "d͡ʒʱ$", "d͡ʒ")
	ipa = gsub(ipa, "dʑʱ$", "dʑ")
	ipa = gsub(ipa, "d̪ʱ$", "d̪")
	ipa = gsub(ipa, "ɡʱ$", "ɡ")
	ipa = gsub(ipa, "kʰ$", "x")
	ipa = gsub(ipa, "ʈʰ$", "ʈ")
	ipa = gsub(ipa, "t͡ʃʰ$", "t͡ʃ")
	ipa = gsub(ipa, "tɕʰ$", "tɕ")
	ipa = gsub(ipa, "t̪ʰ$", "t̪")

	-- deaspiration before t̪
	ipa = gsub(ipa, "kʰt̪", "xt̪")

	-- regressive assimilation
	ipa = gsub(ipa, "kd͡ʒ", "ɡd͡ʒ")
	ipa = gsub(ipa, "kdʑ", "ɡdʑ")

	ipa = gsub(ipa, "b‿p", "pː")
	ipa = gsub(ipa, "d([ʱ?])‿t", "tː")
	ipa = gsub(ipa, "d͡ʒ([ʱ?])‿t͡ʃ", "t͡ʃː")
	ipa = gsub(ipa, "d̪([ʱ?])‿t̪", "t̪ː")
	ipa = gsub(ipa, "f‿b", "bː")
	ipa = gsub(ipa, "ɡ([ʱ?])‿k", "kː")
	ipa = gsub(ipa, "k([ʰ?])‿ɡ", "ɡː")
	ipa = gsub(ipa, "p‿b", "bː")
	ipa = gsub(ipa, "t([ʰ?])‿d", "dː")
	ipa = gsub(ipa, "t͡ʃ([ʰ?])‿dʒ", "dʒː")
	ipa = gsub(ipa, "t̪([ʰ?])‿d̪", "d̪ː")
	ipa = gsub(ipa, "v‿p", "pː")
	ipa = gsub(ipa, "sː([t̪d̪])", "s̪%1")

	ipa = gsub(ipa, "dʒ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "dʒʱ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "dʑ(‿?)([d̪t̪])", "z̪%2")
	ipa = gsub(ipa, "dʑʱ(‿?)([d̪t̪])", "z̪%2")

	ipa = gsub(ipa, "^(" .. consonants .. ")ɾ(" .. vowel .. ")(" .. consonants .. ")ɾ", "%1ɾ%2%3ː") -- R syncope
	ipa = gsub(ipa, "([ɖd̪ʈt̪])([lɾɹ])", "%1ː%2")

	-- intervocalic e̯
	ipa = gsub(ipa, "(" .. vowel .. ")‿(" .. vowel .. ")", "%1e̯%2")

	ipa = gsub(ipa, "‿", "")

	-- long vowels
	ipa = gsub(ipa, "^(" .. vowel .. ")(" .. consonants .. ")$", "%1ː%2")
	ipa = gsub(ipa, "^(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2ː")
	ipa = gsub(ipa, "^(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2%3ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2%3ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")$", "%1%2%3%4ː")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. ")(" .. consonants .. "ʱ)(" .. vowel .. ")$", "%1%2%3%4ː")
	ipa = gsub(ipa, "^(" .. consonants .. "ʰ?)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2ː%3")
	ipa = gsub(ipa, "^(" .. consonants .. "ʱ)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2ː%3")
	ipa = gsub(ipa, "^(" .. consonants .. ")(" .. consonants .. "ʰ?)(" .. vowel .. ")(" .. consonants .. ")$", "%1%2%3ː%4")

	-- half-long vowels
	ipa = gsub(ipa, "(" .. vowel .. ")$", "%1ˑ")
	ipa = gsub(ipa, "(" .. vowel .. ") ", "%1ˑ ")

	-- dental and retroflex laterals
	ipa = gsub(ipa, "l([t̪d̪])", "l̪%1")
	ipa = gsub(ipa, "l([ʈɖ])", "ɭ%1")

	-- dental and retroflex nasals
	ipa = gsub(ipa, "n([t̪d̪])", "n̪%1")
	ipa = gsub(ipa, "n̪([td])", "n%1")
	ipa = gsub(ipa, "n([ʈɖ])", "ɳ%1")

	-- dental and retroflex sibilants
	ipa = gsub(ipa, "s([t̪d̪])", "s̪%1")
	ipa = gsub(ipa, "([t̪d̪])s", "%1s̪")
	ipa = gsub(ipa, "s̪([td])", "s%1")
	ipa = gsub(ipa, "([td])s̪", "%1s")

	ipa = gsub(ipa, "z([t̪d̪])", "z̪%1")
	ipa = gsub(ipa, "([t̪d̪])z", "%1z̪")
	ipa = gsub(ipa, "z̪([td])", "z%1")
	ipa = gsub(ipa, "([td])z̪", "%1z")

	ipa = gsub(ipa, "ʃ([td])", "s%1")
	ipa = gsub(ipa, "ʃ([ʈɖ])", "ʂ%1")

	-- initial stress
	ipa = gsub(ipa, "^(" .. vowel .. ")", "ˈ%1")
	ipa = gsub(ipa, "^(" .. consonants .. ")", "ˈ%1")

	return ipa
end

local function vanga_narrow_IPA(ipa)
	local vowel = "[aiuoêɔɔ̃ɛeææ̃ãẽĩõũ]"
	local consonants = "[bβcdd̪ɸgɦjklmnprṛɾsśs̪ʃtt̪zz̪]"
	local implosives = {
	["bʱ"] = "ɓ", ["d̪ʱ"] = "ɗ̪", ["dʱ"] = "ɗ", ["dʒʱ"] = "ɗʒ", ["ɡʱ"] = "ɠ",
}

	ipa = gsub(ipa, "bʱ", "β")
	ipa = gsub(ipa, "^β", "bʱ")
	ipa = gsub(ipa, " β", " bʱ")

	-- lenition before dental
	ipa = gsub(ipa, "dʒ([d̪t̪])", "z̪%1")
	ipa = gsub(ipa, "dʒʱ([d̪t̪])", "z̪%1")

	-- word-final deaspiration
	ipa = gsub(ipa, "bʱ$", "b")
	ipa = gsub(ipa, "ɖʱ$", "ɖ")
	ipa = gsub(ipa, "dʒʱ$", "dʒ")
	ipa = gsub(ipa, "dʑʱ$", "dʑ")
	ipa = gsub(ipa, "d̪ʱ$", "d̪")
	ipa = gsub(ipa, "ɡʱ$", "ɡ")
	ipa = gsub(ipa, "kʰ$", "k")
	ipa = gsub(ipa, "pʰ$", "p")
	ipa = gsub(ipa, "ʈʰ$", "ʈ")
	ipa = gsub(ipa, "t͡ʃʰ$", "t͡ʃ")
	ipa = gsub(ipa, "tɕʰ$", "tɕ")
	ipa = gsub(ipa, "t̪ʰ$", "t̪")

	-- half-long vowels
	ipa = gsub(ipa, "(" .. vowel .. ")$", "%1ˑ")
	ipa = gsub(ipa, "(" .. vowel .. ") ", "%1ˑ ")

	-- replacing voiced aspirates with implosives
	ipa = gsub(ipa, "([bd̪dʒɡ]ʱ)", implosives)

	-- initial stress
	ipa = gsub(ipa, "^(" .. vowel .. ")", "ˈ%1")
	ipa = gsub(ipa, "^(" .. consonants .. ")", "ˈ%1")

	return ipa
end

local function eastern_vanga_narrow_IPA(ipa)
	local vowel = "[aiuoêɔɔ̃ɛeææ̃ãẽĩõũ]"
	local consonants = "[bβcdd̪fɸgɦjklmnprṛɾsśs̪ʃtt̪zz̪]"

	ipa = gsub(ipa, "bʱ", "β")
	ipa = gsub(ipa, "^β", "bʱ")
	ipa = gsub(ipa, " β", " bʱ")

	-- lenition before dental
	ipa = gsub(ipa, "dʒ([d̪t̪])", "z̪%1")
	ipa = gsub(ipa, "dʒʱ([d̪t̪])", "z̪%1")

	-- half-long vowels
	ipa = gsub(ipa, "(" .. vowel .. ")$", "%1ˑ")
	ipa = gsub(ipa, "(" .. vowel .. ") ", "%1ˑ ")

	-- replacing aspiration with tones
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)a", "%1%2á")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)i", "%1%2í")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)u", "%1%2ú")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)o", "%1%2ó")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)ɔ", "%1%2ɔ́")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)ɛ", "%1%2έ")
	ipa = gsub(ipa, "(" .. consonants .. ")ʰ(ː?)e", "%1%2é")

	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)a", "%1%2á")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)i", "%1%2í")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)u", "%1%2ú")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)o", "%1%2ó")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)ɔ", "%1%2ɔ́")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)ɛ", "%1%2έ")
	ipa = gsub(ipa, "(" .. consonants .. ")ʱ(ː?)e", "%1%2é")

	-- initial stress
	ipa = gsub(ipa, "^(" .. vowel .. ")", "ˈ%1")
	ipa = gsub(ipa, "^(" .. consonants .. ")", "ˈ%1")

	return ipa
end

-- Rarh
function export.make(frame)
	local args = frame:getParent().args
	local pagetitle = mw.title.getCurrentTitle().text

	local p, results = {}, {}, {}

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		p = { pagetitle }
	end

	for _, Bengali in ipairs(p) do
		local formal = export.toIPA(Bengali, "formal")
		local desanskritized = export.toIPA(Bengali, "desanskritized")
		local colloquial = export.toIPA(Bengali, "colloquial")
		table.insert(results, { pron = "/" .. formal .. "/" })
		local narrow = export.narrow_IPA(formal)
		table.insert(results, { pron = "[" .. narrow .. "]" })
		-- desanskritized
		if colloquial ~= desanskritized then if formal ~= desanskritized then table.insert(results, { pron = "/" .. desanskritized .. "/" })
			local desa_narrow = export.narrow_IPA(desanskritized)
			if desanskritized ~= desa_narrow then table.insert(results, { pron = "[" .. desa_narrow .. "]" }) end
		end end
		-- colloquial
		local col_narrow = colloquial_narrow_IPA(colloquial)
		if formal ~= colloquial then table.insert(results, { pron = "/" .. colloquial .. "/" })
			if colloquial ~= col_narrow then table.insert(results, { pron = "[" .. col_narrow .. "]" }) end
		else
			if narrow ~= col_narrow then table.insert(results, { pron = "[" .. col_narrow .. "]" }) end
		end
	end

	return  "* " ..  m_a.format_qualifiers(lang, {"ราฬฺ"}) .. " " .. m_IPA.format_IPA_full { lang = lang, items = results }
end

-- Dhaka
function export.make_dhaka(frame)
	local args = frame:getParent().args
	local pagetitle = mw.title.getCurrentTitle().text

	local p, results = {}, {}, {}

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		p = { pagetitle }
	end

	for _, Bengali in ipairs(p) do
		local dhaka = export.toIPA(Bengali, "dhaka")
		local colloquial = export.toIPA(Bengali, "dhaka_colloquial")
		table.insert(results, { pron = "/" .. dhaka .. "/" })
		local narrow = export.narrow_IPA(dhaka)
		table.insert(results, { pron = "[" .. narrow .. "]" })
		-- colloquial
		local col_narrow = colloquial_narrow_IPA(colloquial)
		if dhaka ~= colloquial then table.insert(results, { pron = "/" .. colloquial .. "/" })
			if colloquial ~= col_narrow then table.insert(results, { pron = "[" .. col_narrow .. "]" }) end
		else
			if narrow ~= col_narrow then table.insert(results, { pron = "[" .. col_narrow .. "]" }) end
		end
	end

	return m_a.format_qualifiers(lang, {"ฒากา"}) .. " " ..  m_IPA.format_IPA_full { lang = lang, items = results }
end

-- Vanga
function export.make_vanga(frame)
	local args = frame:getParent().args
	local pagetitle = mw.title.getCurrentTitle().text

	local p, results = {}, {}, {}

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		p = { pagetitle }
	end

	for _, Bengali in ipairs(p) do
		local vanga = export.toIPA(Bengali, "vanga")
		local eastern_vanga = export.toIPA(Bengali, "eastern_vanga")
		table.insert(results, { pron = "/" .. vanga .. "/" })
		local narrow = vanga_narrow_IPA(vanga)
		table.insert(results, { pron = "[" .. narrow .. "]" })
		local eastern_narrow = eastern_vanga_narrow_IPA(eastern_vanga)
		table.insert(results, { pron = "[" .. eastern_narrow .. "]" })
	end

	return m_a.format_qualifiers(lang, {"วังคะ"}) .. " " ..  m_IPA.format_IPA_full { lang = lang, items = results }
end

-- Eastern Vanga
function export.make_eastern_vanga(frame)
	local args = frame:getParent().args
	local pagetitle = mw.title.getCurrentTitle().text

	local p, results = {}, {}, {}

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		p = { pagetitle }
	end

	for _, Bengali in ipairs(p) do
		local vanga = export.toIPA(Bengali, "vanga")
		local eastern_vanga = export.toIPA(Bengali, "eastern_vanga")
		table.insert(results, { pron = "/" .. vanga .. "/" })
		local narrow = eastern_vanga_narrow_IPA(eastern_vanga)
		table.insert(results, { pron = "[" .. narrow .. "]" })
	end

	return m_a.format_qualifiers(lang, {"วังคะตะวันออก"}) .. " " ..  m_IPA.format_IPA_full { lang = lang, items = results }
end

-- Varendra
function export.make_varendra(frame)
	local args = frame:getParent().args
	local pagetitle = mw.title.getCurrentTitle().text

	local p, results = {}, {}, {}

	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
	else
		p = { pagetitle }
	end

	for _, Bengali in ipairs(p) do
		local varendra = export.toIPA(Bengali, "varendra")
		table.insert(results, { pron = "/" .. varendra .. "/" })
		local narrow = export.narrow_IPA(varendra)
		table.insert(results, { pron = "[" .. narrow .. "]" })
	end

	return m_a.format_qualifiers(lang, {"วเรนทระ"}) .. " " ..  m_IPA.format_IPA_full { lang = lang, items = results }
end

return export