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 == nil then
new_t = 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 ]
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 = {
= "ɪə",
= "eə",
= "aə",
= "ɔə",
= "ʊə",
= "ɑə",
= "əə",
},
SSB = {
= "ɪː",
= "ɛː",
= "ɑː",
= "oː",
= "ɵː", -- Really, this should be ɵwə → ɵː. There is not a change in vowel quality. ɵw was changed to ʉw to distinguish the phoneme from əw.
= "aː", -- This sound is not considered a phoneme by Lindsey, so is not found in the lexical set list above.
= "əː",
}
}
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 or system
if not systems then
error("No system called " .. system " is found in ].")
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)
local to_table = systems
local i = 1
while i <= length do
local char, chars = usub(text, i, i), usub(text, i, i + 1)
if from_table then
table.insert(output, to_table])
i = i + 2
else
table.insert(output, to_table] 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) 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 '<span class="IPA">' .. IPA_transcription .. '</span>'
end
local function get_compare_value(IPA)
return (IPA:gsub("*", 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 = rows or {}
table.insert(rows, tag(IPA))
table.insert(rows, table.concat(tsort(keywords), ", "))
end
local output = {}
for i, cells in ipairs(rows) do
output = 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 then
local keywords_by_IPA = {}
collection = keywords_by_IPA
for keyword, IPA in pairs(lexical_sets) do
keywords_by_IPA = keywords_by_IPA or {}
table.insert(keywords_by_IPA, keyword)
end
end
already_seen = 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 = v
end
for k, v in pairs(t2) do
if t == nil then
t = v
else
error("Table 1 has a value for " .. k .. ".")
end
end
return t
end
local labels = {
RP = "]",
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 or args) then
args = export.convert(args, provided_system, system)
end
already_seen = true
end
local output = {}
local i = 0
for code, transcription in pairs(args) do
i = i + 1
output = "* " .. (labels or code) .. ": " .. tag("/" .. transcription .. "/")
end
return table.concat(output, "\n")
end
return export