Модул:category tree/langcatboiler

Документација модула[прикажи] [уреди] [историја] [освежи]

This module implements {{langcatboiler}}. The documentation here describes how the module works, and how to add, modify or remove information from the category tree. For information on how to use the template itself, see its documentation.

This module does not use labels. Effectively, there is only one label, whose data is hard-coded into the module.

local export = {}

local function makeCategoryLink(object)
	return "[[:Категорија:" .. object:getCategoryName() .. "|" .. object:getCanonicalName() .. "]]"
end

local function linkbox(lang, setwiki, setwikt, setsister, entryname)
	local wiktionarylinks = "''None.''"
	
	local canonicalName = lang:getCanonicalName()
	local wikimediaLanguages = lang:getWikimediaLanguages()
	local categoryName = lang:getCategoryName()
	local wikipediaArticle = setwiki or lang:getWikipediaArticle()
	
	if setwikt then
		require "Модул:debug".track "langcatboiler/setwikt"
		if setwikt == "-" then
			require "Модул:debug".track "langcatboiler/setwikt/hyphen"
		end
	end
	
	if setwikt ~= "-" and wikimediaLanguages and wikimediaLanguages[1] then
		wiktionarylinks = {}
		
		for _, wikimedialang in ipairs(wikimediaLanguages) do
			table.insert(wiktionarylinks,
				(wikimedialang:getCanonicalName() ~= canonicalName and "(''" .. wikimedialang:getCanonicalName() .. "'') " or "") ..
				"'''[[:" .. wikimedialang:getCode() .. ":|" .. wikimedialang:getCode() .. ".wiktionary.org]]'''")
		end
		
		wiktionarylinks = table.concat(wiktionarylinks, "<br/>")
	end
	
	local plural = wikimediaLanguages[2] and "s" or ""
	
	return table.concat{
[=[<div style="clear: right; border: solid #aaa 1px; margin: 1 1 1 1; background: #f9f9f9; width: 270px; padding: 5px; margin: 5px; text-align: left; float: right">
<div style="text-align: center; margin-bottom: 10px; margin-top: 5px">''']=], categoryName, [=['''</div>

{| style="font-size: 90%; background: #f9f9f9;"
|-
| style="vertical-align: middle; height: 35px; width: 35px;" | [[File:Wiktionary-logo-v2.svg|35px|none|Викиречник]]
|| '']=], categoryName, [=[ издање]=], plural, [=[ Викиречник''
|-
| colspan="2" style="padding-left: 10px; border-bottom: 1px solid lightgray;" | ]=], wiktionarylinks, [=[

|-
| style="vertical-align: middle; height: 35px" | [[File:Wikipedia-logo.png|35px|none|Википедија]]
|| ''Википедијин чланак о ]=], categoryName, [=[''
|-
| colspan="2" style="padding-left: 10px; border-bottom: 1px solid lightgray;" | ]=], (setwiki == "-" and "''None.''" or "'''[[w:" .. wikipediaArticle .. "|" .. wikipediaArticle .. "]]'''"), [=[

|-
| style="vertical-align: middle; height: 35px" | [[File:Wikimedia-logo.svg|35px|none|Wikimedia Commons]]
|| ''Links related to ]=], categoryName, [=[ in sister projects at Wikimedia Commons''
|-
| colspan="2" style="padding-left: 10px; border-bottom: 1px solid lightgray;" | ]=], (setsister == "-" and "''None.''" or "'''[[commons:Категорија:" .. (setsister or categoryName) .. "|" .. (setsister or categoryName) .. "]]'''"), [=[

|-
| style="vertical-align: middle; height: 35px" | [[File:Crystal kfind.png|35px|none|Considerations]]
|| ]=], categoryName, [=[ considerations
|-
| colspan="2" style="padding-left: 10px; border-bottom: 1px solid lightgray;" | '''[[Викиречник:О ]=], canonicalName, [=[]]'''
|-
| style="vertical-align: middle; height: 35px" | [[File:Incomplete list.svg|35px|none|Индекс]]
|| ]=], categoryName, [=[ index
|-
| colspan="2" style="padding-left: 10px; border-bottom: 1px solid lightgray;" | '''[[Индекс:]=], canonicalName, [=[]]'''
|-
| style="vertical-align: middle; height: 35px" | [[File:Open book nae 02.svg|35px|none|Entry]]
|| ]=], categoryName, [=[ entry
|-
| colspan="2" style="padding-left: 10px;" | ''']=], require("Модул:links").full_link({lang = require("Модул:languages").getByCode("sr"), term = entryname or canonicalName}), [=['''
|}
</div>]=]
}
end

