A modult a Modul:category tree/name cat/doc lapon tudod dokumentálni

local export = {}

-- Category object

local Category = {}
Category.__index = Category


function Category.new_main(frame)
	local params = {
		[1] = {required = true},
		[2] = {required = true},
		[3] = {required = true},
	}
	
	args = require("Module:parameters").process(frame:getParent().args, params)
	
	return Category.new({lang = args[1], source = args[2], nametype = args[3]})
end


function Category.new(info)
	for key, val in pairs(info) do
		if not (key == "nametype" or key == "lang" or key == "source") then
			error("The parameter \"" .. key .. "\" was not recognized. "
				.."Recognized parameters are \"nametype\", \"lang\", and \"source\".")
		end
	end
	
	if not info.nametype then
		error("No name type was specified.")
	end
	
	if not info.lang then
		error("No current language code was specified.")
	end
	
	if not info.source then
		error("No source was specified.")
	end
	
	local self = setmetatable({}, Category)
	self._info = info

	local special_sources
	if info.nametype:find("given names") then
		special_sources = require("Module:table").listToSet({"surnames",
			"place names", "coinages", "the Bible"
		})
	elseif info.nametype:find("surnames") then
		special_sources = require("Module:table").listToSet({
			"given names", "place names", "occupations", "patronymics",
			"common nouns", "nicknames"
		})
	else
		special_sources = {}
	end
	
	self._lang = type(info.lang) == "table" and info.lang.getCode and info.lang
		or require("Module:languages").getByCode(info.lang, true)
	self._source = type(info.source) == "table" and info.source.getCode and info.source
		or special_sources[info.source] and info.source
		or info.source:find(" languages$") and require("Module:families").getByCanonicalName(info.source:gsub(" languages$", ""))
		or require("Module:languages").getByCode(info.source, true, "allow etym")
	
	return self
end

export.new = Category.new
export.new_main = Category.new_main


function Category:getInfo()
	return self._info
end


local function getSourceText(source)
	local sourcetext = source
	if type(source) == "table" then
		if source:getType() == "family" then
			sourcetext = source:getCanonicalName() .. " languages"
		else
			sourcetext = source:getCanonicalName()
		end
	end
	return sourcetext
end


function Category:getBreadcrumbName()
	return "from " .. getSourceText(self._source)
end


function Category:getDataModule()
	return "Module:category tree/name cat"
end


function Category:canBeEmpty()
	return false
end


function Category:isHidden()
	return false
end


local function getCategoryNameForSource(self, source)
	return mw.getContentLanguage():ucfirst(self._lang:getCanonicalName()) .. " " .. self._info.nametype .. " from " .. getSourceText(source)
end


function Category:getCategoryName()
	return getCategoryNameForSource(self, self._source)
end


function Category:getDescription()
	local origintext, addltext
	if self._source == "surnames" then
		origintext = "transferred from surnames"
	elseif self._source == "given names" then
		origintext = "transferred from given names"
	elseif self._source == "nicknames" then
		origintext = "transferred from nicknames"
	elseif self._source == "place names" then
		origintext = "transferred from place names"
		addltext = " For place names that are also surnames, see [[:Category:" .. getCategoryNameForSource(self, "surnames") .. "]]."
	elseif self._source == "common nouns" then
		origintext = "transferred from common nouns"
	elseif self._source == "coinages" then
		origintext = "originating as coinages"
		addltext = " These are names of artificial origin, names based on fictional characters, combinations of two words or names or backward spellings. Names of uncertain origin can also be placed here if there is a strong suspicion that they are coinages."
	elseif self._source == "occupations" then
		origintext = "originating as occupations"
	elseif self._source == "patronymics" then
		origintext = "originating as patronymics"
	elseif self._source == "the Bible" then
		-- Hack esp. for Hawaiian names. We should consider changing them to
		-- have the source as Biblical Hebrew and mention the derivation from
		-- the Bible some other way.
		origintext = "originating from the Bible"
	elseif type(self._source) == "string" then
		error("Unrecognized string source \"" .. self._source .. "\", should be special-cased or not allowed")
	else
		local catname = self._source:getCategoryName()
		origintext = "of [[:Category:" .. catname .. "|" .. catname .. "]] origin"
		if self._source:getCode() == self._lang:getCode() then
			addltext = " These are names derived from common nouns, local mythology, etc."
		end
	end
	return self._lang:getCanonicalName() .. " " .. self._info.nametype .. " " .. origintext ..
		". (This includes names derived at an older stage of the language.)" .. (
		addltext or "")
