Модуль:ky-decl
Көрүнүш
Documentation for this module may be created at Модуль:ky-decl/doc
local p = {}
-- ====== UI styles (можно вынести в общий модуль позже) ======
local h_bg = '#DEDEDE'
local t_bg = '#F9F9F9'
local b_color = '#aaaaaa'
local i_border = '1px solid #ffffff'
local function make_link(term, display)
local target = mw.ustring.lower(term)
local text = display or target
return "[[" .. target .. "|" .. text .. "]]"
end
local function wrap_box(title, content)
local res = '\n<div class="mw-collapsible mw-collapsed" style="width:65%; border:1px solid ' .. b_color .. '; margin-top:10px; font-size:95%; font-family: sans-serif;">'
res = res .. '<div style="background:#eeeeee; padding:4px 10px; font-weight:bold; text-align:left; border-bottom:1px solid ' .. b_color .. ';">' .. title .. '</div>'
res = res .. '<div class="mw-collapsible-content" style="background:' .. t_bg .. ';">\n'
res = res .. '{| style="width:100%; text-align:center; border-collapse:collapse; background:' .. t_bg .. '; table-layout: fixed;"\n' .. content .. '\n|}\n'
res = res .. '</div>\n</div>'
return res
end
-- ====== helpers ======
local VOWELS = "аеёиоуүөыэюяи"
local function is_vowel(ch)
return mw.ustring.find(VOWELS, ch, 1, true) ~= nil
end
-- 4-класстуу үндөшүү:
-- back unrounded: а, ы, я -> A
-- back rounded: о, у, ё, ю -> O
-- front unrounded: е, и, э -> E
-- front rounded: ө, ү -> Ö
local function harmony4(word)
local map = {
['а']='A',['ы']='A',['я']='A',
['о']='O',['у']='O',['ё']='O',['ю']='O',
['е']='E',['и']='E',['э']='E',
['ө']='Ö',['ү']='Ö'
}
for i = mw.ustring.len(word), 1, -1 do
local ch = mw.ustring.sub(word, i, i)
if map[ch] then return map[ch] end
end
return 'A'
end
local function low_vowel(h) -- а/о/е/ө
local m = { A='а', O='о', E='е', ['Ö']='ө' }
return m[h] or 'а'
end
local function high_vowel(h) -- ы/у/и/ү
local m = { A='ы', O='у', E='и', ['Ö']='ү' }
return m[h] or 'ы'
end
local function last_char(word)
return mw.ustring.sub(word, -1)
end
-- глухие для выбора т/к
local VOICELESS = "пкстшфхцчщ"
local VOICED = "бвгджзлмнң"
local SONORANT = "рй"
local function in_set(set, ch)
return mw.ustring.find(set, ch, 1, true) ~= nil
end
-- Префикс суффикса (первый согласный) для разных категорий
local function prefix_for(word, kind)
local last = last_char(word)
local v = is_vowel(last)
if kind == "pl" then
if v then return "л" end
if in_set(VOICELESS, last) then return "т" end
if in_set(VOICED, last) then return "д" end
return "л"
end
if kind == "gen" or kind == "acc" then
if v then return "н" end
if in_set(VOICELESS, last) then return "т" end
if in_set(VOICED, last) or in_set(SONORANT, last) then return "д" end
return "д"
end
if kind == "dat" then
if v then return "г" end
return in_set(VOICELESS, last) and "к" or "г"
end
if kind == "loc" or kind == "abl" then
if v then return "д" end
return in_set(VOICELESS, last) and "т" or "д"
end
return ""
end
-- суффикс по падежу (без основы)
local function suffix_for(word, kind)
local h = harmony4(word)
local a = low_vowel(h)
local i = high_vowel(h)
local pfx = prefix_for(word, kind)
if kind == "nom" then return "" end
if kind == "pl" then
-- стандартное: -лар/-лер/-лор/-лөр (через pfx + low + р)
return pfx .. a .. "р"
end
if kind == "gen" then
-- -нын/-нин/-тун/-тин ... => pfx + i + н
return pfx .. i .. "н"
end
if kind == "acc" then
-- -ны/-ни/-ту/-ти ... => pfx + i
return pfx .. i
end
if kind == "dat" then
-- -га/-ге/-го/-гө ... => pfx + a
return pfx .. a
end
if kind == "loc" then
-- -да/-де/-до/-дө ... => pfx + a
return pfx .. a
end
if kind == "abl" then
-- -дан/-ден/-дон/-дөн ... => pfx + a + н
return pfx .. a .. "н"
end
return ""
end
local function apply(word, kind)
-- исключения множественного (можно расширять)
if kind == "pl" and word == "бала" then return "балдар" end
return word .. suffix_for(word, kind)
end
function p.make_forms(word)
local forms = {}
forms.nom = word
forms.pl = apply(word, "pl")
forms.gen = apply(word, "gen")
forms.dat = apply(word, "dat")
forms.acc = apply(word, "acc")
forms.loc = apply(word, "loc")
forms.abl = apply(word, "abl")
return forms
end
function p.render_table(frame)
local args = frame.args
if frame:getParent() then
-- чтобы можно было вызывать и напрямую, и из шаблона
for k,v in pairs(frame:getParent().args) do
if args[k] == nil or args[k] == "" then args[k] = v end
end
end
local word = args['сөз'] or args['word'] or mw.title.getCurrentTitle().text
word = mw.ustring.gsub(word, "^.-:", "")
word = mw.ustring.gsub(word, "^.*/", "")
local forms = p.make_forms(word)
local plural = (args['көп'] and args['көп'] ~= "") and args['көп'] or forms.pl
local content = '|-\n'
content = content .. '! style="width:20%; background:' .. h_bg .. '; border:' .. i_border .. ';" | \n'
content = content .. '! style="width:40%; background:' .. h_bg .. '; border:' .. i_border .. '; padding:2px;" | ' .. make_link("жекелик") .. '\n'
content = content .. '! style="width:40%; background:' .. h_bg .. '; border:' .. i_border .. '; padding:2px;" | ' .. make_link("көптүк") .. '\n'
local cases = {
{"Атооч","nom"},
{"Илик","gen"},
{"Барыш","dat"},
{"Табыш","acc"},
{"Жатыш","loc"},
{"Чыгыш","abl"}
}
for _, c in ipairs(cases) do
local sg = (c[2] == "nom") and word or apply(word, c[2])
local plv = (c[2] == "nom") and plural or (plural .. suffix_for(plural, c[2]))
content = content .. "|-\n"
content = content .. "! style=\"background:" .. h_bg .. "; border:" .. i_border .. "; padding:2px;\" | " .. make_link(c[1]) .. "\n"
content = content .. "| style=\"border:" .. i_border .. "; padding:2px;\" | " .. sg .. "\n"
content = content .. "| style=\"border:" .. i_border .. "; padding:2px;\" | " .. plv .. "\n"
end
return wrap_box(word .. " сөзүнүн [[жөндөлүш|жөндөлүшү]]", content)
end
return p