local function edit_link(title, text)
	return '<span class="plainlinks">['
		.. tostring(mw.uri.fullUrl(title, { action = "edit" }))
		.. ' ' .. text .. ']</span>'
end

-- Should perhaps use wiki syntax.
local function infobox(lang)
	local ret = {}
	
	table.insert(ret, '<table class="wikitable language-category-info"')
	
	if type(lang.getRawData) == "function" then
		local raw_data = lang:getRawData()
		if raw_data then
			local replacements = {
				[1] = "canonical-name",
				[2] = "wikidata-item",
				[3] = "family",
			}
			local function replacer(letter1, letter2)
				return letter1:lower() .. "-" .. letter2:lower()
			end
			-- For each key in the language data modules, returns a descriptive
			-- kebab-case version (containing ASCII lowercase words separated
			-- by hyphens).
			local function kebab_case(key)
				key = replacements[key] or key
				key = key:gsub("(%l)(%u)", replacer):gsub("(%l)_(%l)", replacer)
				return key
			end
			local function html_attribute_encode(str)
				str = mw.text.jsonEncode(str)
					:gsub('"', "&quot;")
					-- & in attributes is automatically escaped.
					-- :gsub("&", "&amp;")
					:gsub("<", "&lt;")
					:gsub(">", "&gt;")
				return str
			end
			pcall(function ()
				table.insert(ret, ' data-code="' .. lang:getCode() .. '"')
				for k, v in require("Модул:table").sortedPairs(lang:getRawData()) do
					table.insert(ret, " data-" .. kebab_case(k)
						.. '="'
						.. html_attribute_encode(v)
						.. '"')
				end
			end)
		end
	end
	table.insert(ret, '>\n')
	table.insert(ret, '<tr class="language-category-data">\n<th colspan="2">'
		.. edit_link("Модул:" .. require("Модул:languages").getDataModuleName(lang:getCode()),
			"Edit language data")
		.. "</th>\n</tr>\n")
	table.insert(ret, "<tr>\n<th>Канонско име</th><td>" .. lang:getCanonicalName() .. "</td>\n</tr>\n")

	local otherNames = lang:getOtherNames(true)
	if otherNames then
		local names = {}
		
		for _, name in ipairs(otherNames) do
			table.insert(names, "<li>" .. name .. "</li>")
		end
		
		if #names > 0 then
			table.insert(ret, "<tr>\n<th>Друга имена</th><td><ul>" .. table.concat(names, "\n") .. "</ul></td>\n</tr>\n")
		end
	end
	
	local aliases = lang:getAliases()
	if aliases then
		local names = {}
		
		for _, name in ipairs(aliases) do
			table.insert(names, "<li>" .. name .. "</li>")
		end
		
		if #names > 0 then
			table.insert(ret, "<tr>\n<th>Алијаси</th><td><ul>" .. table.concat(names, "\n") .. "</ul></td>\n</tr>\n")
		end
	end

	local varieties = lang:getVarieties()
	if varieties then
		local names = {}
		
		for _, name in ipairs(varieties) do
			if type(name) == "string" then
				table.insert(names, "<li>" .. name .. "</li>")
			else
				assert(type(name) == "table")
				local first_var
				local subvars = {}
				for i, var in ipairs(name) do
					if i == 1 then
						first_var = var
					else
						table.insert(subvars, "<li>" .. var .. "</li>")
					end
				end
				if #subvars > 0 then
					table.insert(names, "<li><dl><dt>" .. first_var .. "</dt>\n<dd><ul>" .. table.concat(subvars, "\n") .. "</ul></dd></dl></li>")
				elseif first_var then
					table.insert(names, "<li>" .. first_var .. "</li>")
				end
			end
		end
		
		if #names > 0 then
			table.insert(ret, "<tr>\n<th>Сорте</th><td><ul>" .. table.concat(names, "\n") .. "</ul></td>\n</tr>\n")
		end
	end

	table.insert(ret, "<tr>\n<th>[[Викиречник:Језици|Код језика]]</th><td><code>" .. lang:getCode() .. "</code></td>\n</tr>\n")
	table.insert(ret, "<tr>\n<th>[[Викиречник:Фамилије|Језичка породица]]</th>\n")
	
	local fam = lang:getFamily()
	local famCode = fam and fam:getCode()
	
	if not fam then
		table.insert(ret, "<td>unclassified</td>")
	elseif famCode == "qfa-iso" then
		table.insert(ret, "<td>[[:Категорија:Језик isolates|језик isolate]]</td>")
	elseif famCode == "qfa-mix" then
		table.insert(ret, "<td>[[:Категорија:Mixed languages|mixed језик]]</td>")
	elseif famCode == "sgn" then
		table.insert(ret, "<td>[[:Категорија:Знаковни језици|знаковни језик]]</td>")
	elseif famCode == "crp" then
		table.insert(ret, "<td>[[:Категорија:Creole или pidgin језици|creole или pidgin]]</td>")
	elseif famCode == "art" then
		table.insert(ret, "<td>[[:Категорија:Конструисани језици|конструисани језици]]</td>")
	else
		table.insert(ret, "<td>" .. makeCategoryLink(fam) .. "</td>")
	end
	
	table.insert(ret, "\n</tr>\n<tr>\n<th>Преци</th>\n")
	
	local ancestors, ancestorChain = lang:getAncestors(), lang:getAncestorChain()
	if ancestors[2] then
		local ancestorList = {}
		
		for i, anc in ipairs(ancestors) do
			ancestorList[i] = "<li>" .. makeCategoryLink(anc) .. "</li>"
		end
		
		table.insert(ret, "<td><ul>\n" .. table.concat(ancestorList, "\n") .. "</ul></td>\n")
	elseif ancestorChain[1] then
		table.insert(ret, "<td><ul>\n")
		
		local chain = {}
		
		for i, anc in ipairs(ancestorChain) do
			chain[i] = "<li>" .. makeCategoryLink(anc) .. "</li>"
		end
		
		table.insert(ret, table.concat(chain, "\n<ul>\n"))
		
		for _, _ in ipairs(chain) do
			table.insert(ret, "</ul>")
		end
		
		table.insert(ret, "</td>\n")
	else
		table.insert(ret, "<td>unknown</td>\n")
	end
	
	table.insert(ret, "</tr>\n")
	
	local scripts = lang:getScripts()
	
	if scripts[1] then
		local script_text = {}
		
		for _, sc in ipairs(scripts) do
			local text = {}
			local code = sc:getCode()
			if code ~= "Hira" then
				table.insert(text, "<li>" .. makeCategoryLink(sc))
			end
			
			if code == "Jpan" then
				local m_scripts = require("Модул:scripts")
				local Hani = m_scripts.getByCode("Hani")
				local Hira = m_scripts.getByCode("Hira")
				local Kana = m_scripts.getByCode("Kana")
				table.insert(text, "<ul>")
				table.insert(text, "<li>" .. makeCategoryLink(Hani) .. "</li>")
				table.insert(text, "<li>" .. makeCategoryLink(Hira) .. "</li>")
				table.insert(text, "<li>" .. makeCategoryLink(Kana) .. "</li>")
				table.insert(text, "</ul>")
			elseif code == "Kore" then
				local m_scripts = require("Модул:scripts")
				local Hang = m_scripts.getByCode("Hang")
				local Hani = m_scripts.getByCode("Hani")
				table.insert(text, "<ul>")
				table.insert(text, "<li>" .. makeCategoryLink(Hang) .. "</li>")
				table.insert(text, "<li>" .. makeCategoryLink(Hani) .. "</li>")
				table.insert(text, "</ul>")
			end
			
			table.insert(text, "</li>")
			
			table.insert(script_text, table.concat(text, "\n"))
		end
		
		table.insert(ret, "<tr>\n<th>[[Викиречник:Писма|Писма]]</th>\n<td><ul>\n" .. table.concat(script_text, "\n") .. "</ul></td>\n</tr>\n")
	else
		table.insert(ret, "<tr>\n<th>[[Викиречник:Писма|Писма]]</th>\n<td>нису прецизирани</td>\n</tr>\n")
	end
	
	if lang._rawData.translit_module then
		local translit_module = lang._rawData.translit_module
		local translit_module_info = {}
		table.insert(translit_module_info,
			("[[Модул:%s]]"):format(translit_module))
		
		if translit_module == "translit-redirect" then
			local data = mw.loadData("Модул:translit-redirect/data")[lang:getCode()]
			if data then
				table.insert(translit_module_info, ":")
				local redirects_to = {}
				local m_scripts = require "Модул:scripts"
				for script, data in require "Модул:table".sortedPairs(data) do
					-- Skip boolean fields like "debug_mode" and "noError".
					if type(data) == "table" then
						table.insert(redirects_to,
							("\n* <code>%s</code>: %s"):format(
								script,
								data.module and ("[[Модул:%s]]"):format(data.module)
									or "(none)"))
					end
				end
				table.insert(translit_module_info, table.concat(redirects_to))
			end
		end
		
		table.insert(ret, [=[
<tr>
<th>[[Викиречник:Транзиција и романизација|Транслитерациони<br>модули]]</th>
<td>]=] .. table.concat(translit_module_info) .. [=[</td>
</tr>
]=])
end
	local wikidataItem = lang:getWikidataItem()
	if lang:getWikidataItem() and mw.wikibase then
		local URL = mw.wikibase.getEntityUrl(wikidataItem)
		local link
		if URL then
			link = '[' .. URL .. ' ' .. wikidataItem .. ']'
		else
			link = '<span class="error">Invalid Wikidata item: <code>' .. wikidataItem .. '</code></span>'
		end
		table.insert(ret, "<tr><th>Википодаци</th><td>" .. link .. "</td></tr>")
	end
	
	table.insert(ret, "</table>")
	
	return table.concat(ret)
