모듈:ja-verbconj

이 모듈에 대한 설명문서는 모듈:ja-verbconj/설명문서에서 만들 수 있습니다

local export = {}

local ulen = mw.ustring.len
local usub = mw.ustring.sub
local umatch = mw.ustring.match
local ugmatch = mw.ustring.gmatch
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local concat = table.concat
local range = require("Module:ja/data/range")

local function kana_to_romaji(kana)
    local tr = require("Module:Hrkt-translit").tr
    return tr(kana, "ja")
end

local function extract_stem(kana)
    return usub(kana, 1, -2)
end

local function contains_kanji(word)
    return umatch(word, "[" .. range.kanji .. "]") ~= nil
end

local function determine_suru_type(stem, lemma)
    -- Get the current page title, which serves as the headword
    local page_title = mw.title.getCurrentTitle().text
    
    -- Check if the page title contains "ずる"
    if page_title:find("ずる") then
        return "zuru"
    end

    -- Determine the type based on the presence of "する" or the stem's last character
    local last_char = usub(stem, -1)
    if last_char == "っ" then
        return "suru-tsu"
    elseif umatch(last_char, "[いきしちにひみりく]") then
        return "suru-i-ku"
    else
        return "suru"
    end
end

local function format_row(label, lemma, stem_kana, ending, is_suru, kana_only, suru_type)
    local ending_parts = mw.text.split(ending, "<br>")
    
    local kana_full = {}
    local romaji_full = {}
    local lemma_combined = {}

    for _, part in ipairs(ending_parts) do
        local full_kana = stem_kana .. part
        table.insert(kana_full, full_kana)
        local part_romaji = kana_to_romaji(full_kana)
        table.insert(romaji_full, part_romaji)
        if is_suru then
            table.insert(lemma_combined, lemma .. part)
        else
            table.insert(lemma_combined, usub(lemma, 1, -2) .. part)
        end
    end

    local kana_combined = table.concat(kana_full, "<br>")
    local romaji_combined = table.concat(romaji_full, "<br>")
    local lemma_combined_str = table.concat(lemma_combined, "<br>")
    
    -- 일본어 텍스트 부분에만 글씨 크기 120% 적용
    kana_combined = kana_combined:gsub("([^\n]*)", '<span style="font-size: 120%;">%1</span>')
    lemma_combined_str = lemma_combined_str:gsub("([^\n]*)", '<span style="font-size: 120%;">%1</span>')

    -- 명령형 포함 모든 로마자 표기에서 위첨자 부분만 이탤릭체 제거
    romaji_combined = romaji_combined:gsub("<i>(.-)</i>", function(text)
        return text:gsub("(.)<sup>(%d+)</sup>", "<i>%1</i><sup>%2</sup>")
    end)
    
    if label:match("명령형") then
        if suru_type == "suru-tsu" then
        	lemma_combined_str = lemma_combined_str:gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            kana_combined = kana_combined:gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            romaji_combined = romaji_combined:gsub("seyo", "<i>seyo</i><sup>1</sup>"):gsub("shiro", "<i>shiro</i><sup>2</sup>")
        elseif suru_type == "zuru" then
        	lemma_combined_str = lemma_combined_str:gsub("ぜよ", "ぜよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("じろ", "じろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            kana_combined = kana_combined:gsub("ぜよ", "ぜよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("じろ", "じろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            romaji_combined = romaji_combined:gsub("zeyo", "<i>zeyo</i><sup>1</sup>"):gsub("jiro", "<i>jiro</i><sup>2</sup>")
        elseif suru_type == "suru-i-ku" then
        	lemma_combined_str = lemma_combined_str:gsub("せ([^よ])", "せ</span><sup>1</sup><span style=\"font-size: 120%\">%1"):gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            kana_combined = kana_combined:gsub("せ([^よ])", "せ</span><sup>1</sup><span style=\"font-size: 120%\">%1"):gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            romaji_combined = romaji_combined:gsub("se([^yo])", "<i>se</i><sup>1</sup>%1"):gsub("seyo", "<i>seyo</i><sup>1</sup>"):gsub("shiro", "<i>shiro</i><sup>2</sup>")
        elseif suru_type == "suru" then
        	lemma_combined_str = lemma_combined_str:gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            kana_combined = kana_combined:gsub("せよ", "せよ</span><sup>1</sup><span style=\"font-size: 120%\">"):gsub("しろ", "しろ</span><sup>2</sup><span style=\"font-size: 120%\">")
            romaji_combined = romaji_combined:gsub("seyo", "<i>seyo</i><sup>1</sup>"):gsub("shiro", "<i>shiro</i><sup>2</sup>")
        end
    end
    
    if kana_only then
        return string.format([[
|-
! style="width: 25%%;" | %s
| style="width: 37.5%%;" | <span class="Jpan" lang="ja-Jpan">%s</span>
| style="width: 37.5%%;" | <i><span class="Latn" lang="ja-Latn">%s</span></i>
]], label, kana_combined, romaji_combined)
    else
        return string.format([[
|-
! style="width: 25%%;" | %s
| style="width: 25%%;" | <span class="Jpan" lang="ja-Jpan">%s</span>
| style="width: 25%%;" | <span class="Jpan" lang="ja-Jpan">%s</span>
| style="width: 25%%;" | <i><span class="Latn" lang="ja-Latn">%s</span></i>
]], label, lemma_combined_str, kana_combined, romaji_combined)
    end
end

local function generate_suru_table(lemma, kana, romaji, kana_only, is_kanji_suru)
    local stem_kana
    if kana_only then
        stem_kana = kana
    elseif is_kanji_suru then
        stem_kana = kana  -- 잘리지 않도록 설정
    else
        stem_kana = usub(kana, 1, -3)
    end
    local suru_type = determine_suru_type(stem_kana, lemma)

    -- Correctly display lemma for different suru types
    local display_lemma
    if suru_type == "zuru" then
        display_lemma = lemma .. "ずる"
    else
        display_lemma = lemma .. "する"
    end

    local endings

    if suru_type == "suru-tsu" then
        endings = {
            mi = "せ<br>し", yo = "し", shu = "する", ren = "する", ka = "すれ", me = "せよ<br>しろ",
            pass = "せられる<br>しられる", caus = "しさせる<br>しさす", pot = "せられる<br>しられる",
            vol = "しよう", neg = "しない", cont_neg = "せず", polite = "します", past = "した",
            te = "して", conditional = "すれば"
        }
    elseif suru_type == "zuru" then
        endings = {
            mi = "じ<br>ぜ", yo = "じ", shu = "ずる", ren = "ずる", ka = "ずれ", me = "ぜよ<br>じろ",
            pass = "じられる<br>ぜられる", caus = "じさせる<br>じさす", pot = "じられる<br>ぜられる", vol = "じよう",
            neg = "じない", cont_neg = "ぜず", polite = "じます", past = "じた",
            te = "じて", conditional = "ずれば"
        }
    elseif suru_type == "suru-i-ku" then
        endings = {
            mi = "さ<br>し", yo = "し", shu = "する", ren = "する", ka = "すれ", me = "せ<br>せよ<br>しろ",
            pass = "される", caus = "させる<br>さす", pot = "せる", vol = "そう<br>しよう",
            neg = "さない<br>しない", cont_neg = "さず", polite = "します", past = "した",
            te = "して", conditional = "すれば<br>せば"
        }
    else
        endings = {
            mi = "し", yo = "し", shu = "する", ren = "する", ka = "すれ", me = "せよ<br>しろ",
            pass = "される", caus = "させる<br>さす", pot = "できる", vol = "しよう",
            neg = "しない", cont_neg = "せず", polite = "します", past = "した",
            te = "して", conditional = "すれば"
        }
    end

    local rows = {
        format_row('미연형(<span lang="ja" class="Jpan">未然形</span>)', lemma, stem_kana, endings.mi, true, kana_only, suru_type),
        format_row('연용형(<span lang="ja" class="Jpan">連用形</span>)', lemma, stem_kana, endings.yo, true, kana_only, suru_type),
        format_row('종지형(<span lang="ja" class="Jpan">終止形</span>)', lemma, stem_kana, endings.shu, true, kana_only, suru_type),
        format_row('연체형(<span lang="ja" class="Jpan">連体形</span>)', lemma, stem_kana, endings.ren, true, kana_only, suru_type),
        format_row('가정형(<span lang="ja" class="Jpan">仮定形</span>)', lemma, stem_kana, endings.ka, true, kana_only, suru_type),
        format_row('명령형(<span lang="ja" class="Jpan">命令形</span>)', lemma, stem_kana, endings.me, true, kana_only, suru_type)
    }

    local core_expressions = {
        format_row('수동형', lemma, stem_kana, endings.pass, true, kana_only, suru_type),
        format_row('사역형', lemma, stem_kana, endings.caus, true, kana_only, suru_type),
        format_row('가능형', lemma, stem_kana, endings.pot, true, kana_only, suru_type),
        format_row('의지 · 권유형', lemma, stem_kana, endings.vol, true, kana_only, suru_type),
        format_row('부정형', lemma, stem_kana, endings.neg, true, kana_only, suru_type),
        format_row('지속 부정형', lemma, stem_kana, endings.cont_neg, true, kana_only, suru_type),
        format_row('경어체', lemma, stem_kana, endings.polite, true, kana_only, suru_type),
        format_row('과거형', lemma, stem_kana, endings.past, true, kana_only, suru_type),
        format_row('접속형(て형)', lemma, stem_kana, endings.te, true, kana_only, suru_type),
        format_row('가정형', lemma, stem_kana, endings.conditional, true, kana_only, suru_type)
    }

    local table_headers = kana_only and "! colspan=\"3\" | " or "! colspan=\"4\" | "
    local table_template = [=[
<div class="NavFrame" style="border:0px;">
<div class="NavHead" align="left" style="font-weight:bold; border:1px solid darkgrey; margin-left:-1px; background-color: var(--nav-head-background, #EAECF0); color: var(--nav-head-text-color, #000000);"><span class="Jpan" lang="ja-Jpan" style="font-size:120%%;">"%s"</span>의 동사 활용 ([[부록:일본어 동사|부록:일본어 동사]])</div>
<div class="NavContent" style="font-size:105%%;">
{| class="wikitable" style="margin-top: 0; text-align: center; width: 100%%; color: var(--table-text-color, #000000); background: var(--table-background-color, #FFFFFF);" rules="all"
%s어간 형태
%s
|-
%s핵심 표현
%s
|}
<p>&sup1; <small>문어체</small> &sup2; <small>구어체</small></p>
</div></div>]=]

    return string.format(table_template, display_lemma, table_headers, table.concat(rows, "\n"), table_headers, table.concat(core_expressions, "\n"))
end

local function generate_godan_table(lemma, kana, romaji, final_kana)
    local endings = {
        ["く"] = { mi = "か", yo = "き", shu = "く", ren = "く", ka = "け", me = "け", pass = "かれる", caus = "かせる<br>かす", pot = "ける", vol = "こう", neg = "かない", cont_neg = "かず", polite = "きます", past = "いた", te = "いて", conditional = "けば" },
        ["ぐ"] = { mi = "が", yo = "ぎ", shu = "ぐ", ren = "ぐ", ka = "げ", me = "げ", pass = "がれる", caus = "がせる<br>がす", pot = "げる", vol = "ごう", neg = "がない", cont_neg = "がず", polite = "ぎます", past = "いだ", te = "いで", conditional = "げば" },
        ["す"] = { mi = "さ", yo = "し", shu = "す", ren = "す", ka = "せ", me = "せ", pass = "される", caus = "させる<br>さす", pot = "せる", vol = "そう", neg = "さない", cont_neg = "さず", polite = "します", past = "した", te = "して", conditional = "せば" },
        ["つ"] = { mi = "た", yo = "ち", shu = "つ", ren = "つ", ka = "て", me = "て", pass = "たれる", caus = "たせる<br>たす", pot = "てる", vol = "とう", neg = "たない", cont_neg = "たず", polite = "ちます", past = "った", te = "って", conditional = "てば" },
        ["ぬ"] = { mi = "な", yo = "に", shu = "ぬ", ren = "ぬ", ka = "ね", me = "ね", pass = "なれる", caus = "なせる<br>なす", pot = "ねる", vol = "のう", neg = "なない", cont_neg = "なず", polite = "にます", past = "んだ", te = "んで", conditional = "ねば" },
        ["ぶ"] = { mi = "ば", yo = "び", shu = "ぶ", ren = "ぶ", ka = "べ", me = "べ", pass = "ばれる", caus = "ばせる<br>ばす", pot = "べる", vol = "ぼう", neg = "ばない", cont_neg = "ばず", polite = "びます", past = "んだ", te = "んで", conditional = "べば" },
        ["む"] = { mi = "ま", yo = "み", shu = "む", ren = "む", ka = "め", me = "め", pass = "まれる", caus = "ませる<br>ます", pot = "める", vol = "もう", neg = "まない", cont_neg = "まず", polite = "みます", past = "んだ", te = "んで", conditional = "めば" },
        ["る"] = { mi = "ら", yo = "り", shu = "る", ren = "る", ka = "れ", me = "れ", pass = "られる", caus = "らせる<br>らす", pot = "れる", vol = "ろう", neg = "らない", cont_neg = "らず", polite = "ります", past = "った", te = "って", conditional = "れば" },
        ["う"] = { mi = "わ", yo = "い", shu = "う", ren = "う", ka = "え", me = "え", pass = "われる", caus = "わせる<br>わす", pot = "える", vol = "おう", neg = "わない", cont_neg = "わず", polite = "います", past = "った", te = "って", conditional = "えば" },
    }
    local ending = endings[final_kana]
    local stem_kana = extract_stem(kana)
    local kana_only = not contains_kanji(lemma)

    local rows = {
        format_row('미연형(<span lang="ja" class="Jpan">未然形</span>)', lemma, stem_kana, ending.mi, false, kana_only),
        format_row('연용형(<span lang="ja" class="Jpan">連用形</span>)', lemma, stem_kana, ending.yo, false, kana_only),
        format_row('종지형(<span lang="ja" class="Jpan">終止形</span>)', lemma, stem_kana, ending.shu, false, kana_only),
        format_row('연체형(<span lang="ja" class="Jpan">連体形</span>)', lemma, stem_kana, ending.ren, false, kana_only),
        format_row('가정형(<span lang="ja" class="Jpan">仮定形</span>)', lemma, stem_kana, ending.ka, false, kana_only),
        format_row('명령형(<span lang="ja" class="Jpan">命令形</span>)', lemma, stem_kana, ending.me, false, kana_only)
    }

    local core_expressions = {
        format_row('수동형', lemma, stem_kana, ending.pass, false, kana_only),
        format_row('사역형', lemma, stem_kana, ending.caus, false, kana_only),
        format_row('가능형', lemma, stem_kana, ending.pot, false, kana_only),
        format_row('의지 · 권유형', lemma, stem_kana, ending.vol, false, kana_only),
        format_row('부정형', lemma, stem_kana, ending.neg, false, kana_only),
        format_row('지속 부정형', lemma, stem_kana, ending.cont_neg, false, kana_only),
        format_row('경어체', lemma, stem_kana, ending.polite, false, kana_only),
        format_row('과거형', lemma, stem_kana, ending.past, false, kana_only),
        format_row('접속형(て형)', lemma, stem_kana, ending.te, false, kana_only),
        format_row('가정형', lemma, stem_kana, ending.conditional, false, kana_only)
    }

    local table_headers = kana_only and "! colspan=\"3\" | " or "! colspan=\"4\" | "
    local table_template = [=[
<div class="NavFrame" style="border:0px;">
<div class="NavHead" align="left" style="font-weight:bold; border:1px solid darkgrey; margin-left:-1px; background-color: var(--nav-head-background, #EAECF0); color: var(--nav-head-text-color, #000000);"><span class="Jpan" lang="ja-Jpan" style="font-size:120%%;">"%s"</span>의 동사 활용 ([[부록:일본어 동사|부록:일본어 동사]])</div>
<div class="NavContent" style="font-size:105%%;">
{| class="wikitable" style="margin-top: 0; text-align: center; width: 100%%; color: var(--table-text-color, #000000); background: var(--table-background-color, #FFFFFF);" rules="all"
%s어간 형태
%s
|-
%s핵심 표현
%s
|}
</div></div>]=]

    return string.format(table_template, lemma, table_headers, table.concat(rows, "\n"), table_headers, table.concat(core_expressions, "\n"))
end

local function extract_kana_from_template()
    local content = mw.title.getCurrentTitle():getContent()
    if content then
        for template in ugmatch(content, "{{ja%-verb|(.-)}}") do
            local params = mw.text.split(template, "|")
            for i, param in ipairs(params) do
                if not param:find("=") then
                    return mw.text.trim(param)
                end
            end
        end
    end
    return ""
end

local function extract_type_from_template()
    local content = mw.title.getCurrentTitle():getContent()
    if content then
        for template in ugmatch(content, "{{ja%-verb|(.-)}}") do
            for param in mw.text.gsplit(template, "|") do
                local type = umatch(param, "type=(%w+)")
                if type then
                    return type
                end
            end
        end
    end
    return nil
end

local function generate_conjugation_table(lemma, kana, romaji, type)
    local kana_only = not contains_kanji(lemma)
    local is_kanji_suru = false

    if kana_only then
        kana = lemma
        if type == "suru" then
            if umatch(lemma, "する$") then
                kana = usub(lemma, 1, -3)
            elseif umatch(lemma, "ずる$") then
                kana = usub(lemma, 1, -3)
            end
        else
            kana = lemma
        end
    else
        if type == "suru" then
            is_kanji_suru = true
            if umatch(lemma, "する$") then
                lemma = usub(lemma, 1, -3)
                kana = usub(kana, 1, -3)
            elseif umatch(lemma, "ずる$") then
                lemma = usub(lemma, 1, -3)
                kana = usub(kana, 1, -3)
            else
                kana = extract_kana_from_template()
                if kana == "" then
                    kana = lemma
                end
            end
        else
            kana = extract_kana_from_template()
            if kana == "" then
                type = extract_type_from_template()
            end
        end
    end

    if type == "1" then
        local final_kana = usub(kana, -1)
        return generate_godan_table(lemma, kana, romaji, final_kana)
    elseif type == "suru" then
        return generate_suru_table(lemma, kana, romaji, kana_only, is_kanji_suru)
    else
        error("지원되지 않는 동사 유형입니다.")
    end
end

function export.show(frame)
    local lemma = mw.title.getCurrentTitle().text
    local kana = extract_kana_from_template()
    local type = extract_type_from_template()

    if kana == "" then
        type = "1"
        kana = extract_kana_from_template()
    end

    local romaji = kana_to_romaji(kana)

    return generate_conjugation_table(lemma, kana, romaji, type)
end

return export