Мазмунга өтүү

Модуль:ky-decl

Wiktionary долбоорунан

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