end

local function NavFrame(content, title)
	return '<div class="NavFrame"><div class="NavHead">'
		.. (title or '{{{title}}}') .. '</div>'
		.. '<div class="NavContent" style="text-align: left;">'
		.. content
		.. '</div></div>'
end

function export.country_categories(frame)
	local categories = {}
	
	for i, country in ipairs(frame:getParent().args) do
		if i > 1 then
			table.insert(categories, "[[Категорија:Језици " .. country .. "]]")
		end
	end
	
	if #categories > 0 then
		return table.concat(categories)
	else
		return "[[Категорија:Језици који нису сортирани у категорију земаља]]"
	end
end


-- Category object

local Category = {}
Category.__index = Category


function Category.new(info)
	for key, val in pairs(info) do
		if not (key == "code" or key == "entryname" or key == "setsister" or key == "setwiki" or key == "setwikt") then
			error("The parameter \"" .. key .. "\" was not recognized.")
		end
	end
	
	local self = setmetatable({}, Category)
	self._info = info
	
	if not self._info.code then
		error("No language code was specified.")
	else
		self._lang = require("Модул:languages").getByCode(self._info.code) or error("The language code \"" .. self._info.code .. "\" is not valid.")
	end
	
	return self
end

export.new = Category.new


function Category:getInfo()
	return self._info
