Module:category tree

Definition from Wiktionary, the free dictionary
Jump to: navigation, search

This module is used for generating category boilerplate templates. It is not meant to be used directly. Rather, each template will have its own submodule, which handles the specifics of that template.

This documentation only covers the generics of the category tree system. If you are looking for documentation on a specific template, or on how to add or modify category information, see the documentation of that template.


The category tree module is invoked as:

{{#invoke:category tree|show|template=name of the template|...other parameters...}}

Every template that uses this module should have a submodule of this module with the name given in the template= parameter. This submodule should export a function named new which takes a single parameter: a table named info that contains the various parameters that were passed to the template initially. This function should return a new Category object representing those parameters, or nil if the combination of parameters was not valid (i.e. no such category exists).

Most templates accept and pass this common set of parameters. The parameters passed to the module by a template are defined by that template individually, so not every template will necessarily use all of these. {{famcatboiler}} for example only passes the code= parameter to the module.

The code that specifies what 'owns' the category's contents. This is usually a language code such as en, but it can also be a script code like Latn or the code of a language family, depending on how the specific template treats it.
A name for the thing that is being categorised. The submodule determines how the label is interpreted, so it depends on the template being used. Many templates use it to look up data in a table, while others may interpret it as a language code of some kind.
The script code of the items to be categorised. This is usually empty, but many categories such as those used by Mandarin Chinese can split into subcategories based on script.

General workings[edit]

The module is based on the principle of two main kinds of category:

Basic categories are those for which the code= parameter is not empty. These therefore belong to a specific language (or similar) and are the "regular" categories. Examples are: Category:English nouns, Category:French templates, Category:nl:Linguistics, Category:English terms derived from Japanese, Category:Latin script characters.

Umbrella categories do not have a code, but contain all basic categories of their label, one for each code. These are the "by language" type categories. Examples are: Category:Nouns by language, Category:Templates by language, Category:Linguistics, Category:Terms derived from Japanese, Category:Characters by script.

Some templates also distinguish a third type of category, the fundamental category. This category is used as the parent category for umbrella categories.

Category objects[edit]

Text-x-generic with pencil.svg This documentation is out of date.
The documentation on this page or section no longer reflects its current state, and some information may be missing or incorrect. Please help by editing the documentation page, and adding information about undocumented features, while removing information that is no longer applicable.

Category objects are returned by each submodule's new function. They represent a single category in the tree. A category object has a variety of methods which may be called on it to ask for information about the category.



Returns the name that is used for the category in the "breadcrumbs" at the top of the category page.



Returns the name of the module which contains the data for this category. This is used to create an "edit" link on the category, which allows users to find and edit the information more easily.



Returns the name of the category that this category object represents.



Returns the description text that is shown at the top of the category page. If the category has no description, this returns nil.



Returns a table of the parent categories of this category. Each element in the table is a table itself, with two elements:

One of two possibilities: An category object representing the parent category, or a string that directly specifies the name of the parent category.
The sorting key that should be used when categorizing the current category in the parent.

If the category has no parents, this returns nil.



Returns a table of the child categories of this category. Each element in the table is a category object representing the child category. If the category has no children, this returns nil.



Returns a category object for the current category's corresponding umbrella category. If the current category is already an umbrella category, this returns nil. It also returns nil if the category has no umbrella category.

local export = {}
local m_languages = require('Module:languages')

-- The main entry point.
-- This is the only function that can be invoked from a template.
	if mw.title.getCurrentTitle().nsText == "Template" then
		return "(This template should be used on pages in the Category: namespace.)"
	elseif mw.title.getCurrentTitle().nsText ~= "Category" then
		error("This template/module can only be used on pages in the Category: namespace.")
	local args = frame.args
	-- Get all the parameters and the label data
	local info = {}
	for key, val in pairs(args) do
		info[key] = val; if info[key] == "" then info[key] = nil end
	-- autofill parameters for topic cat
	if info.template == "topic cat" and not info.code and not info.label then
		pagename = mw.title.getCurrentTitle().text
		pagename = mw.text.split(pagename,':')
		if #pagename == 1 then
			info.label = pagename[1]
		elseif #pagename == 2 then
			info.code = pagename[1]
			info.label = pagename[2]
	if not info.template then
		error("The \"template\" parameter was not specified.")
	local template = info.template
	info.template = nil
	local current = require("Module:category tree/" .. template).new(info, true)
	local display = {}
	local categories = {}
	-- Check if the category is empty
	local isEmpty =, "all") == 0
	-- Are the parameters valid?
	if not current then
		table.insert(categories, "[[Category:Categories with invalid label]]")
		table.insert(categories, isEmpty and "[[Category:Empty categories]]" or nil)
		table.insert(display, show_error(
			"The label \"" .. (info.label or "") .. "\" given to the " ..
			mw.getCurrentFrame():expandTemplate{title = "temp", args = {template}} ..
			" template is not valid. You may have mistyped it, or it simply has not been created yet. " ..
			"To add a new label, please consult the documentation of the template."))
		-- Exit here, as all code beyond here relies on current not being nil
		return table.concat(categories, "") .. table.concat(display, "\n\n") .. "<br clear=\"all\"/>"
	-- Does the category have the correct name?
	if mw.title.getCurrentTitle().text ~= current:getCategoryName() then
		table.insert(categories, "[[Category:Categories with incorrect name]]")
		table.insert(display, show_error(
			"Based on the parameters given to the " ..
			mw.getCurrentFrame():expandTemplate{title = "temp", args = {template}} ..
			" template, this category should be called '''[[:Category:" .. current:getCategoryName() .. "]]'''."))
	-- Add cleanup category for empty categories
	if isEmpty and not current:canBeEmpty() then
		table.insert(categories, "[[Category:Empty categories]]")
	-- Generate the displayed information
	table.insert(display, show_breadcrumbs(current))
	table.insert(display, show_description(current))
	table.insert(display, show_children(current))
	table.insert(display, show_TOC(info))
	show_categories(current, categories)
	return table.concat(categories, "") .. table.concat(display, "\n\n") .. "<br clear=\"all\"/>"

function show_error(text)
	return  mw.getCurrentFrame():expandTemplate{title = "maintenance box", args = {
		image = "[[File:Ambox warning pn.svg|50px]]",
		title = "The automatically-generated contents of this category has errors.",
		text = text,

-- Check the name of the current page, and return an error if it's not right.
function check_name(current, template, info)
	local errortext = nil
	local category = nil
	if not current then
		errortext =
			"The label \"" .. (info.label or "") .. "\" given to the " .. mw.getCurrentFrame():expandTemplate{title = "temp", args = {template}} .. " template is not valid. " ..
			"You may have mistyped it, or it simply has not been created yet. To add a new label, please consult the documentation of the template."
		category = "[[Category:Categories with invalid label]]"
	if errortext then
		return (category or "") .. show_error(errortext)
		return nil

-- Show the parent categories that the current category should be placed in.
function show_categories(current, categories)
	local parents = current:getParents()
	if not parents then
	for _, parent in ipairs(parents) do
		if type( == "string" then
			table.insert(categories, "[[" .. .. "|" .. parent.sort .. "]]")
			local parent_name =
			table.insert(categories, "[[Category:" .. parent_name .. "|" .. parent.sort .. "]]")
	-- Also put the category in its corresponding "umbrella" or "by language" category.
	local umbrella = current:getUmbrella()
	if umbrella then
		if type(umbrella) == "string" then
			table.insert(categories, "[[" .. umbrella .. "|" .. current:getCategoryName() .. "]]")
			table.insert(categories, "[[Category:" .. umbrella:getCategoryName() .. "|" .. current:getCategoryName() .. "]]")

-- Show navigational "breadcrumbs" at the top of the page.
function show_breadcrumbs(current)
	local steps = {}
	-- Start at the current label and move our way up the "chain" from child to parent, until we can't go further.
	while current do
		local category = nil
		local display_name = nil
		if type(current) == "string" then
			category = current
			display_name = current:gsub("^Category:", "")
			category = "Category:" .. current:getCategoryName()
			display_name = current:getBreadcrumbName()
		display_name = mw.getContentLanguage():ucfirst(display_name)
		table.insert(steps, 1, "» [[:" .. category .. "|" .. display_name .. "]]")
		-- Move up the "chain" by one level.
		if type(current) == "string" then
			current = nil
			current = current:getParents()
			if current then
				current = current[1].name
	return "<small>" .. table.concat(steps, " ") .. "</small>"

-- Show a short description text for the category.
function show_description(current)
	return (current:getDescription() or "") .. mw.getCurrentFrame():expandTemplate{title = "edit", args = {current:getDataModule(), type = "sup"}}

-- Show a list of child categories.
function show_children(current)
	local children = current:getChildren()
	if not children then
		return nil
	table.sort(children, function(first, second) return first.sort < second.sort end)
	local children_list = {}
	for _, child in ipairs(children) do
		local child_basic =
		local child_page ="Category:" .. child_basic)
		if child_page.exists then
			local child_description =
			table.insert(children_list, "* [[:Category:" .. child_basic .. "]]: " .. child_description)
	return table.concat(children_list, "\n")

-- Show a table of contents with links to each letter in the language's script.
function show_TOC(info)
	local code = info.code or "en"
	local num_pages = 300, "pages")
	-- No need for a TOC if all entry names can fit on one page.
	if num_pages > 200 then
		-- This category is very large, see if there is an "extended" version of the TOC.
		if num_pages > 2500 then
			local TOC_template_extended ="Template:" .. code .. "-categoryTOC/full")
			if TOC_template_extended.exists then
				return mw.getCurrentFrame():expandTemplate{title = TOC_template_extended.text, args = {}}
		local TOC_template ="Template:" .. code .. "-categoryTOC")
		if TOC_template.exists then
			return mw.getCurrentFrame():expandTemplate{title = TOC_template.text, args = {}}
	return nil

return export