Module:pl-noun

Definition from Wiktionary, the free dictionary
Jump to: navigation, search
The following documentation is located at Module:pl-noun/documentation. [edit]
Useful links: subpage listtransclusionstestcases

This module implements {{pl-decl-noun}}, {{pl-decl-noun-sing}}, {{pl-decl-noun-pl}} and {{pl-decl-noun-dual}}.


local m_links = require('Module:links')
local m_adj = require('Module:pl-adj')
 
local export = {}
 
local lang = require("Module:languages").getByCode("pl")
 
local cases_en = {
	"nominative",
	"genitive",
	"dative",
	"accusative",
	"instrumental",
	"locative",
	"vocative"
}
 
local cases_pl = {
	"mianownik (kto? co?)",
	"dopełniacz (kogo? czego?)",
	"celownik (komu? czemu?)",
	"biernik (kogo? co?)",
	"narzędnik (kim? czym?)",
	"miejscownik (o kim? o czym?)",
	"wołacz (o!)"
}
 
local function make_table(items, heads, width, title, curtitle)
	local result = {}
 
	title = title or ('declension of <i class="Latn mention" lang="pl" xml:lang="pl">%s</i>'):format(items[1][1])
 
	if heads and (#heads > 0) then
		table.insert(result, '|-\n! style="width: 8em;" |\n')
		for _, head in ipairs(heads) do
			table.insert(result, ('! scope="col" | %s\n'):format(head))
		end
	end
 
	local maxl = 0
	for i = 1, 7 do
		table.insert(result, ('|-\n! title="%s" scope="row" | %s\n'):format(cases_pl[i], cases_en[i]))
		for _, item in ipairs(items[i]) do
			item = mw.text.trim(item)
			table.insert(result, (item == "-") and '| —\n' or ('| %s\n'):format(
				m_links.full_link(item, nil, lang, nil, nil, nil, {}, false)
			))
			if not width then -- speed
				local l = mw.ustring.len(m_links.remove_links(item))
				if maxl < l then
					maxl = l
				end
			end
		end
	end
 
	if not width then
		width = math.floor(maxl * 0.78) -- number obtained by anecdotal evidence
		width = (width < 10) and 10 or width
		width = 9 + (width * #heads)
	end
 
	return ([=[<div class="NavFrame inflection-table-noun" style="width: %uem">
<div class="NavHead">%s</div>
<div class="NavContent">
{| style="width: %uem; margin: 0;" class="wikitable inflection-table"
]=]):format(width, title, width) .. table.concat(result, "") .. "|}</div></div>"
end
 
local function make_table_sg(declinfo, width, curtitle)
	return make_table({
		{ declinfo.nom },
		{ declinfo.gen },
		{ declinfo.dat },
		{ declinfo.acc },
		{ declinfo.ins },
		{ declinfo.loc },
		{ declinfo.voc }
	}, { "singular only" }, width, nil, curtitle)
end
 
local function make_table_pl(declinfo, width, curtitle)
	return make_table({
		{ declinfo.nomp },
		{ declinfo.genp },
		{ declinfo.datp },
		{ declinfo.accp },
		{ declinfo.insp },
		{ declinfo.locp },
		{ declinfo.vocp }
	}, { "plural only" }, width, nil, curtitle)
end
 
local function make_table_dual(declinfo, width, curtitle)
	return make_table({
		{ declinfo.nom, declinfo.nomd, declinfo.nomp },
		{ declinfo.gen, declinfo.gend, declinfo.genp },
		{ declinfo.dat, declinfo.datd, declinfo.datp },
		{ declinfo.acc, declinfo.accd, declinfo.accp },
		{ declinfo.ins, declinfo.insd, declinfo.insp },
		{ declinfo.loc, declinfo.locd, declinfo.locp },
		{ declinfo.voc, declinfo.vocd, declinfo.vocp }
	}, { "singular", "dual", "plural" }, width, nil, curtitle)
end
 
local function make_table_both(declinfo, width, curtitle)
	return make_table({
		{ declinfo.nom, declinfo.nomp },
		{ declinfo.gen, declinfo.genp },
		{ declinfo.dat, declinfo.datp },
		{ declinfo.acc, declinfo.accp },
		{ declinfo.ins, declinfo.insp },
		{ declinfo.loc, declinfo.locp },
		{ declinfo.voc, declinfo.vocp }
	}, { "singular", "plural" }, width, nil, curtitle)
end
 
local function get_mode()
	local frame = mw.getCurrentFrame()
	if mw.isSubsting() then
		return 'subst'
	elseif frame:getParent():getTitle() == mw.title.getCurrentTitle().fullText then
		return 'demo'
	else
		return 'xclude'
	end
end
 
function export.template_decl_noun_dual(frame)
	local pargs = frame:getParent().args
	local width = pargs.width and tonumber(pargs.width)
	local title = mw.title.getCurrentTitle()
 
	local declinfo
	if get_mode() == 'demo' then
		declinfo = {
			nom = '{{{nom| {{{1}}} }}}' , nomd = '{{{nomd| {{{2}}} }}}' , nomp = '{{{nomp| {{{3}}} }}}',
			gen = '{{{gen| {{{4}}} }}}' , gend = '{{{gend| {{{5}}} }}}' , genp = '{{{genp| {{{6}}} }}}',
			dat = '{{{dat| {{{7}}} }}}' , datd = '{{{datd| {{{8}}} }}}' , datp = '{{{datp| {{{9}}} }}}',
			acc = '{{{acc| {{{10}}} }}}', accd = '{{{accd| {{{11}}} }}}', accp = '{{{accp| {{{12}}} }}}',
			ins = '{{{ins| {{{13}}} }}}', insd = '{{{insd| {{{14}}} }}}', insp = '{{{insp| {{{15}}} }}}',
			loc = '{{{loc| {{{16}}} }}}', locd = '{{{locd| {{{17}}} }}}', locp = '{{{locp| {{{18}}} }}}',
			voc = '{{{voc| {{{19}}} }}}', vocd = '{{{vocd| {{{20}}} }}}', vocp = '{{{vocp| {{{21}}} }}}'
		}
	else
		declinfo = {
			nom = mw.text.trim(pargs.nom or pargs[ 1]), nomd = mw.text.trim(pargs.nomd or pargs[ 2]), nomp = mw.text.trim(pargs.nomp or pargs[ 3]),
			gen = mw.text.trim(pargs.gen or pargs[ 4]), gend = mw.text.trim(pargs.gend or pargs[ 5]), genp = mw.text.trim(pargs.genp or pargs[ 6]),
			dat = mw.text.trim(pargs.dat or pargs[ 7]), datd = mw.text.trim(pargs.datd or pargs[ 8]), datp = mw.text.trim(pargs.datp or pargs[ 9]),
			acc = mw.text.trim(pargs.acc or pargs[10]), accd = mw.text.trim(pargs.accd or pargs[11]), accp = mw.text.trim(pargs.accp or pargs[12]),
			ins = mw.text.trim(pargs.ins or pargs[13]), insd = mw.text.trim(pargs.insd or pargs[14]), insp = mw.text.trim(pargs.insp or pargs[15]),
			loc = mw.text.trim(pargs.loc or pargs[16]), locd = mw.text.trim(pargs.locd or pargs[17]), locp = mw.text.trim(pargs.locp or pargs[18]),
			voc = mw.text.trim(pargs.voc or pargs[19]), vocd = mw.text.trim(pargs.vocd or pargs[20]), vocp = mw.text.trim(pargs.vocp or pargs[21])
		}
	end
 
	return make_table_dual(declinfo, width, title.fullText)
end
 
function export.template_decl_noun_pl(frame)
	local pargs = frame:getParent().args
	local width = pargs.width and tonumber(pargs.width)
	local title = mw.title.getCurrentTitle()
 
	local declinfo
	if get_mode() == 'demo' then
		declinfo = {
			nom = '{{{nom}}}', nomd = '{{{nomd}}}', nomp = '{{{nomp| {{{1}}} }}}',
			gen = '{{{gen}}}', gend = '{{{gend}}}', genp = '{{{genp| {{{2}}} }}}',
			dat = '{{{dat}}}', datd = '{{{datd}}}', datp = '{{{datp| {{{3}}} }}}',
			acc = '{{{acc}}}', accd = '{{{accd}}}', accp = '{{{accp| {{{4}}} }}}',
			ins = '{{{ins}}}', insd = '{{{insd}}}', insp = '{{{insp| {{{5}}} }}}',
			loc = '{{{loc}}}', locd = '{{{locd}}}', locp = '{{{locp| {{{6}}} }}}',
			voc = '{{{voc}}}', vocd = '{{{vocd}}}', vocp = '{{{vocp| {{{7}}} }}}'
		}
 
		return make_table_pl(declinfo, width, title.fullText)
	else
		declinfo = {
			nomp = mw.text.trim(pargs.nomp or pargs[1]),
			genp = mw.text.trim(pargs.genp or pargs[2]),
			datp = mw.text.trim(pargs.datp or pargs[3]),
			accp = mw.text.trim(pargs.accp or pargs[4]),
			insp = mw.text.trim(pargs.insp or pargs[5]),
			locp = mw.text.trim(pargs.locp or pargs[6]),
			vocp = mw.text.trim(pargs.vocp or pargs[7])
		}
 
		return make_table_pl(declinfo, width, title.fullText) .. "[[Category:Polish pluralia tantum]]"
	end
end
 
function export.template_decl_noun_sg(frame)
	local pargs = frame:getParent().args
	local width = pargs.width and tonumber(pargs.width)
	local title = mw.title.getCurrentTitle()
 
	local declinfo
	if get_mode() == 'demo' then
		declinfo = {
			nom = '{{{nom| {{{1}}} }}}', nomd = '{{{nomd}}}', nomp = '{{{nomp}}}',
			gen = '{{{gen| {{{2}}} }}}', gend = '{{{gend}}}', genp = '{{{genp}}}',
			dat = '{{{dat| {{{3}}} }}}', datd = '{{{datd}}}', datp = '{{{datp}}}',
			acc = '{{{acc| {{{4}}} }}}', accd = '{{{accd}}}', accp = '{{{accp}}}',
			ins = '{{{ins| {{{5}}} }}}', insd = '{{{insd}}}', insp = '{{{insp}}}',
			loc = '{{{loc| {{{6}}} }}}', locd = '{{{locd}}}', locp = '{{{locp}}}',
			voc = '{{{voc| {{{7}}} }}}', vocd = '{{{vocd}}}', vocp = '{{{vocp}}}'
		}
 
		return make_table_sg(declinfo, width, title.fullText)
	else
		declinfo = {
			nom = mw.text.trim(pargs.nom or pargs[1]),
			gen = mw.text.trim(pargs.gen or pargs[2]),
			dat = mw.text.trim(pargs.dat or pargs[3]),
			acc = mw.text.trim(pargs.acc or pargs[4]),
			ins = mw.text.trim(pargs.ins or pargs[5]),
			loc = mw.text.trim(pargs.loc or pargs[6]),
			voc = mw.text.trim(pargs.voc or pargs[7])
		}
 
		return make_table_sg(declinfo, width, title.fullText) .. "[[Category:Polish singularia tantum]]"
	end
end
 
function export.template_decl_noun(frame)
	local pargs = frame:getParent().args
	local width = pargs.width and tonumber(pargs.width)
	local title = mw.title.getCurrentTitle()
 
	local declinfo 
	if get_mode() == 'demo' then
		declinfo = {
			nom = '{{{nom| {{{1}}} }}}' , nomd = '{{{nomd}}}', nomp = '{{{nomp| {{{2}}} }}}',
			gen = '{{{gen| {{{3}}} }}}' , gend = '{{{gend}}}', genp = '{{{genp| {{{4}}} }}}',
			dat = '{{{dat| {{{5}}} }}}' , datd = '{{{datd}}}', datp = '{{{datp| {{{6}}} }}}',
			acc = '{{{acc| {{{7}}} }}}' , accd = '{{{accd}}}', accp = '{{{accp| {{{8}}} }}}',
			ins = '{{{ins| {{{9}}} }}}' , insd = '{{{insd}}}', insp = '{{{insp| {{{10}}} }}}',
			loc = '{{{loc| {{{11}}} }}}', locd = '{{{locd}}}', locp = '{{{locp| {{{12}}} }}}',
			voc = '{{{voc| {{{13}}} }}}', vocd = '{{{vocd}}}', vocp = '{{{vocp| {{{14}}} }}}'
		}
	else
		declinfo = {
			nom = mw.text.trim(pargs.nom or pargs[ 1]), nomp = mw.text.trim(pargs.nomp or pargs[ 2]),
			gen = mw.text.trim(pargs.gen or pargs[ 3]), genp = mw.text.trim(pargs.genp or pargs[ 4]),
			dat = mw.text.trim(pargs.dat or pargs[ 5]), datp = mw.text.trim(pargs.datp or pargs[ 6]),
			acc = mw.text.trim(pargs.acc or pargs[ 7]), accp = mw.text.trim(pargs.accp or pargs[ 8]),
			ins = mw.text.trim(pargs.ins or pargs[ 9]), insp = mw.text.trim(pargs.insp or pargs[10]),
			loc = mw.text.trim(pargs.loc or pargs[11]), locp = mw.text.trim(pargs.locp or pargs[12]),
			voc = mw.text.trim(pargs.voc or pargs[13]), vocp = mw.text.trim(pargs.vocp or pargs[14])
		}
	end
 
	return make_table_both(declinfo, width, title.fullText)
end
 
-- declension
 
local function make_lookup_table(str)
	local ret = {}
	for i in mw.ustring.gmatch(str, "%a+") do
		ret[i] = true
	end
	return ret
end
 
local patterns = {}
 
local function masc_common(pattern, stem, last, gens_ending, noms_form, nomp_form, altgenp)
	local endings = make_lookup_table(
		"b c ch ci cz d dz f g h j k l ł m n ni p r rz " ..
		"s si sł sm sn st sz t w z zd zi zł zm zn ż x")
 
	if not endings[last] then
		-- suppress module error on the template page
		if not mw.ustring.match(last, "^{{{") then
			error("Unsupported word ending: " .. last)
		end
	end
 
	-- nominative singular
	local noms_lookup = { ci = "ć"; ni = "ń"; si = "ś"; zi = "ź"; }
	if not noms_form or (noms_form == "") then
		noms_form = stem .. (noms_lookup[last] or last)
	end
 
	if last == "x" then
		last = "ks"
	end
 
	-- genitive singular
	local gens_form = stem .. last .. gens_ending
 
	-- accusative singular
	local accs_form = (pattern == "masc-inani") and noms_form or gens_form
 
	-- instrumental singular
	local inss_form
	if (last == "g") or (last == "k") then
		inss_form = stem .. last .. "iem"
	else
		inss_form = stem .. last .. "em"
	end
 
	-- locative singular
	-- vocative singular is the same
	local locs_lookup = {
		b = "bie";
		c = "cu"; ch = "chu"; ci = "ciu"; cz = "czu";
		d = "dzie"; dz = "dzu";
		f = "fie";
		g = "gu";
		h = "hu";
		j = "ju";
		k = "ku"; ks = "ksie";
		l = "lu"; ["ł"] = "le";
		m = "mie";
		n = "nie"; ni = "niu";
		p = "pie";
		r = "rze"; rz = "rzu";
		s = "sie"; si = "siu"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie";
			st = "ście"; sz = "szu";
		t = "cie";
		w = "wie";
		z = "zie"; zd = "ździe"; zi = "ziu"; ["zł"] = "źle"; zm = "źmie";
			zn = "źnie"; ["ż"] = "żu";
	}
	locs_form = stem .. (locs_lookup[last] or last)
 
	-- nominative plural
	-- accusative and vocative plural are the same
	if not nomp_form or (nomp_form == "") then
		local nomp_e_ending = make_lookup_table("c ci cz dz j l ni rz si sz zi ż")
		if (last == "g") or (last == "k") then
			nomp_form = stem .. last .. "i"
		elseif nomp_e_ending[last] then
			nomp_form = stem ..last .. "e"
		else
			nomp_form = stem .. last .. "y"
		end
	end
 
	-- genitive plural
	local genp_form
	if (last == "ci") or (last == "ni") or (last == "si") or (last =="zi") then
		genp_form = stem .. last
	elseif (last == "l") then
		genp_form = stem .. last .. "i"
	elseif (last == "j") then
		genp_form = stem .. last .. "ów"
		if not altgenp or (altgenp == "") then
			altgenp = stem .. "i"
		end
	elseif (last == "cz") or (last == "rz") or (last == "sz") or (last == "ż") then
		genp_form = stem .. last .. "y"
	else
		genp_form = stem .. last .. "ów"
	end
	if altgenp and (altgenp ~= "") then
		genp_form = "[[" .. genp_form .. "]]/[[" .. altgenp .. "]]"
	end
 
	-- accusative plural
	local accp_form = (pattern == "masc-pers") and genp_form or nomp_form
 
	return {
		nom = noms_form;
		gen = gens_form;
		dat = stem .. last .. "owi";
		acc = accs_form;
		ins = inss_form;
		loc = locs_form;
		voc = locs_form;
 
		nomp = nomp_form;
		genp = genp_form;
		datp = stem .. last .. "om";
		accp = accp_form;
		insp = stem .. last .. "ami";
		locp = stem .. last .. "ach";
		vocp = nomp_form;
	}
end
 
patterns["masc-inani"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local gens_ending = pargs[3]
	local noms_form = pargs[4]
	local altgenp = pargs[5]
 
	return masc_common("masc-inani", stem, last, gens_ending, noms_form,
		nil, altgenp)
end
 
patterns["masc-ani"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local noms_form = pargs[3]
	local altgenp = pargs[4]
 
	return masc_common("masc-ani", stem, last, "a", noms_form,
		nil, altgenp)
end
 
patterns["masc-pers"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local nomp_form = pargs[3]
	local noms_form = pargs[4]
	local altgenp = pargs[5]
 
	return masc_common("masc-pers", stem, last, "a", noms_form,
		nomp_form, altgenp)
end
 
patterns["masc-pers-adj"] = function (pargs)
	local word = pargs[1] or mw.title.getCurrentTitle().fullText
	if mw.ustring.match(word, "^{{{") then
		word = "przykładowa"
	end
 
	local decl = m_adj.autoinflect(word)
 
	return {
		nom = decl[1];
		gen = decl[6];
		dat = decl[9];
		acc = decl[6];
		ins = decl[12];
		loc = decl[12];
		voc = decl[1];
 
		nomp = decl[4];
		genp = decl[8];
		datp = decl[10];
		accp = decl[8];
		insp = decl[13];
		locp = decl[8];
		vocp = decl[4];
	}
end
 
patterns["log"] = function (pargs)
	local stem = pargs[1]
	local nomp_form = pargs[2]
	local inanimate = false
 
	if not stem or (stem == "") then
		local title = mw.title.getCurrentTitle().fullText
		stem = mw.ustring.match(title, "^(.*)log$")
		inanimate = true
	end
 
	if not nomp_form or (nomp_form == "") then
		if inanimate then
			nomp_form = stem .. "logi"
		else
			nomp_form = "[[" .. stem .. "lodzy]]/[[" .. stem .. "logowie]]"
		end
	end
 
	local gens_form = stem .. "loga"
	if inanimate then
		gens_form = stem .. "logu"
	end
 
	local accs_form = stem .. "loga"
	if inanimate then
		accs_form = stem .. "log"
	end
 
	return {
		nom = stem .. "log";
		gen = gens_form;
		dat = stem .. "logowi";
		acc = accs_form;
		ins = stem .. "logiem";
		loc = stem .. "logu";
		voc = stem .. "logu";
 
		nomp = nomp_form;
		genp = stem .. "logów";
		datp = stem .. "logom";
		accp = stem .. "logów";
		insp = stem .. "logami";
		locp = stem .. "logach";
		vocp = nomp_form;
	}
end
 
patterns["sta"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "sta";
		gen = stem .. "sty";
		dat = stem .. "ście";
		acc = stem .. "stę";
		ins = stem .. "stą";
		loc = stem .. "ście";
		voc = stem .. "sto";
 
		nomp = stem .. "ści";
		genp = stem .. "stów";
		datp = stem .. "stom";
		accp = stem .. "stów";
		insp = stem .. "stami";
		locp = stem .. "stach";
		vocp = stem .. "ści";
	}
end
 
patterns["ta"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "ta";
		gen = stem .. "ty";
		dat = stem .. "cie";
		acc = stem .. "tę";
		ins = stem .. "tą";
		loc = stem .. "cie";
		voc = stem .. "to";
 
		nomp = stem .. "ci";
		genp = stem .. "tów";
		datp = stem .. "tom";
		accp = stem .. "tów";
		insp = stem .. "tami";
		locp = stem .. "tach";
		vocp = stem .. "ci";
	}
end
 
patterns["masc-a"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
 
	local endings = make_lookup_table("c ch st t")
 
	if not endings[last] then
		-- suppress module error on the template page
		if not mw.ustring.match(last, "^{{{") then
			error("Unsupported word ending: " .. last)
		end
	end
 
	local dats_lookup = {
		c = "cy";
		ch = "sze";
		st = "ście";
		t = "cie";
	}
	local dats_form = stem .. (dats_lookup[last] or last)
 
	local nomp_lookup = {
		c = "cy";
		ch = "chowie";
		st = "ści";
		t = "ci";
	}
	local nomp_form = stem .. (nomp_lookup[last] or (last .. "i"))
 
	return {
		nom = stem .. last .. "a";
		gen = stem .. last .. "y";
		dat = dats_form;
		acc = stem .. last .. "ę";
		ins = stem .. last .. "ą";
		loc = dats_form;
		voc = stem .. last .. "o";
 
		nomp = nomp_form;
		genp = stem .. last .. "ów";
		datp = stem .. last .. "om";
		accp = stem .. last .. "ów";
		insp = stem .. last .. "ami";
		locp = stem .. last .. "ach";
		vocp = nomp_form;
	}
end
 
 
patterns["fem-a"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local genp_form = pargs[3]
	local nomp_form = pargs[4] -- not sure whether this is used anywhere
 
	local endings = make_lookup_table(
		"b c ch ci cz d dz dzi dż f g h j k l ł m n ni p r rz " ..
		"s si sł sm sn st sz t w z zd zi zł zm zn ż")
	if not endings[last] then
		-- suppress module error on the template page
		if not mw.ustring.match(last, "^{{{") then
			error("Unsupported word ending: " .. last)
		end
	end
 
	local soft_endings = make_lookup_table("ci dzi ni si zi")
 
	local gens_form = stem .. last .. "y"
	if soft_endings[last] then
		gens_form = stem .. last
	elseif (last == "g") or (last == "j") or (last == "k") or (last == "l") then
		gens_form = stem .. last .. "i"
	end
 
	local dats_lookup = {
		b = "bie";
		c = "cy"; ch = "sze"; ci = "ci"; cz = "czy";
		d = "dzie"; dz = "dzy"; dzi = "dzi"; ["dż"] = "dży";
		f = "fie";
		g = "dze";
		h = "że";
		j = "ji";
		k = "ce";
		l = "li"; ["ł"] = "le";
		m = "mie";
		n = "nie"; ni = "ni";
		p = "pie";
		r = "rze"; rz = "rzy";
		s = "sie"; si = "si"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie";
			st = "ście"; sz = "szy";
		t = "cie";
		w = "wie";
		z = "zie"; zd = "ździe"; zi = "zi"; ["zł"] = "źle"; zm = "źmie";
			zn = "źnie"; ["ż"] = "ży";
	}
	local dats_form = stem .. (dats_lookup[last] or last)
 
	local nomp_e_ending = make_lookup_table("c ci cz dz dzi dż j l ni rz si sz zi ż")
	local nomp_form = stem .. last .. "y"
	if (last == "g") or (last == "k") then
		nomp_form = stem .. last .. "i"
	elseif nomp_e_ending[last] then
		nomp_form = stem .. last .. "e"
	end
 
	if not genp_form or (genp_form == "") then
		if last == "j" then
			genp_form = "[[" .. stem .. "ji]]/[[" .. stem .. "yj]]"
		elseif last == "k" then
			if mw.ustring.match(stem, "[aąeęioóuy]$") then
				genp_form = stem .. "k"
			else
				genp_form = stem .. "ek"
			end
		else
			genp_form = stem .. last
		end	
	end
 
	return {
		nom = stem .. last .. "a";
		gen = gens_form;
		dat = dats_form;
		acc = stem .. last .. "ę";
		ins = stem .. last .. "ą";
		loc = dats_form;
		voc = stem .. last .. "o";
 
		nomp = nomp_form;
		genp = genp_form;
		datp = stem .. last .. "om";
		accp = nomp_form;
		insp = stem .. last .. "ami";
		locp = stem .. last .. "ach";
		vocp = nomp_form;
	}
end
 
patterns["fem-softcons"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local nomp_ending = pargs[3] or ""
	local noms_form = pargs[4]
 
	local endings = make_lookup_table("c ci cz dz dzi j l ni rz si sz wi zi ż")
	if not endings[last] then
		-- suppress module error on the template page
		if not mw.ustring.match(last, "^{{{") then
			error("Unsupported word ending: " .. last)
		end
	end
 
	-- nominative singular
	if not noms_form or (noms_form == "") then
		local noms_lookup = {
			ci = "ć"; dzi = "dź"; ni = "ń"; si = "ś"; zi = "ź"; }
		noms_form = stem .. (noms_lookup[last] or last)
	end
 
	-- genitive singular
	local gens_form = stem .. last
	local gens_y_ending = make_lookup_table("c cz dz sz rz ż")
	if last == "j" then
		gens_form = stem .. "i"
	end
	if last == "l" then
		gens_form = gens_form .. "i"
	elseif gens_y_ending[last] then
		gens_form = gens_form .. "y"
	end
 
	-- nominative plural
	-- this is trivial, but used in 3 places in the table
	local nomp_form = stem .. last .. nomp_ending;
 
	return {
		nom = noms_form;
		gen = gens_form;
		dat = gens_form;
		acc = noms_form;
		ins = stem .. last .. "ą";
		loc = gens_form;
		voc = gens_form;
 
		nomp = nomp_form;
		genp = gens_form;
		datp = stem .. last .. "om";
		accp = nomp_form;
		insp = stem .. last .. "ami";
		locp = stem .. last .. "ach";
		vocp = nomp_form;
	}
end
 
patterns["fem-adj"] = function (pargs)
	local word = pargs[1] or mw.title.getCurrentTitle().fullText
	if mw.ustring.match(word, "^{{{") then
		word = "przykładowa"
	end
 
	local decl = m_adj.autoinflect(word)
 
	return {
		nom = decl[2];
		gen = decl[7];
		dat = decl[7];
		acc = decl[11];
		ins = decl[11];
		loc = decl[7];
		voc = decl[15];
 
		nomp = decl[5];
		genp = decl[8];
		datp = decl[10];
		accp = decl[5];
		insp = decl[13];
		locp = decl[8];
		vocp = decl[5];
	}
end
 
patterns["ja"] = function (pargs)
	local stem = pargs[1]
	local yj = "yj"
	if pargs[2] and (pargs[2] ~= "") then
		yj = "ij"	
	end
 
	return {
		nom = stem .. "ja";
		gen = stem .. "ji";
		dat = stem .. "ji";
		acc = stem .. "ję";
		ins = stem .. "ją";
		loc = stem .. "ji";
		voc = stem .. "jo";
 
		nomp = stem .. "je";
		genp = "[[" .. stem .. "ji]]/[[" .. stem .. yj .. "]]";
		datp = stem .. "jom";
		accp = stem .. "je";
		insp = stem .. "jami";
		locp = stem .. "jach";
		vocp = stem .. "je";
	}
end
 
patterns["ia"] = function (pargs)
	local stem = pargs[1]
	local oldgenp = stem .. "ij"
	if mw.ustring.match(stem, "[dtr]$") then
		oldgenp = stem .. "yj"
	end
 
	return {
		nom = stem .. "ia";
		gen = stem .. "ii";
		dat = stem .. "ii";
		acc = stem .. "ię";
		ins = stem .. "ią";
		loc = stem .. "ii";
		voc = stem .. "io";
 
		nomp = stem .. "ie";
		genp = "[[" .. stem .. "ii]]/[[" .. oldgenp .. "]]";
		datp = stem .. "iom";
		accp = stem .. "ie";
		insp = stem .. "iami";
		locp = stem .. "iach";
		vocp = stem .. "ie";
	}
end
 
patterns["ka"] = function (pargs)
	local stem = pargs[1]
	local genp_form = stem .. "ek"
	-- omit the "e" if the last letter of the stem is a vowel
	if mw.ustring.match(stem, "[aąeęioóuy]$") then
		genp_form = stem .. "k"
	end
 
	return {
		nom = stem .. "ka";
		gen = stem .. "ki";
		dat = stem .. "ce";
		acc = stem .. "kę";
		ins = stem .. "ką";
		loc = stem .. "ce";
		voc = stem .. "ko";
 
		nomp = stem .. "ki";
		genp = genp_form;
		datp = stem .. "kom";
		accp = stem .. "ki";
		insp = stem .. "kami";
		locp = stem .. "kach";
		vocp = stem .. "ki";
	}
end
 
patterns["ść"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "ć";
		gen = stem .. "ci";
		dat = stem .. "ci";
		acc = stem .. "ć";
		ins = stem .. "cią";
		loc = stem .. "ci";
		voc = stem .. "ci";
 
		nomp = stem .. "ci";
		genp = stem .. "ci";
		datp = stem .. "ciom";
		accp = stem .. "ci";
		insp = stem .. "ciami";
		locp = stem .. "ciach";
		vocp = stem .. "ci";
	}
end
 
patterns["ni"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "ni";
		gen = stem .. "ni";
		dat = stem .. "ni";
		acc = stem .. "nię";
		ins = stem .. "nią";
		loc = stem .. "ni";
		voc = stem .. "ni";
 
		nomp = stem .. "nie";
		genp = stem .. "ń";
		datp = stem .. "niom";
		accp = stem .. "nie";
		insp = stem .. "niami";
		locp = stem .. "niach";
		vocp = stem .. "nie";
	}
end
 
patterns["neut-o"] = function (pargs)
	local stem = pargs[1]
	local last = pargs[2]
	local genp_form = pargs[3]
 
	local endings = make_lookup_table("b c ch d f g j k l ł m n p r s sł sm sn st t w z zd zł zm zn")
	if not endings[last] then
		-- suppress module error on the template page
		if not mw.ustring.match(last, "^{{{") then
			error("Unsupported word ending: " .. last)
		end
	end
 
	local inss_form = stem .. last .. "em"
	if last == "g" or last == "k" then
		inss_form = stem .. last .. "iem"
	end
 
	local locs_lookup = {
		b = "bie";
		c = "cu"; ch = "chu";
		d = "dzie";
		f = "fie";
		g = "gu";
		j = "ju";
		k = "ku";
		l = "lu"; ["ł"] = "le";
		m = "mie";
		n = "nie";
		p = "pie";
		r = "rze";
		s = "sie"; ["sł"] = "śle"; sm = "śmie"; sn = "śnie"; st = "ście";
		t = "cie";
		w = "wie";
		z = "zie"; zd = "ździe"; ["zł"] = "źle"; zm = "źmie"; zn = "źnie";
	}
 
	locs_form = stem .. (locs_lookup[last] or (last .. "u"))
 
	if not genp_form or genp_form == "" then
		genp_form = stem .. last
	end
 
	return {
		nom = stem .. last .. "o";
		gen = stem .. last .. "a";
		dat = stem .. last .. "u";
		acc = stem .. last .. "o";
		ins = inss_form;
		loc = locs_form;
		voc = stem .. last .. "o";
 
		nomp = stem .. last .. "a";
		genp = genp_form;
		datp = stem .. last .. "om";
		accp = stem .. last .. "a";
		insp = stem .. last .. "ami";
		locp = stem .. last .. "ach";
		vocp = stem .. last .. "a";
	}
end
 
patterns["neut-e"] = function (pargs)
	local stem = pargs[1]
	local genp_form = pargs[2] or stem
 
	return {
		nom = stem .. "e";
		gen = stem .. "a";
		dat = stem .. "u";
		acc = stem .. "e";
		ins = stem .. "em";
		loc = stem .. "u";
		voc = stem .. "e";
 
		nomp = stem .. "a";
		genp = genp_form;
		datp = stem .. "om";
		accp = stem .. "a";
		insp = stem .. "ami";
		locp = stem .. "ach";
		vocp = stem .. "a";
	}
end
 
patterns["neut-ę"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "ę";
		gen = stem .. "ęcia";
		dat = stem .. "ęciu";
		acc = stem .. "ę";
		ins = stem .. "ęciem";
		loc = stem .. "ęciu";
		voc = stem .. "ę";
 
		nomp = stem .. "ęta";
		genp = stem .. "ąt";
		datp = stem .. "ętom";
		accp = stem .. "ęta";
		insp = stem .. "ętami";
		locp = stem .. "ętach";
		vocp = stem .. "ęta";
	}
end
 
patterns["neut-mię"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "mię";
		gen = stem .. "mienia";
		dat = stem .. "mieniu";
		acc = stem .. "mię";
		ins = stem .. "mieniem";
		loc = stem .. "mieniu";
		voc = stem .. "mię";
 
		nomp = stem .. "miona";
		genp = stem .. "mion";
		datp = stem .. "mionom";
		accp = stem .. "miona";
		insp = stem .. "mionami";
		locp = stem .. "mionach";
		vocp = stem .. "miona";
	}
end
 
patterns["neut-adj"] = function (pargs)
	local word = pargs[1] or mw.title.getCurrentTitle().fullText
	if mw.ustring.match(word, "^{{{") then
		word = "przykładowa"
	end
 
	local decl = m_adj.autoinflect(word)
 
	return {
		nom = decl[3];
		gen = decl[6];
		dat = decl[9];
		acc = decl[3];
		ins = decl[12];
		loc = decl[12];
		voc = decl[3];
 
		nomp = decl[5];
		genp = decl[8];
		datp = decl[10];
		accp = decl[5];
		insp = decl[13];
		locp = decl[8];
		vocp = decl[5];
	}
end
 
patterns["nie"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "nie";
		gen = stem .. "nia";
		dat = stem .. "niu";
		acc = stem .. "nie";
		ins = stem .. "niem";
		loc = stem .. "niu";
		voc = stem .. "nie";
 
		nomp = stem .. "nia";
		genp = stem .. "ń";
		datp = stem .. "niom";
		accp = stem .. "nia";
		insp = stem .. "niami";
		locp = stem .. "niach";
		vocp = stem .. "nia";
	}
end
 
patterns["cie"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "cie";
		gen = stem .. "cia";
		dat = stem .. "ciu";
		acc = stem .. "cie";
		ins = stem .. "ciem";
		loc = stem .. "ciu";
		voc = stem .. "cie";
 
		nomp = stem .. "cia";
		genp = stem .. "ć";
		datp = stem .. "ciom";
		accp = stem .. "cia";
		insp = stem .. "ciami";
		locp = stem .. "ciach";
		vocp = stem .. "cia";
	}
end
 
patterns["um"] = function (pargs)
	local stem = pargs[1]
 
	return {
		nom = stem .. "um";
		gen = stem .. "um";
		dat = stem .. "um";
		acc = stem .. "um";
		ins = stem .. "um";
		loc = stem .. "um";
		voc = stem .. "um";
 
		nomp = stem .. "a";
		genp = stem .. "ów";
		datp = stem .. "om";
		accp = stem .. "a";
		insp = stem .. "ami";
		locp = stem .. "ach";
		vocp = stem .. "a";
	}
end
 
function export.template_decl_pattern(frame)
	local args = frame.args
	local pargs = frame:getParent().args
	local title = mw.title.getCurrentTitle()
 
	if not patterns[args[1]] then
		error("Invalid declension pattern: " .. args.pattern)
	end
 
	-- support "num" as fallback for "tantum" to match Latin templates
	local tantum = args.tantum or pargs.tantum or args.num or pargs.num
 
	local declinfo_auto
	if frame:getParent():getTitle() == title.fullText then
		declinfo_auto = patterns[args[1]]({ "{{{1}}}", "{{{2}}}", "{{{3}}}", "{{{4}}}", "{{{5}}}" })
	else
		declinfo_auto = patterns[args[1]](pargs)
	end
 
	-- support manual overrides
	local declinfo = {
		nom = args.noms or pargs.noms or declinfo_auto.nom;
		gen = args.gens or pargs.gens or declinfo_auto.gen;
		dat = args.dats or pargs.dats or declinfo_auto.dat;
		acc = args.accs or pargs.accs or declinfo_auto.acc;
		ins = args.inss or pargs.inss or declinfo_auto.ins;
		loc = args.locs or pargs.locs or declinfo_auto.loc;
		voc = args.vocs or pargs.vocs or declinfo_auto.voc;
 
		nomp = args.nomp or pargs.nomp or declinfo_auto.nomp;
		genp = args.genp or pargs.genp or declinfo_auto.genp;
		datp = args.datp or pargs.datp or declinfo_auto.datp;
		accp = args.accp or pargs.accp or declinfo_auto.accp;
		insp = args.insp or pargs.insp or declinfo_auto.insp;
		locp = args.locp or pargs.locp or declinfo_auto.locp;
		vocp = args.vocp or pargs.vocp or declinfo_auto.vocp;
	}
 
	if mw.isSubsting() then
		if tantum == "s" or tantum == "sg" then
			return ([=[
{{pl-decl-noun-sing
 | <!-- nom --> %s
 | <!-- gen --> %s
 | <!-- dat --> %s
 | <!-- acc --> %s
 | <!-- ins --> %s
 | <!-- loc --> %s
 | <!-- voc --> %s
}}]=]
			):format(
				declinfo.nom,
				declinfo.gen,
				declinfo.dat,
				declinfo.acc,
				declinfo.ins,
				declinfo.loc,
				declinfo.voc
			)
		elseif tantum == "p" or tantum == "pl" then
			return ([=[
{{pl-decl-noun-pl
 | <!-- nom --> %s
 | <!-- gen --> %s
 | <!-- dat --> %s
 | <!-- acc --> %s
 | <!-- ins --> %s
 | <!-- loc --> %s
 | <!-- voc --> %s
}}]=]
			):format(
				declinfo.nomp,
				declinfo.genp,
				declinfo.datp,
				declinfo.accp,
				declinfo.insp,
				declinfo.locp,
				declinfo.vocp
			)
		end
 
		return ([=[
{{pl-decl-noun
| <!-- nom sg --> %s
| <!-- nom pl --> %s
| <!-- gen sg --> %s
| <!-- gen pl --> %s
| <!-- dat sg --> %s
| <!-- dat pl --> %s
| <!-- acc sg --> %s
| <!-- acc pl --> %s
| <!-- ins sg --> %s
| <!-- ins pl --> %s
| <!-- loc sg --> %s
| <!-- loc pl --> %s
| <!-- voc sg --> %s
| <!-- voc pl --> %s
}}]=]):format(
			declinfo.nom, declinfo.nomp,
			declinfo.gen, declinfo.genp,
			declinfo.dat, declinfo.datp,
			declinfo.acc, declinfo.accp,
			declinfo.ins, declinfo.insp,
			declinfo.loc, declinfo.locp,
			declinfo.voc, declinfo.vocp
		)
	else
		if tantum == "s" or tantum == "sg" then
			return make_table_sg(declinfo, width, title.fullText) .. "[[Category:Polish singularia tantum]]"
		elseif tantum == "p" or tantum == "pl" then
			return make_table_pl(declinfo, width, title.fullText) .. "[[Category:Polish pluralia tantum]]"
		end
 
		return make_table_both(declinfo, width, title.fullText)
	end
end
 
return export