This module implements the {{haw-IPA}}
template.
local export = {}
local m_str_utils = require("Module:string utilities")
local decomp = mw.ustring.toNFD
local find = m_str_utils.find
local gmatch = m_str_utils.gmatch
local gsub = m_str_utils.gsub
local len = m_str_utils.len
local lower = m_str_utils.lower
local sub = m_str_utils.sub
local lang = require("Module:languages").getByCode("haw")
local ipa = require("Module:IPA")
local U = require("Module:string/char")
local breve = U(0x032F)
local macron = U(0x0304)
local cons = "bcdfghklmnpqrstvwzʻ"
local vowels = "aeiouāēīōū"
local diphs = {
"āi", "āe", "āo", "āu", "ēi", "ōu",
"ae", "ai", "ao", "au", "ei", "eu", "iu", "ou", "oi"
}
local respell = {
= "k",
= "p",
= "l",
= "w"
}
local stressed = "ˈˌ"
local boundary = "%.ˈˌ%+-"
-- syllabify word
local function syllabify(word)
-- mark diphthongs with brackets
for _, diph in ipairs(diphs) do
word = gsub(word, diph, "{" .. diph .. "}")
end
-- split between vowels and consonants
word = gsub(word, "()()", "%1.%2")
-- remove diphthong brackets and any dots inside them
word = gsub(word, "{*}", function(a) return gsub(a, "", "") end)
-- syllables that end in consonants are invalid
if find(word, "$") then
error("One of the entries has an invalid Hawaiian syllable structure.")
end
return word
end
local function stress(word)
-- decompose macrons from vowels
word = decomp(word)
-- stress the last vowel if it has a macron, second last otherwise
local stress_vowel_pos = len(gsub(word, "", "")) + (find(word, macron .. "$") and 1 or 0)
-- add stressed vowel at given position
word = gsub(word, "()", function(v)
stress_vowel_pos = stress_vowel_pos - 1
return (stress_vowel_pos == 1) and 'ˈ' .. v or v
end)
-- shift stress mark before space or syllable boundary
return gsub(word, "(*)ˈ", "ˈ%1")
end
-- generate pronunciation of words
function export.toIPA(entry, is_phonetic)
if type(entry) == "table" then
entry = table.concat(entry)
end
-- make entry lowercase
entry = lower(entry)
-- validate characters
if not find(entry, "") then
error("Invalid characters. Only valid Hawaiian letters, spaces and symbols '+' and '-' are accepted.")
end
-- syllabify entry
entry = syllabify(entry)
-- syllabify and stress entry
local result = ""
for segment in gmatch(syllabify(entry), "+?") do
-- apply stress to each segment
segment = stress(segment)
-- convert to secondary stress if part of compound
if find(segment, "") then
segment = gsub(segment, "ˈ", "ˌ"):gsub("", ".")
end
result = result .. segment
end
-- remove syllable boundaries before stress
result = gsub(result, "%.()", "%1")
-- mark long vowels
result = gsub(result, macron, "ː")
-- mark diphthongised vowels
result = gsub(result, "()iu", "%1i" .. breve .. "u"):gsub("()oi", "%1o" .. breve .. "i")
result = gsub(result, "(ː?)", "%1" .. breve)
-- replace respellt consonants
for k, v in pairs(respell) do
result = gsub(result, "", v)
end
-- real value of glottal stop
result = gsub(result, "ʻ", "ʔ")
-- phonetic transcriptions
if is_phonetic then
-- allophony of /k/ before /i/
result = gsub(result, "ki", "ti")
-- real pronunciation of /w/
result = gsub(result, "w", "ʋ")
-- allophony of glides /j/, /w/
result = gsub(result, "(" .. breve .. "?)()", "%1j%2")
result = gsub(result, "(" .. breve .. "?)()", "%1w%2")
-- actual pronunciation of diphthongs
result = gsub(result, "i" .. breve, "j")
result = gsub(result, "u" .. breve, "w")
-- allophony of /a/
result = gsub(result, "(?)a", "%1ɐ")
result = gsub(result, "a", "ə")
result = gsub(result, "ː", "aː")
-- allophony of /e/
result = gsub(result, "(?)e", "%1ɛ")
result = gsub(result, "e(*)ɛ", "ɛ%1ɛ")
result = gsub(result, "ɛ(*)e", "ɛ%1ɛ")
result = gsub(result, "ɛː", "eː")
end
return result
end
-- rapid pronunciation of diphthongs
function export.rapid(entry)
return gsub(entry, "ɐj", "ɛj"):gsub("ɐw", "ɔw")
end
-- display pronunciation
function export.show(frame)
local args = frame:getParent().args
local pagetitle = mw.title.getCurrentTitle().text
local p, results = {}, {}
if args then
for _, v in ipairs(args) do
table.insert(p, (v ~= "") and v or nil)
end
else
p = { pagetitle }
end
for _, word in ipairs(p) do
local phonemic = export.toIPA(word, false)
local phonetic = export.toIPA(word, true)
local rapid = export.rapid(phonetic)
table.insert(results, { pron = "/" .. phonemic .. "/" })
if phonemic ~= phonetic then table.insert(results, { pron = "" }) end
if phonetic ~= rapid then table.insert(results, { pron = "", qq = {"rapid speech"} }) end
end
return ipa.format_IPA_full { lang = lang, items = results }
end
return export