end


function Category:getBreadcrumbName()
	return self._lang:getCanonicalName()
end


function Category:getDataModule()
	return "Модул:category tree/langcatboiler"
end


function Category:canBeEmpty()
	return true
end


function Category:isHidden()
	return false
end


function Category:getCategoryName()
	return mw.getContentLanguage():ucfirst(self._lang:getCategoryName())
end


function Category:getDescription()
	if self._lang:getCode() == "und" then
		return
			"This is the main category of the '''" .. self._lang:getCategoryName() .. "''', represented in Wiktionary by the [[Викиречник:Језици|код]] '''" .. self._lang:getCode() .. "'''. " ..
			"This language contains terms in historical writing, whose meaning has not yet been determined by scholars."
	end
	
	local canonicalName = self._lang:getCanonicalName()
	
	local ret = linkbox(self._lang, self._info.setwiki, self._info.setwikt, self._info.setsister, self._info.entryname)
	
	ret = ret .. "This is the main category of the '''" .. self._lang:getCategoryName() .. "'''.\n\nInformation about " .. canonicalName .. ":\n\n" .. infobox(self._lang)
	
	if self._lang:getType() == "reconstructed" then
		ret = ret .. "\n\n" ..
			canonicalName .. " is a reconstructed language. Its words and roots are not directly attested in any written works, but have been reconstructed through the ''comparative method'', " ..
			"which finds regular similarities between languages that cannot be explained by coincidence or word-borrowing, and extrapolates ancient forms from these similarities.\n\n" ..
			"According to our [[Wiktionary:Criteria for inclusion|criteria for inclusion]], terms in " .. canonicalName ..
			" should '''not''' be present in entries in the main namespace, but may be added to the Reconstruction: namespace."
	elseif self._lang:getType() == "appendix-constructed" then
		ret = ret .. "\n\n" ..
			canonicalName .. " is a constructed language that is only in sporadic use. " ..
			"According to our [[Викиречник:Критеријуми за укључивање|критеријуми за укључивање]], израза у " .. canonicalName ..
			" '''не''' требају бити присутни у записима у главном простору имена, али могу бити додани у Додатак: именски простор. " ..
			"Сви термини на овом језику могу бити доступни на [[Додатак:" .. canonicalName .. "]]."
	end
	
	local about = mw.title.new("Викиречник:О " .. canonicalName)
	
	if about.exists then
		ret = ret .. "\n\n" ..
			"Молим видите '''[[Викиречник:О " .. canonicalName .. "]]''' за информације и посебна разматрања за креирање " .. self._lang:getCategoryName() .. " уноса."
	end
	
	local ok, tree_of_descendants = pcall(
		require("Модул:family tree").print_children,
		self._lang:getCode(), {
			protolanguage_under_family = true,
			must_have_descendants = true
		})
	
	if ok then
		if tree_of_descendants then
			ret = ret .. NavFrame(
				tree_of_descendants,
				"Породично дрво")
		else
			ret = ret .. "\n\n" .. self._lang:getCanonicalName()
				.. " has no descendants or varieties listed in Wiktionary's language data modules."
		end
	else
		mw.log("error while generating tree: " .. tostring(tree_of_descendants))
	end
