A modult a Modul:zu-nouns/doc lapon tudod dokumentálni

local m_utilities = require("Module:utilities")
local m_links = require("Module:links")
local m_common = require("Module:zu-common")

local lang = require("Module:languages").getByCode("zu")

local export = {}


local prefixes = {
	["1"] = {
		"^([uU][" .. m_common.diacritic .. "]*[mM][uU][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*[mM][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*)([nN].+)$",
		},
	["1a"] = {
		"^([uU][" .. m_common.diacritic .. "]*)(.+)$",
		},
	["2"] = {
		"^([aA][" .. m_common.diacritic .. "]*[bB][aeAE][" .. m_common.diacritic .. "]*)(.+)$",
		"^([aA][" .. m_common.diacritic .. "]*[bB])([" .. m_common.vowel .. ".+)$",
		},
	["2a"] = {
		"^([oO][" .. m_common.diacritic .. "]*)(.+)$",
		},
	["3"] = {
		"^([uU][" .. m_common.diacritic .. "]*[mM][uU][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*[mM][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*)([nN].+)$",
		},
	["4"] = {
		"^([iI][" .. m_common.diacritic .. "]*[mM][iI][" .. m_common.diacritic .. "]*)(.+)$",
		"^([iI][" .. m_common.diacritic .. "]*[mM])([" .. m_common.vowel .. "].+)$",
		},
	["5"] = {
		"^([iI][" .. m_common.diacritic .. "]*)(.+)$",
		},
	["6"] = {
		"^([aA][" .. m_common.diacritic .. "]*[mM][aA][" .. m_common.diacritic .. "]*)(.+)$",
		"^([aA][" .. m_common.diacritic .. "]*[mM])([" .. m_common.vowel .. "].+)$",
		},
	["7"] = {
		"^([iI][" .. m_common.diacritic .. "]*[sS][iI][" .. m_common.diacritic .. "]*)(.+)$",
		"^([iI][" .. m_common.diacritic .. "]*[sS])([" .. m_common.vowel .. "].+)$",
		},
	["8"] = {
		"^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*)(.+)$",
		"^([iI][" .. m_common.diacritic .. "]*[zZ])([" .. m_common.vowel .. "].+)$",
		},
	["9"] = {
		"^([iI][" .. m_common.diacritic .. "]*[mMnN])([^" .. m_common.vowel .. "].+)$",
		"^([iI][" .. m_common.diacritic .. "]*)([lLmMnN][" .. m_common.vowel .. "].+)$",
		},
	["10"] = {
		"^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*[mMnN])([^" .. m_common.vowel .. "].+)$",
		"^([iI][" .. m_common.diacritic .. "]*[zZ][iI][" .. m_common.diacritic .. "]*)([hHlLmMnN][" .. m_common.vowel .. "wW].+)$",
		},
	["11"] = {
		"^([uU][" .. m_common.diacritic .. "]*)(.+)$",
		--"^([uU][" .. m_common.diacritic .. "]*[lL][uU][" .. m_common.diacritic .. "]*)(.+)$",
		--"^([uU][" .. m_common.diacritic .. "]*[lL][wW])([" .. m_common.vowel .. "].+)$",
		},
	["14"] = {
		"^([uU][" .. m_common.diacritic .. "]*[bB][uU][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*[bB])([" .. m_common.vowel .. "].+)$",
		"^([uU][" .. m_common.diacritic .. "]*[tT][sS][hH][wW]?)([aA].+)$",
		},
	["15"] = {
		"^([uU][" .. m_common.diacritic .. "]*[kK][uU][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*[kK][wW])([" .. m_common.vowel .. "].+)$",
		},
	["17"] = {
		"^([uU][" .. m_common.diacritic .. "]*[kK][uU][" .. m_common.diacritic .. "]*)(.+)$",
		"^([uU][" .. m_common.diacritic .. "]*[kK][wW])([" .. m_common.vowel .. "].+)$",
		},
}


