Bengali IPA pronunciation module. See {{bn-IPA}}.

Testcases

Module:bn-IPA/testcases:

17 of 35 tests failed. (refresh)

TextExpectedActualComments
test_all:
Failedব্রাহ্মণ (brahmon)bɾamɦónbɾamhón
Failedউত্তর (uttor)ut̪ːóɾut̪ːɔɾ
Passedঅ্যান্টার্কটিকা (ênṭarkṭika)ænʈaɾkʈikaænʈaɾkʈika
Passedব্যায়াম (bêẏam)bæambæam
Passedদেশ (deś)d̪eʃd̪eʃ
Failedমধু (modhu)mód̪ʱumɔd̪ʱu
Passedআমার (amar)amaɾamaɾ
Failedখেলনা (khelna)kʰælnakʰelna
Failedবিবাহ (bibaho)bibaɦóbibahó
Passedগম (gom)ɡɔmɡɔm
Failedখরগোশ (khorgōś)kʰɔɾɡóʃkʰɔɾɡoʃ
Passedমুক্ত (mukto)mukt̪ómukt̪ó
Passedমিঞা (mĩa)mĩamĩa
Passedশাস্ত্র (śastro)ʃast̪ɾóʃast̪ɾó
Passedত্বক (tok)t̪ɔkt̪ɔk
Passedঅন্বেষণ (onneśon)ɔnːeʃɔnɔnːeʃɔn
Passedশ্রাবণ (srabon)sɾabónsɾabón
Passedভাই (bhai)bʱai̯bʱai̯
Passedদৃষ্টি (driśṭi)d̪ɾiʃʈid̪ɾiʃʈi
Failedশক্তি (śokti)ʃokt̪iʃɔkt̪i
Passedওস্তাদ (ōstad)ost̪ad̪ost̪ad̪
Failedপঙ্কজ (poṅkoj)pɔŋkodʒpɔŋkɔd͡ʒ
Passedদেওয়াল (deōẇal)d̪eo̯ald̪eo̯al
Passedনিবৃত্ত (nibritto)nibɾit̪ːónibɾit̪ːó
Failedমৃত্যুঞ্জয় (mrittunjoẏ)mɾit̪ːundʒɔe̯mɾit̪ːund͡ʒɔe̯
Failedগর্ভপাত (gorbhopat)ɡɔɾbʱópat̪ɡɔɾbʱɔpat̪
Passedগর্ভ (gorbho)ɡɔɾbʱóɡɔɾbʱó
Failedযক্ষ্মা (jokkha)dʒɔkʰːad͡ʒɔkʰːa
Failedরক্ষা (rokkha)rókʰːarɔkʰːa
Passedসংখ্যা (śoṅkha)ʃɔŋkʰaʃɔŋkʰa
Failedসবজি (śoboji)ʃóbdʒiʃɔbód͡ʒi
Failedইনফ্লুয়েঞ্জা (inphluẏenja)influ̯endʒainflu̯end͡ʒa
Failedপশ্চিমবঙ্গ (pościmboṅgo)póʃtʃimbɔŋɡópɔʃt͡ʃimbɔŋɡó
Failedনয়ন (noẏon)nɔe̯ónnɔe̯on
Failedজিহ্বা (jiubha)dʒiu̯bʱad͡ʒiu̯bʱa

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))
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, {"Rarh"}) .. " " .. 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, {"Dhaka"}) .. " " ..  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, {"Vanga"}) .. " " ..  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, {"Eastern Vanga"}) .. " " ..  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, {"Varendra"}) .. " " ..  m_IPA.format_IPA_full { lang = lang, items = results }
end

return export