ret = ret .. " __EXPECTUNUSEDCATEGORY__" -- it's OK if this category is empty	
	return ret
end


function Category:getParents()
	local canonicalName = self._lang:getCanonicalName()
	
	local ret = {{name = "Категорија:Сви језици", sort = canonicalName}}
	
	local fam = self._lang:getFamily()
	local famCode = fam and fam:getCode()
	
	if not fam then
		table.insert(ret, {name = "Категорија:Unclassified језици", sort = canonicalName})
	elseif famCode == "qfa-iso" then
		table.insert(ret, {name = "Категорија:Изоловани језици", sort = canonicalName})
	elseif famCode == "qfa-mix" then
		table.insert(ret, {name = "Категорија:Мешани језици", sort = canonicalName})
	elseif famCode == "sgn" then
		table.insert(ret, {name = "Категорија:Сви знаковни језици", sort = canonicalName})
	elseif famCode == "crp" then
		table.insert(ret, {name = "Категорија:Креолски или пиџин језици", sort = canonicalName})
		
		for _, anc in ipairs(self._lang:getAncestors()) do
			table.insert(ret, {name = "Категорија:" .. anc:getCanonicalName() .. "-based creole or pidgin languages", sort = canonicalName})
		end
	elseif famCode == "art" then
		if self._lang:getType() == "appendix-constructed" then
			table.insert(ret, {name = "Категорија:Додатак-само конструисани језици", sort = canonicalName})
		else
			table.insert(ret, {name = "Категорија:Конструисани језици", sort = canonicalName})
		end
		
		for _, anc in ipairs(self._lang:getAncestors()) do
			table.insert(ret, {name = "Категорија:" .. anc:getCanonicalName() .. "- засновани језици", sort = canonicalName})
		end
	else
		table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(fam:getCategoryName()), sort = canonicalName})
		
		if self._lang:getType() == "reconstructed" then
			table.insert(ret, {name = "Категорија:Реконструисани језици", sort = (mw.ustring.gsub(canonicalName, "^Пра%-", ""))})
		end
	end
	
	for _, sc in ipairs(self._lang:getScripts()) do
		table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(sc:getCategoryName() .. " језици"), sort = canonicalName})
		
		if sc:getCode() == "Jpan" then
			table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(require("Модул:scripts").getByCode("Hani"):getCategoryName() .. " језици"), sort = canonicalName})
			table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(require("Модул:scripts").getByCode("Hira"):getCategoryName() .. " језици"), sort = canonicalName})
			table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(require("Модул:scripts").getByCode("Kana"):getCategoryName() .. " језици"), sort = canonicalName})
		elseif sc:getCode() == "Kore" then
			table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(require("Модул:scripts").getByCode("Hang"):getCategoryName() .. " језици"), sort = canonicalName})
			table.insert(ret, {name = "Категорија:" .. mw.getContentLanguage():ucfirst(require("Модул:scripts").getByCode("Hani"):getCategoryName() .. " језици"), sort = canonicalName})
		end
	end
	
	if self._lang:hasTranslit() then
		table.insert(ret, {name = "Категорија:Језици са аутоматском транслитерацијом", sort = canonicalName})
	end
	
	return ret