local function split_prefix(word, class, tone)
	if not prefixes[class] then
		error("Invalid class \"" .. class .. "\".")
	end

	local prefix, stem
	word = mw.ustring.toNFD(word)
	
	for _, pattern in ipairs(prefixes[class]) do
		prefix, stem = mw.ustring.match(word, pattern)
		
		if prefix then
			break
		end
	end
	
	if not prefix then
		if mw.title.getCurrentTitle().nsText ~= "Template" then
			error("Word \"" .. word .. "\" does not match any valid prefix of class \"" .. class .. "\".")
		end
	else
		local sstem = m_common.split_syllables(stem)
		local stone = mw.text.split(tone or mw.ustring.rep("L", #sstem), "")
		
		if #sstem ~= #stone then
			error("The word \"" .. stem .. "\" and the tone pattern " .. tone .. " have different numbers of syllables.")
		end
		
		return mw.ustring.toNFC(prefix), mw.ustring.toNFC(stem)
	end
end


function makeSortKey(word, class)
	local prefix, stem = split_prefix(word, class)
	
	return lang:makeSortKey(stem or word)
end


local function simple(data, base, prefix, class)
	base = lang:makeEntryName(base)
	
	if prefix then
		prefix = prefix .. "_"
	else
		prefix = ""
	end
	
	if class == "2a" then
		data.forms[prefix .. "simp"] = {"b" .. base}
	elseif class == "5" then
		data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^i", "li"))}
	elseif class == "11" then
		data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^u", "lu"))}
	else
		data.forms[prefix .. "simp"] = {(mw.ustring.gsub(base, "^[aiu]%-?", ""))}
	end
end


local function locative_ku(data, base, prefix, tone)
	base = lang:makeEntryName(base)
	
	if prefix then
		prefix = prefix .. "_"
	else
		prefix = ""
	end
	
	if mw.ustring.find(base, "^[au]") then
		data.forms[prefix .. "loc"]  = {m_common.apply_tone("ku" .. mw.ustring.gsub(base, "^[au]", ""), tone)}
	elseif mw.ustring.find(base, "^[" .. m_common.vowel .. "]") then
		data.forms[prefix .. "loc"]  = {m_common.apply_tone("k" .. base)}
	elseif base == "mi" or base == "thi" or base == "ni" then
		data.forms[prefix .. "loc"] = {m_common.apply_tone("ki" .. base, tone)}
	else
		data.forms[prefix .. "loc"]  = {m_common.apply_tone("ku" .. base, tone)}
	end
end


local function locative_e(data, base, prefix, class)
	base = lang:makeEntryName(base)
	
	if prefix then
		prefix = prefix .. "_"
	else
		prefix = ""
	end
	
	if mw.ustring.find(base, "^u") and class == "11" then
		base = mw.ustring.gsub(base, "^u", "o")
	else
		base = mw.ustring.gsub(base, "^[aiu]", "e")
	end
	
	data.forms[prefix .. "loc"]  = {base}
end


local function locative_extend(base)
	base = lang:makeEntryName(base)
	
	base = mw.ustring.gsub(base, "[aou]$", {["a"] = "e", ["o"] = "we", ["u"] = "wi"}) .. "ni"
	
	base = mw.ustring.gsub(base, "mbw([ei]ni)$", "nj%1")
	base = mw.ustring.gsub(base, "mpw([ei]ni)$", "ntsh%1")
	base = mw.ustring.gsub(base, "bhw([ei]ni)$", "j%1")
	base = mw.ustring.gsub(base, "[bp]w([ei]ni)$", "tsh%1")
	base = mw.ustring.gsub(base, "phw([ei]ni)$", "sh%1")
	base = mw.ustring.gsub(base, "mw([ei]ni)$", "ny%1")
	base = mw.ustring.gsub(base, "([fvw])w([ei]ni)$", "%1%2")
	
	return base
end


local function copulative(data, base, prefix, class, tone)
	base = lang:makeEntryName(base)
	
	if prefix then
		prefix = prefix .. "_"
	else
		prefix = ""
	end
	
	if mw.ustring.find(base, "^u") and class == "11" then
		data.forms[prefix .. "cop"]  = {m_common.apply_tone("w" .. base)}
	elseif mw.ustring.find(base, "^[aou]") then
		data.forms[prefix .. "cop"]  = {m_common.apply_tone("ng" .. base)}
	elseif mw.ustring.find(base, "^i") then
		data.forms[prefix .. "cop"]  = {m_common.apply_tone("y" .. base)}
	elseif base == "we" or base == "ye" then
		data.forms[prefix .. "cop"] = {m_common.apply_tone("ngu" .. base, tone)}
	else
		data.forms[prefix .. "cop"]  = {m_common.apply_tone("yi" .. base, tone)}
	end
end


local function possessive(data, base, prefix, ka, tone)
	base = lang:makeEntryName(base)
	
	local tone_subst
	if tone then
		tone_subst = "H" .. tone
	end
	
	if prefix then
		prefix = prefix .. "_"
	else
		prefix = ""
	end
	
	if ka then
		base = mw.ustring.gsub(base, "^u", "")
		
		data.forms[prefix .. "poss_mod_c1" ] = {  "ka" .. base}
		data.forms[prefix .. "poss_mod_c2" ] = {"baka" .. base}
		data.forms[prefix .. "poss_mod_c3" ] = {  "ka" .. base}
		data.forms[prefix .. "poss_mod_c4" ] = {  "ka" .. base}
		data.forms[prefix .. "poss_mod_c5" ] = {"lika" .. base}
		data.forms[prefix .. "poss_mod_c6" ] = {  "ka" .. base}
		data.forms[prefix .. "poss_mod_c7" ] = {"sika" .. base}
		data.forms[prefix .. "poss_mod_c8" ] = {"zika" .. base}
		data.forms[prefix .. "poss_mod_c9" ] = {  "ka" .. base}
		data.forms[prefix .. "poss_mod_c10"] = {"zika" .. base}
		data.forms[prefix .. "poss_mod_c11"] = {"luka" .. base}
		data.forms[prefix .. "poss_mod_c14"] = {"buka" .. base}
		data.forms[prefix .. "poss_mod_c15"] = {"kuka" .. base}
		data.forms[prefix .. "poss_mod_c17"] = {"kuka" .. base}
		
		data.forms[prefix .. "poss_subst_c1" ] = {  "oka" .. base}
		data.forms[prefix .. "poss_subst_c2" ] = {"abaka" .. base}
		data.forms[prefix .. "poss_subst_c3" ] = {  "oka" .. base}
		data.forms[prefix .. "poss_subst_c4" ] = {  "eka" .. base}
		data.forms[prefix .. "poss_subst_c5" ] = {"elika" .. base}
		data.forms[prefix .. "poss_subst_c6" ] = {  "aka" .. base}
		data.forms[prefix .. "poss_subst_c7" ] = {"esika" .. base}
		data.forms[prefix .. "poss_subst_c8" ] = {"ezika" .. base}
		data.forms[prefix .. "poss_subst_c9" ] = {  "eka" .. base}
		data.forms[prefix .. "poss_subst_c10"] = {"ezika" .. base}
		data.forms[prefix .. "poss_subst_c11"] = {"oluka" .. base}
		data.forms[prefix .. "poss_subst_c14"] = {"obuka" .. base}
		data.forms[prefix .. "poss_subst_c15"] = {"okuka" .. base}
		data.forms[prefix .. "poss_subst_c17"] = {"okuka" .. base}
	else
		local w
		if mw.ustring.find(base, "^[ou]") then
			base = mw.ustring.gsub(base, "^u", "o")
			w = ""
		elseif mw.ustring.find(base, "^[ai]") then
			base = mw.ustring.gsub(base, "^i", "e")
			w = "w"
		else
			base = "a" .. base
			w = "w"
		end
		
		data.forms[prefix .. "poss_mod_c1" ] = {m_common.apply_tone("w" .. base, tone)}
		data.forms[prefix .. "poss_mod_c2" ] = {m_common.apply_tone("b" .. base, tone)}
		data.forms[prefix .. "poss_mod_c3" ] = {m_common.apply_tone("w" .. base, tone)}
		data.forms[prefix .. "poss_mod_c4" ] = {m_common.apply_tone("y" .. base, tone)}
		data.forms[prefix .. "poss_mod_c5" ] = {m_common.apply_tone("l" .. base, tone)}
		data.forms[prefix .. "poss_mod_c6" ] = {m_common.apply_tone(base, tone)}
		data.forms[prefix .. "poss_mod_c7" ] = {m_common.apply_tone("s" .. base, tone)}
		data.forms[prefix .. "poss_mod_c8" ] = {m_common.apply_tone("z" .. base, tone)}
		data.forms[prefix .. "poss_mod_c9" ] = {m_common.apply_tone("y" .. base, tone)}
		data.forms[prefix .. "poss_mod_c10"] = {m_common.apply_tone("z" .. base, tone)}
		data.forms[prefix .. "poss_mod_c11"] = {m_common.apply_tone("l" .. w .. base, tone)}
		data.forms[prefix .. "poss_mod_c14"] = {m_common.apply_tone("b" .. base, tone)}
		data.forms[prefix .. "poss_mod_c15"] = {m_common.apply_tone("k" .. w .. base, tone)}
		data.forms[prefix .. "poss_mod_c17"] = {m_common.apply_tone("k" .. w .. base, tone)}
		
		data.forms[prefix .. "poss_subst_c1" ] = {m_common.apply_tone("ow" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c2" ] = {m_common.apply_tone("ab" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c3" ] = {m_common.apply_tone("ow" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c4" ] = {m_common.apply_tone("ey" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c5" ] = {m_common.apply_tone("el" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c6" ] = {m_common.apply_tone("aw" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c7" ] = {m_common.apply_tone("es" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c8" ] = {m_common.apply_tone("ez" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c9" ] = {m_common.apply_tone("ey" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c10"] = {m_common.apply_tone("ez" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c11"] = {m_common.apply_tone("ol" .. w .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c14"] = {m_common.apply_tone("ob" .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c15"] = {m_common.apply_tone("ok" .. w .. base, tone_subst)}
		data.forms[prefix .. "poss_subst_c17"] = {m_common.apply_tone("ok" .. w .. base, tone_subst)}
	end
end


local function forms(data, n, class, base, shortloc, loc)
	-- Full form
	data.forms[n .. "_full"] = {base}
	
	-- Simple form
	simple(data, base, n, class)
	
	-- Locative
	if class == "1" or class == "1a" or class == "2" or class == "2a" then
		locative_ku(data, base, n)
	elseif shortloc then
		locative_e(data, base, n, class)
	elseif loc then
		data.forms[n .. "_loc"]  = {loc}
	else
		local loc = locative_extend(base)
		locative_e(data, loc, n, class)
	end
	
	-- Copulative
	copulative(data, base, n, class)
	
	-- Possessive forms
	possessive(data, base, n, class == "1a")
end


function export.noun(frame)
	local params = {
		[1] = {default = mw.title.getCurrentTitle().nsText == "Template" and "L" or nil},
		[2] = {required = true, default = "1"},
		[3] = {default = mw.title.getCurrentTitle().nsText == "Template" and "2" or nil},
		[4] = {default = mw.title.getCurrentTitle().nsText == "Template" and "abantu" or nil},
		
		["shortloc"] = {type = "boolean"},
		["loc_sg"] = {default = false},
		["loc_pl"] = {default = false}
		}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {forms = {}, info = "", categories = {lang:getCanonicalName() .. " class " .. args[2] .. " nouns"}}
	
	if args[1] then
		table.insert(data.categories, lang:getCanonicalName() .. " nouns with tone " .. args[1])
	else
		table.insert(data.categories, "Requests for tone in " .. lang:getCanonicalName() .. " noun entries")
	end
	
	
	data.info = "class " .. args[2] .. (args[3] and "/" .. args[3] or "")
	
	if args[2] == "2" or args[2] == "2a" or args[2] == "4" or args[2] == "6" or args[2] == "8" or args[2] == "10" then
		if args[3] or args[4] then
			error("Nouns of plural classes cannot have plural forms.")
		end
		
		forms(data, "pl", args[2], mw.title.getCurrentTitle().subpageText, args["shortloc"], args["loc_pl"])
		table.insert(data.categories, lang:getCanonicalName() .. " pluralia tantum")
	else
		forms(data, "sg", args[2], mw.title.getCurrentTitle().subpageText, args["shortloc"], args["loc_sg"])
		
		-- Plural
		if args[3] then
			forms(data, "pl", args[3], args[4], args["shortloc"], args["loc_pl"])
		else
			table.insert(data.categories, lang:getCanonicalName() .. " singularia tantum")
		end
	end
	
	if args["shortloc"] then
		data.info = data.info .. ", short locative"
		table.insert(data.categories, lang:getCanonicalName() .. " nouns with short locative")
	end
	
	return make_table(data) .. m_utilities.format_categories(data.categories, lang, makeSortKey(mw.title.getCurrentTitle().subpageText, args[2]))
end


function export.pron(frame)
	local params = {
		[1] = {},
		[2] = {},
		[3] = {},
		[4] = {},
		[5] = {},
		
		["head"] = {},
		}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {forms = {}, info = "", categories = {}}
	data.pron = true
	if args[1] then
		table.insert(data.categories, lang:getCanonicalName() .. " pronouns with tone " .. args[1])
	else
		table.insert(data.categories, "Requests for tone in " .. lang:getCanonicalName() .. " pronoun entries")
	end
	
	local base  = m_common.apply_tone(args["head"] or mw.title.getCurrentTitle().subpageText, args[1])
	local stem  = args[2] and m_common.apply_tone(args[2], args[3]) or base
	local pstem = args[4] and m_common.apply_tone(args[4], args[5]) or stem
	
	data.info = "stem " .. m_links.full_link({lang = lang, alt = "-" .. stem}, "term")
	
	if args[4] then
		data.info = data.info .. ", poss. stem " .. m_links.full_link({lang = lang, alt = "-" .. pstem}, "term")
	end
	
	data.forms["full"] = {base}

	if args[3] then
		locative_ku(data, stem, nil, "H" .. args[3])
		copulative(data, stem, nil, nil, "H" .. args[3])
	else
		locative_ku(data, stem)
		copulative(data, stem)
	end
		
	if stem == "mi" or stem == "we" then
		possessive(data, pstem, nil, nil, "HL")
	elseif pstem == "ithu" or stem == "inu" then
		possessive(data, pstem, nil, nil, "FL")
	else
		if args[5] then
			possessive(data, pstem, nil, nil, "FL")
		else
			possessive(data, pstem)
		end
	end
	
	return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end


-- Make the table
function make_table(data)
	local function repl(param)
		if param == "info" then
			return mw.getContentLanguage():ucfirst(data.info or "")
		end
		
		local form = data.forms[param]
		
		if not form or #form == 0 then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			table.insert(ret, m_links.full_link({lang = lang, term = subform}))
		end
		
		return table.concat(ret, ", ")
	end
	
	local names = {
		["full"] = "full form",
		["simp"] = "simple form",
		["loc"]  = "locative",
		["cop"]  = "copulative",
		
		["sg"] = "singular",
		["pl"] = "plural",
		
		["mod"] = "modifier",
		["subst"] = "substantive",
		
		["c1"] = "class 1",
		["c2"] = "class 2",
		["c3"] = "class 3",
		["c4"] = "class 4",
		["c5"] = "class 5",
		["c6"] = "class 6",
		["c7"] = "class 7",
		["c8"] = "class 8",
		["c9"] = "class 9",
		["c10"] = "class 10",
		["c11"] = "class 11",
		["c14"] = "class 14",
		["c15"] = "class 15",
		["c17"] = "class 17",
	}
	
	local columns = {"mod", "subst"}
	local numbers = {"sg", "pl"}
	local cases = {"full", "simp", "loc", "cop"}
	local classes = {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c14", "c15", "c17"}
	
	if data.pron then
		numbers = {""}
		cases = {"full", "loc", "cop"}
	end
	
	local wikicode = {}
	
	table.insert(wikicode, "{| class=\"wikitable inflection-table vsSwitcher\" data-toggle-category=\"inflection\" style=\"border-style: double; border-width: 3px; margin: 0;\"")
	table.insert(wikicode, "|-")
	table.insert(wikicode, "! class=\"vsToggleElement\" style=\"background: #CCC; text-align: left;\" colspan=\"" .. tostring(#numbers * #columns + 1) .. "\" | {{{info}}}")
	
	if not data.pron then
		table.insert(wikicode, "|- class=\"vsShow\"")
		table.insert(wikicode, "|")
		
		for _, number in ipairs(numbers) do
			table.insert(wikicode, "! " .. mw.getContentLanguage():ucfirst(names[number]))
		end
	end
	
	for _, case in ipairs({"full", "loc"}) do
		table.insert(wikicode, "|- class=\"vsShow\"")
		table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage():ucfirst(names[case]))
		
		if data.pron then
			table.insert(wikicode, "| style=\"min-width: 10em;\" | {{{" .. case .. "}}}")
		else
			for _, number in ipairs(numbers) do
				table.insert(wikicode, "| style=\"min-width: 10em;\" | {{{" .. number .. "_" .. case .. "}}}")
			end
		end
	end
	
	if not data.pron then
		table.insert(wikicode, "|- class=\"vsHide\"")
		table.insert(wikicode, "|")
		
		for _, number in ipairs(numbers) do
			table.insert(wikicode, "! colspan=\"" .. tostring(#columns) .. "\" | " .. mw.getContentLanguage():ucfirst(names[number]))
		end
	end
	
	for _, case in ipairs(cases) do
		table.insert(wikicode, "|- class=\"vsHide\"")
		table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage():ucfirst(names[case]))
		
		if data.pron then
			table.insert(wikicode, "| colspan=\"" .. tostring(#columns) .. "\" | {{{" .. case .. "}}}")
		else
			for _, number in ipairs(numbers) do
				table.insert(wikicode, "| colspan=\"" .. tostring(#columns) .. "\" | {{{" .. number .. "_" .. case .. "}}}")
			end
		end
	end
	
	table.insert(wikicode, "|- class=\"vsHide\"")
	table.insert(wikicode, "! colspan=\"" .. tostring(#numbers * #columns + 1) .. "\" | Possessive forms")
	
	if not data.pron then
		table.insert(wikicode, "|- class=\"vsHide\"")
		table.insert(wikicode, "|")
		
		for _, number in ipairs(numbers) do
			table.insert(wikicode, "! colspan=\"" .. tostring(#columns) .. "\" | " .. mw.getContentLanguage():ucfirst(names[number]))
		end
	end
	
	table.insert(wikicode, "|- class=\"vsHide\"")
	table.insert(wikicode, "|")
	
	for _, number in ipairs(numbers) do
		for _, column in ipairs(columns) do
			table.insert(wikicode, "! style=\"min-width: 8em;\" | " .. mw.getContentLanguage():ucfirst(names[column]))
		end
	end
	
	for _, class in ipairs(classes) do
		table.insert(wikicode, "|- class=\"vsHide\"")
		table.insert(wikicode, "! " .. mw.getContentLanguage():ucfirst(names[class]))
		
		for _, number in ipairs(numbers) do
			for _, column in ipairs(columns) do
				table.insert(wikicode, "| {{{" .. (data.pron and "" or number .. "_") .. "poss_" .. column .. "_" .. class .. "}}}")
			end
		end
	end
	
	table.insert(wikicode, "|}")
	
	wikicode = table.concat(wikicode, "\n")
	
	return mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl)
end


return export