Jump to content

Module:ja-conj

From Wiktionary, the free dictionary


local export = {}
local m_ja = require("Module:ja")
local m_links = require("Module:links")
local lang = require("Module:languages").getByCode("ja")

local romaji = require("Module:Hrkt-translit").tr
local ja_shift = require("Module:ja-shift").shift
local ja_onbin = require("Module:ja-shift").onbin

function export.jaconj(frame)
	
	local params = {
		[1] = {}, -- Stem. For irregular verbs: "suru", "kuru", etc.
		[2] = {}, -- For godan: final kana, for ichidan: "ichi"
		["head"] = {},
		["ou"] = {type = "boolean", default = "false"} -- For exceptions like 問う, 請う and 恋う
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	local data = {rows = {"dic", "pas", "cau", "pot", "per", "con", "hyp", "vol", "imp"}, forms = {}, cascade= {}, entry = {}}
	
	local head = args["head"] or mw.title.getCurrentTitle().text
	local headstem = head:sub(1, -4) -- Remove last kana
	
	local ou = (head == "問う" or head == "請う" or head == "恋う" or args["ou"] == "true") and "true" or "false"
	
	local grade = args[2] == "i" and "ichi" or args[2]
	grade = args[2] == nil and args[1] or grade -- Irregular verbs
	
	for key, row in pairs(data.rows) do
		
		data.forms[row] = autoConjugate(args[1], row, grade, headstem, head, ou)
		for ckey, crow in pairs(data.forms[row]) do data.cascade[row .. "." .. tostring(ckey)] = crow end
		
	end
	
	return export.make_table(data, headstem, args, head, grade)
	
end

function export.make_table(data, headstem, args, head, grade)
	
	local result = {}
	local tail = [=[
</div></div>
]=]

	local content = [=[
<div class="NavFrame">
<div class="NavHead" style="text-align: left;">Extended conjugation of<span class="Jpan" lang="ja-Jpan">【[[:@HEADWORD#Japanese|@HEADWORD]]】</span>@ANNOTATION</div>
<div class="NavContent columns-bg ul-column-count inflection-table" data-column-count="2" style="text-align: left; line-height: 2">
* '''[[Appendix:Japanese_glossary#ren'yōkei|''Ren’yōkei'']] / Verb stem:''' {dic.mas}
* '''Non-past / Imperfective:''' {dic.pln}
** '''Negative:''' {dic.neg}
** '''Polite:''' {dic.pol}
** '''Polite negative:''' {dic.png}
* '''Past / Perfective:''' {per.pln}
** '''Negative:''' {per.neg}
** '''Polite:''' {per.pol}
** '''Polite negative:''' {per.png}
* '''Conjunctive (''te''-form):''' {con.pln}
** '''Negative:''' {con.neg}
* '''Hypothetical conditional:''' {hyp.pln}
** '''Negative:''' {hyp.neg}
** '''Negative (colloquial):''' {hyp.ngc}
* '''Volitional / Presumptive:''' {vol.pln}
** '''Polite:''' {vol.pol}
* '''Imperative:''' @IMPERATIVE
** '''Polite [[なさい#Japanese|''-nasai'']] form (informal):''' {imp.pol}
* '''Archaic or classical negative:''' {dic.fng}
* '''Formal negative continuative:''' {dic.ncn}
* <li style="break-before:column"> '''Passive:''' {pas.pln}
** '''Verb stem:''' {pas.mas}
** '''Negative:''' {pas.neg}
** '''Polite:''' {pas.pol}
** '''Polite negative:''' {pas.png}
** '''Conjunctive (''te''-form):''' {pas.con}
* '''Causative:''' {cau.pln}
** '''Short form:''' {cau.srt}
** '''Verb stem:''' {cau.mas}
** '''Negative:''' {cau.neg}
** '''Polite:''' {cau.pol}
** '''Polite negative:''' {cau.png}
** '''Conjunctive (''te''-form):''' {cau.con}
* '''Potential:''' {pot.pln}
** '''Verb stem:''' {pot.mas}
** '''Negative:''' {pot.neg}
** '''Polite:''' {pot.pol}
** '''Polite negative:''' {pot.png}
** '''Past / Perfective:''' {pot.per}
** '''Conjunctive (''te''-form):''' {pot.con}
]=]

	local imperativeForms = (grade == "ichi" or grade == "suru") and "(''written'') {imp.wri}, (''spoken'') {imp.spo}" or "{imp.pln}"
	local annotation = [=[[[Appendix:Japanese verbs#Five-grade_(五段_godan)|''godan'']] ("pentagrade")]=]
	if grade == "ichi" and romaji(args[1]:sub(-3), 'jp'):sub(-1) == "i" then
		annotation = [=[[[Appendix:Japanese verbs#Upper monograde (上一段 kami ichidan)|''kami ichidan'']] ("upper monograde")]=]
	elseif grade == "ichi" and romaji(args[1]:sub(-3), 'jp'):sub(-1) == "e" then
		annotation = [=[[[Appendix:Japanese verbs#Lower_monograde_(下一段_shimo_ichidan)|''shimo ichidan'']] ("lower monograde")]=]
	elseif grade == "kuru" then
		annotation = [=[[[Appendix:Japanese verbs#k-irregular_(カ行変格_ka-gyō_henkaku)|''ka-gyō henkaku'']] ("''k''-irregular")]=]
	elseif grade == "suru" then
		annotation = [=[[[Appendix:Japanese verbs#s-irregular_(サ行変格_sa-gyō_henkaku)|''sa-gyō henkaku'']] ("''s''-irregular")]=]
	end
	content = content:gsub("@IMPERATIVE", imperativeForms)
	content = content:gsub("@HEADWORD", head)
	content = content:gsub("@ANNOTATION", 'Class:&nbsp;' .. annotation)
	
	table.insert(result, content)

	-- Tail
	table.insert(result, tail)

	return (string.gsub(table.concat(result), "{([^|}]+)}",
			function(code)
				data.entry[code] = map(data.cascade[code], function(i)
					local translit = romaji(i:gsub("-", ""), 'jp'):gsub(headstem, romaji(args[1], 'jp'))
					local iruby = nil
					if (grade == "kuru" and headstem == "来") or (grade == "suru" and headstem == "為") then
						iruby = '<ruby>' .. headstem .. '<rt>' .. i:sub(1, 3) .. '</rt></ruby>' .. i:sub(4) -- Remove first character, + kanji, +ruby
						i = headstem .. i:sub(4) -- Remove first character, + kanji
					end
					local jplinks = {} -- Suffixes and standalone words link to their own pages
					local count = 0
					for w in i:gmatch("([^- ]+)") do
						count = count + 1
						if w == "て" or w == "ず" then
							table.insert(jplinks, '[[:' .. w .. '#Suffix|' .. w .. ']]')
						elseif w == "に" then
							table.insert(jplinks, '[[:' .. w .. '#Particle|' .. w .. ']]')
						elseif w == "して" or w == "した" then
							table.insert(jplinks, '[[:' .. w .. '#Verb|' .. w .. ']]')
						else
							if iruby == nil then
								table.insert(jplinks, '[[:' .. w .. '#Japanese|' .. w .. ']]')
							else
								table.insert(jplinks, '[[:' .. w .. '#Japanese|' .. get_nth(iruby, count) .. ']]')
							end
						end
					end
					return '<span class="Jpan" lang="ja-Jpan">' .. table.concat(jplinks) .. '</span>&nbsp;<span style="font-size:90%">[' .. translit .. ']</span>' 
				end)
				return table.concat(data.entry[code], ", ")
			end))
	
end

function autoConjugate(stem, row, grade, headstem, head, ou)
	
	local conj = "—"
	
	-- Dictionary / Imperfective / Non-past
	if row == "dic" then
		
		if grade == "suru" then return {
			pln = { "する" },
			neg = { "しない" },
			pol = { "し-ます" },
			png = { "し-ません" },
			mas = { "し" },
			fng = { "せず" },
			ncn = { "せず に" },
		} elseif grade == "kuru" then return {
			pln = { "くる" },
			neg = { "こない" },
			pol = { "き-ます" },
			png = { "き-ません" },
			mas = { "き" },
			fng = { "こ-ず" },
			ncn = { "こ-ず に" },
		} end
		
		conj = grade == "ichi" and {
			pln = { head },
			neg = { headstem .. "ない", headstem .. "ぬ", headstem .. "ん" },
			pol = { headstem .. "ます" },
			png = { headstem .. "ません" },
			mas = { headstem },
			fng = { headstem .. "-ず" },
			ncn = { headstem .. "-ず に" },
		} or {
			pln = { head },
			neg = { headstem .. ja_shift(grade, "a") .. "ない" },
			pol = { headstem .. ja_shift(grade, "i") .. "ます" },
			png = { headstem .. ja_shift(grade, "i") .. "ません" },
			mas = { headstem .. ja_shift(grade, "i") },
			fng = { headstem .. ja_shift(grade, "a") .. "-ず" },
			ncn = { headstem .. ja_shift(grade, "a") .. "-ず に" },
		}
		
		return conj
		
	-- Passive
	elseif row == "pas" then
		
		if grade == "suru" then return {
			pln = { "される" },
			neg = { "され-ない" },
			pol = { "され-ます" },
			png = { "され-ません" },
			mas = { "され" },
			con = { "され-て" },
		} elseif grade == "kuru" then return {
			pln = { "こられる" },
			neg = { "こられ-ない" },
			pol = { "こられ-ます" },
			png = { "こられ-ません" },
			mas = { "こられ" },
			con = { "こられ-て" },
		} end
		
		conj = {
			pln = { headstem .. ja_shift(grade, "a") .. "れる" },
			neg = { headstem .. ja_shift(grade, "a") .. "れ-ない" },
			pol = { headstem .. ja_shift(grade, "a") .. "れ-ます" },
			png = { headstem .. ja_shift(grade, "a") .. "れ-ません" },
			mas = { headstem .. ja_shift(grade, "a") .. "れ"},
			con = { headstem .. ja_shift(grade, "a") .. "れ-て"},
		}
		
		return conj
		
	-- Causative
	elseif row == "cau" then
		
		if grade == "suru" then return {
			pln = { "させる" },
			neg = { "させ-ない" },
			pol = { "させ-ます" },
			png = { "させ-ません" },
			mas = { "させ" },
			con = { "させ-て" },
			srt = { "さす" },
		} elseif grade == "kuru" then return {
			pln = { "こさせる" },
			neg = { "こさせ-ない" },
			pol = { "こさせ-ます" },
			png = { "こさせ-ません" },
			mas = { "こさせ" },
			con = { "こさせ-て" },
			srt = { "こさす" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "させる" },
			neg = { headstem .. "させ-ない" },
			pol = { headstem .. "させ-ます" },
			png = { headstem .. "させ-ません" },
			mas = { headstem .. "させ" },
			con = { headstem .. "させ-て" },
			srt = { headstem .. "さす" },
		} or {
			pln = { headstem .. ja_shift(grade, "a") .. "せる" },
			neg = { headstem .. ja_shift(grade, "a") .. "せ-ない" },
			pol = { headstem .. ja_shift(grade, "a") .. "せ-ます" },
			png = { headstem .. ja_shift(grade, "a") .. "せ-ません" },
			mas = { headstem .. ja_shift(grade, "a") .. "せ" },
			con = { headstem .. ja_shift(grade, "a") .. "せ-て" },
			srt = { headstem .. ja_shift(grade, "a") .. "す" },
		}
		
		return conj
		
	-- Potential
	elseif row == "pot" then
		
		if grade == "suru" then return {
			pln = { "できる" },
			neg = { "できない" },
			pol = { "でき-ます" },
			png = { "でき-ません" },
			mas = { "でき" },
			con = { "でき-て" },
			per = { "でき-た" },
		} elseif grade == "kuru" then return {
			pln = { "こられる" },
			neg = { "こられ-ない" },
			pol = { "こられ-ます" },
			png = { "こられ-ません" },
			mas = { "こられ" },
			con = { "こられ-て" },
			per = { "こられ-た" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "られる", headstem .. "れる" },
			neg = { headstem .. "られ-ない", headstem .. "れ-ない" },
			pol = { headstem .. "られ-ます", headstem .. "れ-ます" },
			png = { headstem .. "られ-ません", headstem .. "れ-ません" },
			mas = { headstem .. "られ", headstem .. "れ" },
			con = { headstem .. "られ-て", headstem .. "れ-て" },
			per = { headstem .. "られ-た", headstem .. "れ-た" },
		} or {
			pln = { headstem .. ja_shift(grade, "e") .. "る" },
			neg = { headstem .. ja_shift(grade, "e") .. "-ない" },
			pol = { headstem .. ja_shift(grade, "e") .. "-ます" },
			png = { headstem .. ja_shift(grade, "e") .. "-ません" },
			mas = { headstem .. ja_shift(grade, "e")},
			con = { headstem .. ja_shift(grade, "e") .. "-て"},
			per = { headstem .. ja_shift(grade, "e") .. "-た"},
		}
		
		return conj
		
	-- Perfective for 問う and 請う
	elseif row == "per" and ou == "true" then
		
		conj = {
			pln = { headstem .. "うた" },
			neg = { headstem .. "わ-なかった" },
			pol = { headstem .. "い-ました" },
			png = { headstem .. "い-ません でした" },
		}
		
		return conj
		
	-- Perfective
	elseif row == "per" and ou == "false" then
		
		if grade == "suru" then return {
			pln = { "した" },
			neg = { "し-なかった" },
			pol = { "し-ました" },
			png = { "し-ません でした" },
		} elseif grade == "kuru" then return {
			pln = { "きた" },
			neg = { "き-なかった" },
			pol = { "き-ました" },
			png = { "き-ません でした" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "た" },
			neg = { headstem .. "-なかった" },
			pol = { headstem .. "-ました" },
			png = { headstem .. "-ません でした" },
		} or {
			pln = { headstem .. ja_onbin(grade, "a") },
			neg = { headstem .. ja_shift(grade, "a") .. "-なかった" },
			pol = { headstem .. ja_shift(grade, "i") .. "-ました" },
			png = { headstem .. ja_shift(grade, "i") .. "-ません でした" },
		}
		
		return conj
		
	-- Te-form for 問う and 請う
	elseif row == "con" and ou == "true" then
		
		conj = {
			pln = { headstem .. "うて" },
			neg = { headstem .. "わ-ない で", headstem .. "わ-なくて" },
		}
		
		return conj
		
	-- Te-form
	elseif row == "con" and ou == "false" then
		
		if grade == "suru" then return {
			pln = { "して" },
			neg = { "しない で", "しなくて" },
		} elseif grade == "kuru" then return {
			pln = { "きて" },
			neg = { "き-ない で", "き-なくて" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "て" },
			neg = { headstem .. "-ない で", headstem .. "-なくて" },
		} or {
			pln = { headstem .. ja_onbin(grade, "e") },
			neg = { headstem .. ja_shift(grade, "a") .. "ない で", headstem .. ja_shift(grade, "a") .. "-なくて" },
		}
		
		return conj
		
	-- Hypothetical conditional
	elseif row == "hyp" then
		
		if grade == "suru" then return {
			pln = { "すれば" },
			neg = { "し-なければ" },
			ngc = { "し-なきゃ" },
		} elseif grade == "kuru" then return {
			pln = { "くれば" },
			neg = { "こ-なければ" },
			ngc = { "こ-なきゃ" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "れば" },
			neg = { headstem .. "-なければ" },
			ngc = { headstem .. "-なきゃ" },
		} or {
			pln = { headstem .. ja_shift(grade, "e") .. "ば" },
			neg = { headstem .. ja_shift(grade, "a") .. "-なければ" },
			ngc = { headstem .. ja_shift(grade, "a") .. "-なきゃ" },
		}
		
		return conj
		
	-- Volitional
	elseif row == "vol" then
		
		if grade == "suru" then return {
			pln = { "しよう" },
			pol = { "し-ましょう" }
		} elseif grade == "kuru" then return {
			pln = { "こよう" },
			pol = { "こ-ましょう" },
		} end
		
		conj = grade == "ichi" and {
			pln = { headstem .. "よう" },
			pol = { headstem .. "-ましょう" },
		} or {
			pln = { headstem .. ja_shift(grade, "o") .. "う" },
			pol = { headstem .. ja_shift(grade, "i") .. "-ましょう" }
		}
		
		return conj
	
	-- Imperative
	elseif row == "imp" then
		
		if grade == "suru" then return {
			wri = { "せよ" },
			spo = { "しろ" },
			pol = { "し-なさい" },
		} elseif grade == "kuru" then return {
			pln = { "こい" },
			pol = { "きなさい" }
		} end
		
		conj = grade == "ichi" and {
			wri = { headstem .. "よ" },
			spo = { headstem .. "ろ" },
			pol = { headstem .. "-なさい" },
		} or {
			pln = { headstem .. ja_shift(grade, "e") },
			pol = { headstem .. ja_shift(grade, "i") .. "-なさい" },
		}
		
		return conj
		
	end
	
	return conj
	
end

function map(tbl, f)
    local t = {}
    for k,v in pairs(tbl) do
        t[k] = f(v)
    end
    return t
end

function get_nth(sentence, n)
    local words = {}

    for word in sentence:gmatch("([^- ]+)") do
        words[#words + 1] = word
    end

    return words[n] 
end

return export