end


function Category:getChildren()
	local ret = {}
	
	local m_poscatboiler = require("Модул:category tree/poscatboiler")
	
	for _, label in ipairs({"додатци", "приступ сервисирању", "леме", "имена", "фразе", "риме", "симболи", "шаблони", "термини по етимологији", "термини по коришћењу"}) do
		local child = m_poscatboiler.new({code = self._lang:getCode(), label = label})
		local parents = child:getParents()
		
		if parents then
			-- Find the current category among the child's parents, to find its sort key
			for _, parent in ipairs(parents) do
				if type(parent.name) == "string" and parent.name == "Категорија:" .. self:getCategoryName() then
					table.insert(ret, {name = child, sort = parent.sort})
					break
				end
			end
		end
	end
	
	local m_derivcatboiler = require("Модул:category tree/derived cat")
	local child = m_derivcatboiler.new({code = nil, label = self._lang:getCode()})
	local sortkey = child._info.label
	local parents = child:getParents()
	
	if parents then
		-- Find the current category among the child's parents, to find its sort key
		for _, parent in ipairs(parents) do
			if type(parent.name) == "string" and parent.name == "Категорија:" .. self:getCategoryName() then
				sortkey = parent.sort
				break
			end
		end
	end
	
	table.insert(ret, {name = child, sort = sortkey})
	
	local m_topic_cat = require("Модул:category tree/topic cat")
	local child = m_topic_cat.new({code = self._lang:getCode(), label = "Све теме"})
	local sortkey = child._info.label
	local parents = child:getParents()
	
	if parents then
		-- Find the current category among the child's parents, to find its sort key
		for _, parent in ipairs(parents) do
			if type(parent.name) == "string" and parent.name == "Категорија:" .. self:getCategoryName() then
				sortkey = parent.sort
				break
			end
		end
	end
	
	table.insert(ret, {name = child, sort = sortkey})
	
	-- FIXME: This is hacky, but it works as a stopgap measure.
	-- We should fix this when these categories get their own category tree modules.
	table.insert(ret, {name = {
		_lang = self._lang,
		getCategoryName = function(self) return "Локални " .. self._lang:getCanonicalName() end,
		getDescription = function(self) return self._lang:getCanonicalName() .. " изрази који се користе у одређеним регионима или дијалектима." end,
		}, sort = "regional"})
	
	table.insert(ret, {name = {
		_lang = self._lang,
		getCategoryName = function(self) return "Захтеви (" .. self._lang:getCanonicalName() .. ")" end,
		getDescription = function(self) return self._lang:getCanonicalName() .. " уноси којима је потребна пажња искусних уредника." end,
		}, sort = "requests"})
	
	table.insert(ret, {name = {
		_lang = self._lang,
		getCategoryName = function(self) return "Корисник " .. self._lang:getCode() end,
		getDescription = function(self) return "корисници викиречника категоризовани према степену познавања језика, за " .. self._lang:getCanonicalName() .. " језик." end,
		}, sort = "user"})
	
	return ret
end


function Category:getUmbrella()
	return nil
end


return export