end

-- If one of the following families occurs in any of the ancestral families
-- of a given language, use it instead of the three-letter parent
-- (or immediate parent if no three-letter parent).
local high_level_families = require("Module:table").listToSet {
	-- Indo-European
	"gem", -- Germanic (for gme, gmq, gmw)
	"inc", -- Indic (for e.g. pra = Prakrit)
	"ine-ana", -- Anatolian (don't keep going to ine)
	"ine-toc", -- Tocharian (don't keep going to ine)
	"ira", -- Iranian (for e.g. xme = Median, xsc = Scythian)
	"sla", -- Slavic (for zle, zls, zlw)
	-- Other
	"ath", -- Athabaskan (for e.g. apa = Apachean)
	"poz", -- Malayo-Polynesian (for e.g. pqe = Eastern Malayo-Polynesian)
	"cau-nwc", -- Northwest Caucasian
	"cau-nec", -- Northeast Caucasian
}

local function find_high_level_family(lang)
	local family = lang:getFamily()
	-- (1) If no family, return nil (e.g. for Pictish).
	if not family then
		return nil
	end
	-- (2) See if any ancestor family is in `high_level_families`.
	-- if so, return it.
	local high_level_family = family
	while high_level_family do
		local high_level_code = high_level_family:getCode()
		if high_level_code == "qfa-not" then
			-- "not a family"; its own parent, causing an infinite loop.
			-- Break rather than return so we get categories like
			-- [[Category:English female given names from sign languages]] and
			-- [[Category:English female given names from constructed languages]].
			break
		end
		if high_level_families[high_level_code] then
			return high_level_family
		end
		high_level_family = high_level_family:getFamily()
	end
	-- (3) If the family is of the form 'FOO-BAR', see if 'FOO' is a family.
	-- If so, return it.
	local basic_family = family:getCode():match("^(.-)%-.*$")
	if basic_family then
		basic_family = require("Module:families").getByCode(basic_family)
		if basic_family then
			return basic_family
		end
	end
	-- (4) Fall back to just the family itself.
	return family
end

function Category:getParents()
	local categories = {}
	local lang = self._info.lang
	local nametype = self._info.nametype
	
	table.insert(categories,
		{name = require("Module:category tree/poscatboiler").new{code = lang, label = nametype},
			sort = getSourceText(self._source)})
	if type(self._source) == "table" then
		table.insert(categories,
			{name = require("Module:category tree/derived cat").new{code = lang, label = self._source:getCode()},
				sort = " "})
		-- If the source is a regular language, put it in a parent category for
		-- the high-level language family, e.g. for "Russian female given names
		-- from German", put it in a parent category "Russian female given names
		-- from Germanic languages" (skipping over West Germanic languages).
		--
		-- If the source is an etymology language, put it in a parent category
		-- for the parent non-etymology language, e.g. for
		-- "French male given names from Gascon", put it in a parent category
		-- "French male given names from Occitan".
		--
		-- If the source is a family, put it in a parent category for the
		-- parent family.
		local sourcetype = self._source:getType()
		if sourcetype == "family" then
			local parent_family = self._source:getFamily()
			if parent_family then
				table.insert(categories,
					{name = Category.new{lang = lang, nametype = nametype, source = parent_family},
					sort = self._source:getCanonicalName()
				})
			end
		elseif sourcetype == "etymology language" then
			local source_parent = require("Module:languages").getNonEtymological(self._source)
			table.insert(categories,
				{name = Category.new{lang = lang, nametype = nametype, source = source_parent},
				sort = self._source:getCanonicalName()
			})
		else
			local high_level_family = find_high_level_family(self._source)
			if high_level_family then -- may not exist, e.g. for Pictish
				table.insert(categories,
					{name = Category.new{lang = lang, nametype = nametype, source = high_level_family},
					sort = self._source:getCanonicalName()
				})
			end
		end
	end

	local gender, label = nametype:match("^(f?e?male) (given names)$")
	if not gender then
		gender, label = nametype:match("^(unisex) (given names)$")
	end
	if gender then
		table.insert(categories,
			{name = Category.new{lang = lang, nametype = label, source = self._source},
			sort = gender
		})
	end
	
	return categories
end

function Category:getChildren()
	return nil
end


function Category:getUmbrella()
	return nil
end


return export

-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet: