Module:User:Erutuon/en-pronunciation

local export = {}

local fun = require "Module:fun"

local usub = mw.ustring.sub local ulen = mw.ustring.len

local function tsort(t) table.sort(t) return t end

-- Reverses key–value pairs. Assumes two keys do not have the same value. If -- they do, the first encountered value will be used as a key. local function invert(t) local new_t = {} for k, v in pairs(t) do		if new_t[v] == nil then new_t[v] = k		end end return new_t end

local sort_value = { ["ɑ"] = "a", ["ɒ"] = "a", ["æ"] = "a", ["ɜ"] = "e", ["ʌ"] = "e", ["ə"] = "e", ["ɪ"] = "i", ["ɔ"] = "o", ["ʊ"] = "u", ["ɵ"] = "u", ["ʉ"] = "u", -- ʉ stands in for ɵ }

local aliases = { Lindsey = "SSB", }

local systems = { RP = { -- from Lexical set kit = "ɪ", dress = "e", trap = "æ", lot = "ɒ", strut = "ʌ", foot = "ʊ", palm = "ɑː", bath = "ɑː", nurse = "ɜː", fleece = "iː", face = "eɪ", thought = "ɔː", goat = "əʊ", goose = "uː", price = "aɪ", choice = "ɔɪ", mouth = "aʊ", near = "ɪə", square = "eə", start = "ɑː", north = "ɔː", force = "ɔː", cure = "ʊə", happy = "i", letter = "ə", comma = "ə", },	SSB = { -- from http://englishspeechservices.com/blog/bre-vowel-symbols/ kit = "ɪ", fleece = "ɪj", happy = "ɪj", near = "ɪː", trap = "a", price = "ɑj", mouth = "aw", palm = "ɑː", start = "ɑː", bath = "ɑː", lot = "ɔ", choice = "oj", thought = "oː", north = "oː", force = "oː", strut = "ʌ", letter = "ə", comma = "ə", goat = "əw", nurse = "əː", foot = "ɵ", goose = "ʉw", cure = "ɵː", -- also oː, ʉwə dress = "ɛ", face = "ɛj", square = "ɛː", } }

-- http://englishspeechservices.com/blog/smoothing-then-and-now/ -- Key changes to value. Schwa is omitted: iː and ɪj mean iːə and ɪjə. local smoothing = { RP = { ["iː"] = "ɪə", ["eɪ"] = "eə", ["aɪ"] = "aə", ["ɔɪ"] = "ɔə", ["uː"] = "ʊə", ["ɑʊ"] = "ɑə", ["əʊ"] = "əə", },	SSB = { ["ɪj"] = "ɪː", ["ɛj"] = "ɛː", ["ɑj"] = "ɑː", ["oj"] = "oː", ["ʉw"] = "ɵː", -- Really, this should be ɵwə → ɵː. There is not a change in vowel quality. ɵw was changed to ʉw to distinguish the phoneme from əw. ["aw"] = "aː", -- This sound is not considered a phoneme by Lindsey, so is not found in the lexical set list above. ["əw"] = "əː", } }

local shortcuts = { SSB = { -- CUBE: capitalized vowel means stress a = "a",	e = "ɛ",	y = "ʌ",	i = "ɪ",	o = "ɔ",	u = "ɵ",	x = "ə", aj = "ɑj",	ej = "ɛj",				ij = "ɪ",	oj = "ɔj", aJ = "ɑj",	eJ = "ɛj",				iJ = "ɪ",	oJ = "ɔj", -- CUBE yw = "əw", aw = "aw",				ew = "əw",							uw = "ʉw", yW = "əw",							-- CUBE; which to use? aW = "aw",				eW = "əw",							uW = "ʉw", aa = "ɑː",	ee = "ɛː",	yy = "əː",	ii = "ɪː",	oo = "oː",	uu = "ɵː", aH = "ɑː",	eH = "ɛː",	yH = "əː",	iH = "ɪː",	oH = "oː",	uH = "ɵː", -- CUBE; which to use? T = "θ",	S = "ʃ",	C = "tʃ",	N = "ŋ",	-- CUBE D = "ð",	Z = "ʒ",	G = "dʒ", },	RP = { a = "æ",	e = "e",	i = "i",	o = "ɒ",	u = "u",	y = "ʌ",	x = "ə", I = "ɪ",				u = "ʊ", au = "aʊ",	eu = "əʊ",				ou = "ɒʊ",	-- "ɑʊ"? ai = "aɪ",	ei = "eɪ",				oi = "ɔɪ", ae = "ɑə",	ee = "eə",	ie = "ɪə",	oe = "ɔə",	ue = "ʊə", ay = "ɑə",	ey = "eə",	iy = "ɪə",	oy = "ɔə",	uy = "ʊə",	-- which to use? --	archaic		or "ɛə"? archaic aa = "ɑː",				ii = "iː",	oo = "ɔː",	uu = "uː", aH = "ɑː",				iH = "iː",	oH = "ɔː",	uH = "uː",	yH = "ɜː",	-- CUBEish; which to use? T = "θ",	S = "ʃ",	C = "tʃ",	N = "ŋ",	-- CUBE D = "ð",	Z = "ʒ",	G = "dʒ", }, }

local function validate_system(system) system = aliases[system] or system if not systems[system] then error("No system called " .. system " is found in Module:User:Erutuon/en-pronunciation.") end return system end

function export.convert(text, from, to) from = validate_system(from) to = validate_system(to) local output = {} local length = ulen(text) local from_table = invert(systems[from]) local to_table = systems[to] local i = 1 while i <= length do		local char, chars = usub(text, i, i), usub(text, i, i + 1) if from_table[chars] then table.insert(output, to_table[from_table[chars]]) i = i + 2 else table.insert(output, to_table[from_table[char]] or char) i = i + 1 end end return table.concat(output) end

function export.smooth(word, system) system = validate_system(system) -- Naive and inefficient method. for vowel_preceding_schwa, smoothed in pairs(smoothing[system]) do word = word:gsub(vowel_preceding_schwa .. "%.?ə", smoothed) end return word end

local function make_row(cells) -- | cell1 || cell2 || cell3 ... return table.concat(		fun.map( function(cell) return "| " .. cell end, cells),		" |") end local function tag(IPA_transcription) return ' ' .. IPA_transcription .. ' ' end

local function get_compare_value(IPA) return (IPA:gsub("[%z\1-\127\194-\244][\128-\191]*", sort_value)) end

local function compare(IPA1, IPA2) return get_compare_value(IPA1) < get_compare_value(IPA2) end

local function make_IPA_keyword_table(IPA_keyword_data) local rows = {} local i = 0 -- local column_length = math.floor((require "Module:table".size(IPA_keyword_data) + 2) / 2) for IPA, keywords in require "Module:table".sortedPairs(IPA_keyword_data, compare) do		i = i + 1 if column_length and i == column_length then i = 1 end rows[i] = rows[i] or {} table.insert(rows[i], tag(IPA)) table.insert(rows[i], table.concat(tsort(keywords), ", ")) end local output = {} for i, cells in ipairs(rows) do		output[i] = make_row(cells) end return table.concat(output, "\n|-\n") end

function export.show(frame) --	local output = fun.map(		function(lexical_sets, system_name)			return fun.map(				function(IPA, keyword)				end,				lexical_sets)		end,		systems)	-- local collection = {} local already_seen = {} for system, lexical_sets in pairs(systems) do		if not already_seen[lexical_sets] then local keywords_by_IPA = {} collection[system] = keywords_by_IPA for keyword, IPA in pairs(lexical_sets) do				keywords_by_IPA[IPA] = keywords_by_IPA[IPA] or {} table.insert(keywords_by_IPA[IPA], keyword) end end already_seen[lexical_sets] = true end local output = { '{| class="wikitable"', "! IPA !! keyword" } for system, keywords_by_IPA in pairs(collection) do table.insert(output, '|-\n! colspan="2" | ' .. system .. "\n|-") table.insert(output, make_IPA_keyword_table(keywords_by_IPA)) end table.insert(output, "|}") return table.concat(output, "\n") end

local function merge(t1, t2) local t = {} for k, v in pairs(t1) do		t[k] = v	end for k, v in pairs(t2) do		if t[k] == nil then t[k] = v		else error("Table 1 has a value for " .. k .. ".") end end return t end

local labels = { RP = "Received Pronunciation", SSB = "Standard Southern British", -- probably not notable enough for a Wikipedia article yet }

function export.template(frame) local params = { RP = {}, SSB = {}, }	local args = require("Module:parameters").process(merge(frame.args, frame:getParent.args), params) local provided_system = next(args) local already_seen = {} for system, lexical_sets in pairs(systems) do		if not (already_seen[lexical_sets] or args[system]) then args[system] = export.convert(args[provided_system], provided_system, system) end already_seen[lexical_sets] = true end local output = {} local i = 0 for code, transcription in pairs(args) do		i = i + 1 output[i] = "* " .. (labels[code] or code) .. ": " .. tag("/" .. transcription .. "/") end return table.concat(output, "\n") end

return export