Wiktionary
miwiktionary
https://mi.wiktionary.org/wiki/Hau_K%C4%81inga
MediaWiki 1.45.0-wmf.8
case-sensitive
Media
Special
Talk
User
User talk
Wiktionary
Wiktionary talk
File
File talk
MediaWiki
MediaWiki talk
Template
Template talk
Help
Help talk
Category
Category talk
TimedText
TimedText talk
Module
Module talk
Module:category tree
828
5877
17321
17312
2025-07-01T14:25:20Z
Ayane Fumihiro
6766
17321
Scribunto
text/plain
-- Prevent substitution.
if mw.isSubsting() then
return require("Module:unsubst")
end
local export = {}
local category_tree_submodule_prefix = "Module:category tree/"
local category_tree_styles_css = "Module:category tree/styles.css"
local m_str_utils = require("Module:string utilities")
local m_template_parser = require("Module:template parser")
local m_utilities = require("Module:utilities")
local ceil = math.ceil
local class_else_type = m_template_parser.class_else_type
local concat = table.concat
local deep_copy = require("Module:table").deepCopy
local full_url = mw.uri.fullUrl
local insert = table.insert
local is_callable = require("Module:fun").is_callable
local log10 = math.log10 or require("Module:math").log10
local new_title = mw.title.new
local pages_in_category = mw.site.stats.pagesInCategory
local parse = m_template_parser.parse
local remove_comments = require("Module:string/removeComments")
local sort = table.sort
local split = m_str_utils.split
local string_compare = require("Module:string/compare")
local trim = m_str_utils.trim
local uupper = m_str_utils.upper
local yesno = require("Module:yesno")
local current_frame = mw.getCurrentFrame()
local current_title = mw.title.getCurrentTitle()
local namespace = current_title.namespace
local poscatboiler_subsystem = "poscatboiler"
local extra_args_error = "Extra arguments to {{((}}auto cat{{))}} are not allowed for this category."
-- Generates a sortkey for a numeral `n`, adding leading zeroes to avoid the "1, 10, 2, 3" sorting problem. `max_n` is the greatest expected value of `n`, and is used to determine how many leading zeroes are needed. If not supplied, it defaults to the number of languages.
function export.numeral_sortkey(n, max_n)
max_n = max_n or require("Module:list of languages").count()
return ("#%%0%dd"):format(ceil(log10(max_n + 1))):format(n)
end
function export.split_lang_label(title_text)
local getByCanonicalName = require("Module:languages").getByCanonicalName
-- Progressively remove a word from the potential canonical name until it
-- matches an actual canonical name.
local words = split(title_text, " ", true)
for i = #words - 1, 1, -1 do
local lang = getByCanonicalName(concat(words, " ", 1, i))
if lang then
return lang, concat(words, " ", i + 1)
end
end
return nil, title_text
end
local function show_error(text)
return require("Module:message box").maintenance(
"red",
"[[File:Ambox warning pn.svg|50px]]",
"This category is not defined in Wiktionary's category tree.",
text
)
end
-- Show the text that goes at the very top right of the page.
local function show_topright(current)
return current.getTopright and current:getTopright() or nil
end
local function link_box(content)
return ("<div class=\"noprint plainlinks\" style=\"float: right; clear: both; margin: 0 0 .5em 1em; background: var(--wikt-palette-paleblue, #f9f9f9); border: 1px var(--border-color-base, #aaaaaa) solid; margin-top: -1px; padding: 5px; font-weight: bold;\">%s</div>"):format(content)
end
local function show_editlink(current)
return link_box(("[%s Edit category data]"):format(tostring(full_url(current:getDataModule(), "action=edit"))))
end
function show_related_changes()
local title = current_title.fullText
return link_box(("[%s <span title=\"Recent edits and other changes to pages in %s\">Recent changes</span>]"):format(
tostring(full_url("Special:RecentChangesLinked", {
target = title,
showlinkedto = 0,
})),
title
))
end
local function show_pagelist(current)
local namespace = "namespace="
local info = current:getInfo()
local lang_code = info.code
if info.label == "citations" or info.label == "citations of undefined terms" then
namespace = namespace .. "Citations"
elseif lang_code then
local lang = require("Module:languages").getByCode(lang_code, true)
if lang then
-- Proto-Norse (gmq-pro) is the probably language with a code ending in -pro
-- that's intended to have mostly non-reconstructed entries.
if (lang_code:find("%-pro$") and lang_code ~= "gmq-pro") or lang:hasType("reconstructed") then
namespace = namespace .. "Reconstruction"
elseif lang:hasType("appendix-constructed") then
namespace = namespace .. "Appendix"
end
end
elseif info.label:match("templates") then
namespace = namespace .. "Template"
elseif info.label:match("modules") then
namespace = namespace .. "Module"
elseif info.label:match("^Wiktionary") or info.label:match("^Pages") then
namespace = ""
end
end
-- Show navigational "breadcrumbs" at the top of the page.
local 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, display_name, nocap
if type(current) == "string" then
category = current
display_name = current:gsub("^Category:", "")
else
if not current.getCategoryName then
error("Internal error: Bad format in breadcrumb chain structure, probably a misformatted value for `parents`: " ..
mw.dumpObject(current))
end
category = "Category:" .. current:getCategoryName()
display_name, nocap = current:getBreadcrumbName()
end
if not nocap then
display_name = mw.getContentLanguage():ucfirst(display_name)
end
insert(steps, 1, ("[[:%s|%s]]"):format(category, display_name))
-- Move up the "chain" by one level.
if type(current) == "string" then
current = nil
else
current = current:getParents()
end
if current then
current = current[1].name
end
end
local templateStyles = require("Module:TemplateStyles")(category_tree_styles_css)
local ol = mw.html.create("ol")
for i, step in ipairs(steps) do
local li = mw.html.create("li")
if i ~= 1 then
local span = mw.html.create("span")
:attr("aria-hidden", "true")
:addClass("ts-categoryBreadcrumbs-separator")
:wikitext(" » ")
li:node(span)
end
li:wikitext(step)
ol:node(li)
end
return templateStyles .. tostring(mw.html.create("div")
:attr("role", "navigation")
:attr("aria-label", "Breadcrumb")
:addClass("ts-categoryBreadcrumbs")
:node(ol))
end
local function show_also(current)
local also = current._info.also
if also and #also > 0 then
return ('<div style="margin-top:-1em;margin-bottom:1.5em">%s</div>'):format(require("Module:also").main(also))
end
return nil
end
-- Show a short description text for the category.
local function show_description(current)
return current.getDescription and current:getDescription() or nil
end
local function show_appendix(current)
local appendix = current.getAppendix and current:getAppendix()
return appendix and ("For more information, see [[%s]]."):format(appendix) or nil
end
local function sort_children(child1, child2)
return string_compare(uupper(child1.sort), uupper(child2.sort))
end
-- Show a list of child categories.
local function show_children(current)
local children = current.getChildren and current:getChildren() or nil
if not children then
return nil
end
sort(children, sort_children)
local children_list = {}
for _, child in ipairs(children) do
local child_name, child_pagetitle = child.name
if type(child_name) == "string" then
child_pagetitle = child_name
else
child_pagetitle = "Category:" .. child_name:getCategoryName()
end
if new_title(child_pagetitle).exists then
insert(children_list, ("* [[:%s]]: %s"):format(
child_pagetitle,
child.description or
type(child_name) == "string" and child_name:gsub("^Category:", "") .. "." or
child_name:getDescription("child")
))
end
end
return concat(children_list, "\n")
end
-- Show a table of contents with links to each letter in the language's script.
local function show_TOC(current)
local titleText = current_title.text
local inCategoryPages = pages_in_category(titleText, "pages")
local inCategorySubcats = pages_in_category(titleText, "subcats")
local TOC_type
-- Compute type of table of contents required.
if inCategoryPages > 2500 or inCategorySubcats > 2500 then
TOC_type = "full"
elseif inCategoryPages > 200 or inCategorySubcats > 200 then
TOC_type = "normal"
else
-- No (usual) need for a TOC if all pages or subcategories can fit on one page;
-- but allow this to be overridden by a custom TOC handler.
TOC_type = "none"
end
if current.getTOC then
local TOC_text = current:getTOC(TOC_type)
if TOC_text ~= true then
return TOC_text or nil
end
end
if TOC_type ~= "none" then
local templatename = current:getTOCTemplateName()
local TOC_template
if TOC_type == "full" then
-- This category is very large, see if there is a "full" version of the TOC.
local TOC_template_full = new_title(templatename .. "/full")
if TOC_template_full.exists then
TOC_template = TOC_template_full
end
end
if not TOC_template then
local TOC_template_normal = new_title(templatename)
if TOC_template_normal.exists then
TOC_template = TOC_template_normal
end
end
if TOC_template then
return current_frame:expandTemplate{title = TOC_template.text, args = {}}
end
end
return nil
end
-- Show the "catfix" that adds language attributes and script classes to the page.
local function show_catfix(current)
local lang, sc = current:getCatfixInfo()
return lang and m_utilities.catfix(lang, sc) or nil
end
-- Show the parent categories that the current category should be placed in.
local function show_categories(current, categories)
local parents = current.getParents and current:getParents() or nil
if not parents then
return nil
end
for _, parent in ipairs(parents) do
local parent_name = parent.name
local sortkey = type(parent.sort) == "table" and parent.sort:makeSortKey() or parent.sort
if type(parent_name) == "string" then
insert(categories, ("[[%s|%s]]"):format(parent_name, sortkey))
else
insert(categories, ("[[Category:%s|%s]]"):format(parent_name:getCategoryName(), sortkey))
end
end
-- Also put the category in its corresponding "umbrella" or "by language" category.
local umbrella = current:getUmbrella()
if umbrella then
-- FIXME: use a language-neutral sorting function like the Unicode Collation Algorithm.
local sortkey = current._lang and current._lang:getCanonicalName() or current:getCategoryName()
sortkey = require("Module:languages").getByCode("en", true):makeSortKey(sortkey)
if type(umbrella) == "string" then
insert(categories, ("[[%s|%s]]"):format(umbrella, sortkey))
else
insert(categories, ("[[Category:%s|%s]]"):format(umbrella:getCategoryName(), sortkey))
end
end
-- Check for various unwanted parser functions, which should be integrated into the category tree data instead.
-- Note: HTML comments shouldn't be removed from `content` until after this step, as they can affect the result.
local content = current_title:getContent()
if not content then
-- This happens when using [[Special:ExpandTemplates]] to call {{auto cat}} on a nonexistent category page,
-- which is needed by Benwing's create_wanted_categories.py script.
return
end
local defaultsort, displaytitle, page_has_param
for node in parse(content):iterate_nodes() do
local node_class = class_else_type(node)
if node_class == "template" then
local name = node:get_name()
if name == "DEFAULTSORT:" and not defaultsort then
insert(categories, "[[Category:Pages with DEFAULTSORT conflicts]]")
defaultsort = true
elseif name == "DISPLAYTITLE:" and not displaytitle then
insert(categories,"[[Category:Pages with DISPLAYTITLE conflicts]]")
displaytitle = true
end
elseif node_class == "parameter" and not page_has_param then
insert(categories,"[[Category:Pages with raw triple-brace template parameters]]")
page_has_param = true
end
end
-- Check for raw category markup, which should also be integrated into the category tree data.
content = remove_comments(content, "BOTH")
local head = content:find("[[", 1, true)
while head do
local close = content:find("]]", head + 2, true)
if not close then
break
end
-- Make sure there are no intervening "[[" between head and close.
local open = content:find("[[", head + 2, true)
while open and open < close do
head = open
open = content:find("[[", head + 2, true)
end
local cat = content:sub(head + 2, close - 1)
local colon = cat:match("^[ _\128-\244]*[Cc][Aa][Tt][EeGgOoRrYy _\128-\244]*():")
if colon then
local pipe = cat:find("|", colon + 1, true)
if pipe ~= #cat then
local title = new_title(pipe and cat:sub(1, pipe - 1) or cat)
if title and title.namespace == 14 then
insert(categories,"[[Category:Categories with categories using raw markup]]")
break
end
end
end
head = open
end
end
local function generate_output(current)
if current then
for _, functionName in pairs{
"getBreadcrumbName",
"getDataModule",
"canBeEmpty",
"getDescription",
"getParents",
"getChildren",
"getUmbrella",
"getAppendix",
"getTOCTemplateName",
} do
if not is_callable(current[functionName]) then
require("Module:debug").track{"category tree/missing function", "category tree/missing function/" .. functionName}
end
end
end
local boxes, display, categories = {}, {}, {}
-- Categories should never show files as a gallery.
insert(categories, "__NOGALLERY__")
if current_frame:getParent():getTitle() == "Template:auto cat" then
insert(categories, "[[Category:Categories calling Template:auto cat]]")
end
-- Check if the category is empty
local totalPages = pages_in_category(current_title.text, "all")
local hugeCategory = totalPages > 1000000 -- 1 million
-- Categorize huge categories, as they cause DynamicPageList to time out and make the category inaccessible.
if hugeCategory then
insert(categories, "[[Category:Huge categories]]")
end
-- Are the parameters valid?
if not current then
insert(categories, "[[Category:Categories that are not defined in the category tree]]")
insert(categories, totalPages == 0 and "[[Category:Empty categories]]" or nil)
insert(display, show_error(
"Double-check the category name for typos. <br>" ..
"[[Special:Search/Category: " .. current_title.text:gsub("^.+:", ""):gsub(" ", "~2 ") .. '~2|Search existing categories]] to check if this category should be created under a different name (for example, "Fruits" instead of "Fruit"). <br>' ..
"To add a new category to Wiktionary's category tree, please consult " .. current_frame:expandTemplate{title = "section link", args = {
"Help:Category#How_to_create_a_category",
}} .. "."))
-- Exit here, as all code beyond here relies on current not being nil
return concat(categories, "") .. concat(display, "\n\n"), true
end
-- Does the category have the correct name?
local currentName = current:getCategoryName()
local correctName = current_title.text == currentName
if not correctName then
insert(categories, "[[Category:Categories with incorrect names]]")
insert(display, show_error(("Based on the data in the category tree, this category should be called '''[[:Category:%s]]'''."):format(currentName)))
end
-- Add cleanup category for empty categories.
local canBeEmpty = current:canBeEmpty()
if canBeEmpty and correctName then
insert(categories, " __EXPECTUNUSEDCATEGORY__")
elseif totalPages == 0 then
insert(categories, "[[Category:Empty categories]]")
end
if current:isHidden() then
insert(categories, "__HIDDENCAT__")
end
-- Put all the float-right stuff into a <div> that does not clear, so that float-left stuff like the breadcrumbs and
-- description can go opposite the float-right stuff without vertical space.
insert(boxes, "<div style=\"float: right;\">")
insert(boxes, show_topright(current))
insert(boxes, show_editlink(current))
insert(boxes, show_related_changes())
insert(boxes, "</div>")
-- Generate the displayed information
insert(display, show_breadcrumbs(current))
insert(display, show_also(current))
insert(display, show_description(current))
insert(display, show_appendix(current))
insert(display, show_children(current))
insert(display, show_TOC(current))
insert(display, show_catfix(current))
insert(display, '<br class="clear-both-in-vector-2022-only">')
show_categories(current, categories)
return concat(boxes, "\n") .. "\n" .. concat(display, "\n\n") .. concat(categories, "")
end
--[==[
List of handler functions that try to match the page name. A handler should return the name of a submodule to
[[Module:category tree]] and an info table which is passed as an argument to the submodule. If a handler does not
recognize the page name, it should return nil. Note that the order of handlers matters!
]==]
local handlers = {}
-- Thesaurus per-language category
insert(handlers, function(title)
local code, label = title:match("^Thesaurus:(%l[%a-]*%a):(.+)")
if code then
return poscatboiler_subsystem, {label = title, raw = true}
end
end)
-- Topic per-language category
insert(handlers, function(title)
local code, label = title:match("^(%l[%a-]*%a):(.+)")
if code then
return poscatboiler_subsystem, {label = title, raw = true}
end
end)
-- Lect category e.g. for [[:Category:New Zealand English]] or [[:Category:Issime Walser]]
insert(handlers, function(title, args)
local lect = args.lect or args.dialect
if lect ~= "" and yesno(lect, true) then -- Same as boolean in [[Module:parameters]].
return poscatboiler_subsystem, {label = title, args = args, raw = true}
end
end)
-- poscatboiler per-language label, e.g. [[Category:English non-lemma forms]]
insert(handlers, function(title, args)
local lang, label = export.split_lang_label(title)
if not lang then
return
end
local baseLabel, script = label:match("(.+) in (.-) script$")
if script and baseLabel ~= "terms" then
local scriptObj = require("Module:scripts").getByCanonicalName(script)
if scriptObj then
return poscatboiler_subsystem, {label = baseLabel, code = lang:getCode(), sc = scriptObj:getCode(), args = args}
end
end
return poscatboiler_subsystem, {label = label, code = lang:getCode(), args = args}
end)
-- poscatboiler label umbrella category
insert(handlers, function(title, args)
local label = title:match("(.+) by language$")
if label then
-- The poscatboiler code will appropriately lowercase if needed.
return poscatboiler_subsystem, {label = label, args = args}
end
end)
-- poscatboiler raw handlers
insert(handlers, function(title, args)
return poscatboiler_subsystem, {label = title, args = args, raw = true}
end)
-- poscatboiler umbrella handlers without 'by language'
insert(handlers, function(title, args)
return poscatboiler_subsystem, {label = title, args = args}
end)
function export.show(frame)
local args, other_args = require("Module:parameters").process(frame:getParent().args, {
["also"] = {type = "title", sublist = "comma without whitespace", namespace = 14}
}, true)
if args.also then
for k, arg in next, args.also do
args.also[k] = arg.prefixedText
end
end
for k, arg in next, other_args do
other_args[k] = trim(arg)
end
if namespace == 10 then -- Template
return "(This template should be used on pages in the [[Help:Namespaces#Category|Category:]] namespace.)"
elseif namespace ~= 14 then -- Category
error("This template/module can only be used on pages in the [[mw:Help:Namespaces#Category|Category:]] namespace.")
end
local first_fail_args_handled, first_fail_cattext
-- Go through each handler in turn. If a handler doesn't recognize the format of the category, it will return nil,
-- and we will consider the next handler. Otherwise, it returns a template name and arguments to call it with, but
-- even then, that template might return an error, and we need to consider the next handler. This happens, for
-- example, with the category "CAT:Mato Grosso, Brazil", where "Mato" is the name of a language, so the poscatboiler
-- per-language label handler fires and tries to find a label "Grosso, Brazil". This throws an error, and
-- previously, this blocked fruther handler consideration, but now we check for the error and continue checking
-- handlers; eventually, the topic umbrella handler will fire and correctly handle the category.
for _, handler in ipairs(handlers) do
-- Use a new title object and args table for each handler, to keep them isolated.
local submodule, info = handler(current_title.text, deep_copy(other_args))
if submodule then
info.also = deep_copy(args.also)
require("Module:debug").track("auto cat/" .. submodule)
-- `failed` is true if no match was found.
submodule = require(category_tree_submodule_prefix .. submodule)
local cattext, failed = generate_output(submodule.main(info))
if failed then
if not first_fail_cattext then
first_fail_cattext = cattext
first_fail_args_handled = info.args and true or false
end
elseif not info.args and next(other_args) then
error(extra_args_error)
else
return cattext
end
end
end
-- If there were no matches, throw an error if any arguments were given, or otherwise return the cattext
-- from the first fail encountered. The final handlers call the boilers unconditionally, so there should
-- always be something to return.
if not first_fail_args_handled and next(other_args) then
error(extra_args_error)
end
return first_fail_cattext
end
-- TODO: new test entrypoint.
return export
hnq4xkn2klq31m3it6o9aitlslniigc
17322
17321
2025-07-01T14:28:09Z
Ayane Fumihiro
6766
17322
Scribunto
text/plain
-- Prevent substitution.
if mw.isSubsting() then
return require("Module:unsubst")
end
local export = {}
local category_tree_submodule_prefix = "Module:category tree/"
local category_tree_styles_css = "Module:category tree/styles.css"
local m_str_utils = require("Module:string utilities")
local m_template_parser = require("Module:template parser")
local m_utilities = require("Module:utilities")
local ceil = math.ceil
local class_else_type = m_template_parser.class_else_type
local concat = table.concat
local deep_copy = require("Module:table").deepCopy
local full_url = mw.uri.fullUrl
local insert = table.insert
local is_callable = require("Module:fun").is_callable
local log10 = math.log10 or require("Module:math").log10
local new_title = mw.title.new
local pages_in_category = mw.site.stats.pagesInCategory
local parse = m_template_parser.parse
local remove_comments = require("Module:string/removeComments")
local sort = table.sort
local split = m_str_utils.split
local string_compare = require("Module:string/compare")
local trim = m_str_utils.trim
local uupper = m_str_utils.upper
local yesno = require("Module:yesno")
local current_frame = mw.getCurrentFrame()
local current_title = mw.title.getCurrentTitle()
local namespace = current_title.namespace
local poscatboiler_subsystem = "poscatboiler"
local extra_args_error = "Extra arguments to {{((}}auto cat{{))}} are not allowed for this category."
-- Generates a sortkey for a numeral `n`, adding leading zeroes to avoid the "1, 10, 2, 3" sorting problem. `max_n` is the greatest expected value of `n`, and is used to determine how many leading zeroes are needed. If not supplied, it defaults to the number of languages.
function export.numeral_sortkey(n, max_n)
max_n = max_n or require("Module:list of languages").count()
return ("#%%0%dd"):format(ceil(log10(max_n + 1))):format(n)
end
function export.split_lang_label(title_text)
local getByCanonicalName = require("Module:languages").getByCanonicalName
-- Progressively remove a word from the potential canonical name until it
-- matches an actual canonical name.
local words = split(title_text, " ", true)
for i = #words - 1, 1, -1 do
local lang = getByCanonicalName(concat(words, " ", 1, i))
if lang then
return lang, concat(words, " ", i + 1)
end
end
return nil, title_text
end
local function show_error(text)
return require("Module:message box").maintenance(
"red",
"[[File:Ambox warning pn.svg|50px]]",
"This category is not defined in Wiktionary's category tree.",
text
)
end
-- Show the text that goes at the very top right of the page.
local function show_topright(current)
return current.getTopright and current:getTopright() or nil
end
local function link_box(content)
return ("<div class=\"noprint plainlinks\" style=\"float: right; clear: both; margin: 0 0 .5em 1em; background: var(--wikt-palette-paleblue, #f9f9f9); border: 1px var(--border-color-base, #aaaaaa) solid; margin-top: -1px; padding: 5px; font-weight: bold;\">%s</div>"):format(content)
end
local function show_editlink(current)
return link_box(("[%s Edit category data]"):format(tostring(full_url(current:getDataModule(), "action=edit"))))
end
function show_related_changes()
local title = current_title.fullText
return link_box(("[%s <span title=\"Recent edits and other changes to pages in %s\">Recent changes</span>]"):format(
tostring(full_url("Special:RecentChangesLinked", {
target = title,
showlinkedto = 0,
})),
title
))
end
local function show_pagelist(current)
local namespace = "namespace="
local info = current:getInfo()
local lang_code = info.code
if info.label == "citations" or info.label == "citations of undefined terms" then
namespace = namespace .. "Citations"
elseif lang_code then
local lang = require("Module:languages").getByCode(lang_code, true)
if lang then
-- Proto-Norse (gmq-pro) is the probably language with a code ending in -pro
-- that's intended to have mostly non-reconstructed entries.
if (lang_code:find("%-pro$") and lang_code ~= "gmq-pro") or lang:hasType("reconstructed") then
namespace = namespace .. "Reconstruction"
elseif lang:hasType("appendix-constructed") then
namespace = namespace .. "Appendix"
end
end
elseif info.label:match("templates") then
namespace = namespace .. "Template"
elseif info.label:match("modules") then
namespace = namespace .. "Module"
elseif info.label:match("^Wiktionary") or info.label:match("^Pages") then
namespace = ""
end
end
-- Show navigational "breadcrumbs" at the top of the page.
local 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, display_name, nocap
if type(current) == "string" then
category = current
display_name = current:gsub("^Category:", "")
else
if not current.getCategoryName then
error("Internal error: Bad format in breadcrumb chain structure, probably a misformatted value for `parents`: " ..
mw.dumpObject(current))
end
category = "Category:" .. current:getCategoryName()
display_name, nocap = current:getBreadcrumbName()
end
if not nocap then
display_name = mw.getContentLanguage():ucfirst(display_name)
end
insert(steps, 1, ("[[:%s|%s]]"):format(category, display_name))
-- Move up the "chain" by one level.
if type(current) == "string" then
current = nil
else
current = current:getParents()
end
if current then
current = current[1].name
end
end
local templateStyles = require("Module:TemplateStyles")(category_tree_styles_css)
local ol = mw.html.create("ol")
for i, step in ipairs(steps) do
local li = mw.html.create("li")
if i ~= 1 then
local span = mw.html.create("span")
:attr("aria-hidden", "true")
:addClass("ts-categoryBreadcrumbs-separator")
:wikitext(" » ")
li:node(span)
end
li:wikitext(step)
ol:node(li)
end
return templateStyles .. tostring(mw.html.create("div")
:attr("role", "navigation")
:attr("aria-label", "Breadcrumb")
:addClass("ts-categoryBreadcrumbs")
:node(ol))
end
local function show_also(current)
local also = current._info.also
if also and #also > 0 then
return ('<div style="margin-top:-1em;margin-bottom:1.5em">%s</div>'):format(require("Module:also").main(also))
end
return nil
end
-- Show a short description text for the category.
local function show_description(current)
return current.getDescription and current:getDescription() or nil
end
local function show_appendix(current)
local appendix = current.getAppendix and current:getAppendix()
return appendix and ("For more information, see [[%s]]."):format(appendix) or nil
end
local function sort_children(child1, child2)
return string_compare(uupper(child1.sort), uupper(child2.sort))
end
-- Show a list of child categories.
local function show_children(current)
local children = current.getChildren and current:getChildren() or nil
if not children then
return nil
end
sort(children, sort_children)
local children_list = {}
for _, child in ipairs(children) do
local child_name, child_pagetitle = child.name
if type(child_name) == "string" then
child_pagetitle = child_name
else
child_pagetitle = "Category:" .. child_name:getCategoryName()
end
if new_title(child_pagetitle).exists then
insert(children_list, ("* [[:%s]]: %s"):format(
child_pagetitle,
child.description or
type(child_name) == "string" and child_name:gsub("^Category:", "") .. "." or
child_name:getDescription("child")
))
end
end
return concat(children_list, "\n")
end
-- Show a table of contents with links to each letter in the language's script.
local function show_TOC(current)
local titleText = current_title.text
local inCategoryPages = pages_in_category(titleText, "pages")
local inCategorySubcats = pages_in_category(titleText, "subcats")
local TOC_type
-- Compute type of table of contents required.
if inCategoryPages > 2500 or inCategorySubcats > 2500 then
TOC_type = "full"
elseif inCategoryPages > 200 or inCategorySubcats > 200 then
TOC_type = "normal"
else
-- No (usual) need for a TOC if all pages or subcategories can fit on one page;
-- but allow this to be overridden by a custom TOC handler.
TOC_type = "none"
end
if current.getTOC then
local TOC_text = current:getTOC(TOC_type)
if TOC_text ~= true then
return TOC_text or nil
end
end
if TOC_type ~= "none" then
local templatename = current:getTOCTemplateName()
local TOC_template
if TOC_type == "full" then
-- This category is very large, see if there is a "full" version of the TOC.
local TOC_template_full = new_title(templatename .. "/full")
if TOC_template_full.exists then
TOC_template = TOC_template_full
end
end
if not TOC_template then
local TOC_template_normal = new_title(templatename)
if TOC_template_normal.exists then
TOC_template = TOC_template_normal
end
end
if TOC_template then
return current_frame:expandTemplate{title = TOC_template.text, args = {}}
end
end
return nil
end
-- Show the "catfix" that adds language attributes and script classes to the page.
local function show_catfix(current)
local lang, sc = current:getCatfixInfo()
return lang and m_utilities.catfix(lang, sc) or nil
end
-- Show the parent categories that the current category should be placed in.
local function show_categories(current, categories)
local parents = current.getParents and current:getParents() or nil
if not parents then
return nil
end
for _, parent in ipairs(parents) do
local parent_name = parent.name
local sortkey = type(parent.sort) == "table" and parent.sort:makeSortKey() or parent.sort
if type(parent_name) == "string" then
insert(categories, ("[[%s|%s]]"):format(parent_name, sortkey))
else
insert(categories, ("[[Category:%s|%s]]"):format(parent_name:getCategoryName(), sortkey))
end
end
-- Also put the category in its corresponding "umbrella" or "by language" category.
local umbrella = current:getUmbrella()
if umbrella then
-- FIXME: use a language-neutral sorting function like the Unicode Collation Algorithm.
local sortkey = current._lang and current._lang:getCanonicalName() or current:getCategoryName()
sortkey = require("Module:languages").getByCode("en", true):makeSortKey(sortkey)
if type(umbrella) == "string" then
insert(categories, ("[[%s|%s]]"):format(umbrella, sortkey))
else
insert(categories, ("[[Category:%s|%s]]"):format(umbrella:getCategoryName(), sortkey))
end
end
-- Check for various unwanted parser functions, which should be integrated into the category tree data instead.
-- Note: HTML comments shouldn't be removed from `content` until after this step, as they can affect the result.
local content = current_title:getContent()
if not content then
-- This happens when using [[Special:ExpandTemplates]] to call {{auto cat}} on a nonexistent category page,
-- which is needed by Benwing's create_wanted_categories.py script.
return
end
local defaultsort, displaytitle, page_has_param
for node in parse(content):iterate_nodes() do
local node_class = class_else_type(node)
if node_class == "template" then
local name = node:get_name()
if name == "DEFAULTSORT:" and not defaultsort then
insert(categories, "[[Category:Pages with DEFAULTSORT conflicts]]")
defaultsort = true
elseif name == "DISPLAYTITLE:" and not displaytitle then
insert(categories,"[[Category:Pages with DISPLAYTITLE conflicts]]")
displaytitle = true
end
elseif node_class == "parameter" and not page_has_param then
insert(categories,"[[Category:Pages with raw triple-brace template parameters]]")
page_has_param = true
end
end
-- Check for raw category markup, which should also be integrated into the category tree data.
content = remove_comments(content, "BOTH")
local head = content:find("[[", 1, true)
while head do
local close = content:find("]]", head + 2, true)
if not close then
break
end
-- Make sure there are no intervening "[[" between head and close.
local open = content:find("[[", head + 2, true)
while open and open < close do
head = open
open = content:find("[[", head + 2, true)
end
local cat = content:sub(head + 2, close - 1)
local colon = cat:match("^[ _\128-\244]*[Cc][Aa][Tt][EeGgOoRrYy _\128-\244]*():")
if colon then
local pipe = cat:find("|", colon + 1, true)
if pipe ~= #cat then
local title = new_title(pipe and cat:sub(1, pipe - 1) or cat)
if title and title.namespace == 14 then
insert(categories,"[[Category:Categories with categories using raw markup]]")
break
end
end
end
head = open
end
end
local function generate_output(current)
if current then
for _, functionName in pairs{
"getBreadcrumbName",
"getDataModule",
"canBeEmpty",
"getDescription",
"getParents",
"getChildren",
"getUmbrella",
"getAppendix",
"getTOCTemplateName",
} do
if not is_callable(current[functionName]) then
require("Module:debug").track{"category tree/missing function", "category tree/missing function/" .. functionName}
end
end
end
local boxes, display, categories = {}, {}, {}
-- Categories should never show files as a gallery.
insert(categories, "__NOGALLERY__")
if current_frame:getParent():getTitle() == "Template:auto cat" then
insert(categories, "[[Category:Ngā kāwai karanga Template:auto cat]]")
end
-- Check if the category is empty
local totalPages = pages_in_category(current_title.text, "all")
local hugeCategory = totalPages > 1000000 -- 1 million
-- Categorize huge categories, as they cause DynamicPageList to time out and make the category inaccessible.
if hugeCategory then
insert(categories, "[[Category:Huge categories]]")
end
-- Are the parameters valid?
if not current then
insert(categories, "[[Category:Categories that are not defined in the category tree]]")
insert(categories, totalPages == 0 and "[[Category:Empty categories]]" or nil)
insert(display, show_error(
"Double-check the category name for typos. <br>" ..
"[[Special:Search/Category: " .. current_title.text:gsub("^.+:", ""):gsub(" ", "~2 ") .. '~2|Search existing categories]] to check if this category should be created under a different name (for example, "Fruits" instead of "Fruit"). <br>' ..
"To add a new category to Wiktionary's category tree, please consult " .. current_frame:expandTemplate{title = "section link", args = {
"Help:Category#How_to_create_a_category",
}} .. "."))
-- Exit here, as all code beyond here relies on current not being nil
return concat(categories, "") .. concat(display, "\n\n"), true
end
-- Does the category have the correct name?
local currentName = current:getCategoryName()
local correctName = current_title.text == currentName
if not correctName then
insert(categories, "[[Category:Categories with incorrect names]]")
insert(display, show_error(("Based on the data in the category tree, this category should be called '''[[:Category:%s]]'''."):format(currentName)))
end
-- Add cleanup category for empty categories.
local canBeEmpty = current:canBeEmpty()
if canBeEmpty and correctName then
insert(categories, " __EXPECTUNUSEDCATEGORY__")
elseif totalPages == 0 then
insert(categories, "[[Category:Empty categories]]")
end
if current:isHidden() then
insert(categories, "__HIDDENCAT__")
end
-- Put all the float-right stuff into a <div> that does not clear, so that float-left stuff like the breadcrumbs and
-- description can go opposite the float-right stuff without vertical space.
insert(boxes, "<div style=\"float: right;\">")
insert(boxes, show_topright(current))
insert(boxes, show_editlink(current))
insert(boxes, show_related_changes())
insert(boxes, "</div>")
-- Generate the displayed information
insert(display, show_breadcrumbs(current))
insert(display, show_also(current))
insert(display, show_description(current))
insert(display, show_appendix(current))
insert(display, show_children(current))
insert(display, show_TOC(current))
insert(display, show_catfix(current))
insert(display, '<br class="clear-both-in-vector-2022-only">')
show_categories(current, categories)
return concat(boxes, "\n") .. "\n" .. concat(display, "\n\n") .. concat(categories, "")
end
--[==[
List of handler functions that try to match the page name. A handler should return the name of a submodule to
[[Module:category tree]] and an info table which is passed as an argument to the submodule. If a handler does not
recognize the page name, it should return nil. Note that the order of handlers matters!
]==]
local handlers = {}
-- Thesaurus per-language category
insert(handlers, function(title)
local code, label = title:match("^Thesaurus:(%l[%a-]*%a):(.+)")
if code then
return poscatboiler_subsystem, {label = title, raw = true}
end
end)
-- Topic per-language category
insert(handlers, function(title)
local code, label = title:match("^(%l[%a-]*%a):(.+)")
if code then
return poscatboiler_subsystem, {label = title, raw = true}
end
end)
-- Lect category e.g. for [[:Category:New Zealand English]] or [[:Category:Issime Walser]]
insert(handlers, function(title, args)
local lect = args.lect or args.dialect
if lect ~= "" and yesno(lect, true) then -- Same as boolean in [[Module:parameters]].
return poscatboiler_subsystem, {label = title, args = args, raw = true}
end
end)
-- poscatboiler per-language label, e.g. [[Category:English non-lemma forms]]
insert(handlers, function(title, args)
local lang, label = export.split_lang_label(title)
if not lang then
return
end
local baseLabel, script = label:match("(.+) in (.-) script$")
if script and baseLabel ~= "terms" then
local scriptObj = require("Module:scripts").getByCanonicalName(script)
if scriptObj then
return poscatboiler_subsystem, {label = baseLabel, code = lang:getCode(), sc = scriptObj:getCode(), args = args}
end
end
return poscatboiler_subsystem, {label = label, code = lang:getCode(), args = args}
end)
-- poscatboiler label umbrella category
insert(handlers, function(title, args)
local label = title:match("(.+) by language$")
if label then
-- The poscatboiler code will appropriately lowercase if needed.
return poscatboiler_subsystem, {label = label, args = args}
end
end)
-- poscatboiler raw handlers
insert(handlers, function(title, args)
return poscatboiler_subsystem, {label = title, args = args, raw = true}
end)
-- poscatboiler umbrella handlers without 'by language'
insert(handlers, function(title, args)
return poscatboiler_subsystem, {label = title, args = args}
end)
function export.show(frame)
local args, other_args = require("Module:parameters").process(frame:getParent().args, {
["also"] = {type = "title", sublist = "comma without whitespace", namespace = 14}
}, true)
if args.also then
for k, arg in next, args.also do
args.also[k] = arg.prefixedText
end
end
for k, arg in next, other_args do
other_args[k] = trim(arg)
end
if namespace == 10 then -- Template
return "(This template should be used on pages in the [[Help:Namespaces#Category|Category:]] namespace.)"
elseif namespace ~= 14 then -- Category
error("This template/module can only be used on pages in the [[mw:Help:Namespaces#Category|Category:]] namespace.")
end
local first_fail_args_handled, first_fail_cattext
-- Go through each handler in turn. If a handler doesn't recognize the format of the category, it will return nil,
-- and we will consider the next handler. Otherwise, it returns a template name and arguments to call it with, but
-- even then, that template might return an error, and we need to consider the next handler. This happens, for
-- example, with the category "CAT:Mato Grosso, Brazil", where "Mato" is the name of a language, so the poscatboiler
-- per-language label handler fires and tries to find a label "Grosso, Brazil". This throws an error, and
-- previously, this blocked fruther handler consideration, but now we check for the error and continue checking
-- handlers; eventually, the topic umbrella handler will fire and correctly handle the category.
for _, handler in ipairs(handlers) do
-- Use a new title object and args table for each handler, to keep them isolated.
local submodule, info = handler(current_title.text, deep_copy(other_args))
if submodule then
info.also = deep_copy(args.also)
require("Module:debug").track("auto cat/" .. submodule)
-- `failed` is true if no match was found.
submodule = require(category_tree_submodule_prefix .. submodule)
local cattext, failed = generate_output(submodule.main(info))
if failed then
if not first_fail_cattext then
first_fail_cattext = cattext
first_fail_args_handled = info.args and true or false
end
elseif not info.args and next(other_args) then
error(extra_args_error)
else
return cattext
end
end
end
-- If there were no matches, throw an error if any arguments were given, or otherwise return the cattext
-- from the first fail encountered. The final handlers call the boilers unconditionally, so there should
-- always be something to return.
if not first_fail_args_handled and next(other_args) then
error(extra_args_error)
end
return first_fail_cattext
end
-- TODO: new test entrypoint.
return export
e717al0c4nxeuwi2qq0dbi2fhg032ev
Module:category tree/data
828
5908
17319
17303
2025-07-01T14:23:02Z
Ayane Fumihiro
6766
17319
Scribunto
text/plain
local labels = {}
local raw_categories = {}
local handlers = {}
local raw_handlers = {}
local subpages = {
-- It should not matter much what order we do the handlers in, but topic handling historically
-- preceded "poscatboiler" handling (i.e. everything else), so keep it that way for the moment.
"topic",
"languages",
"miscellaneous",
"wiktionary maintenance",
"wiktionary users",
}
-- Import subpages
for _, subpage in ipairs(subpages) do
local datamodule = "Module:category tree/" .. subpage
local retval = require(datamodule)
if retval["LABELS"] then
for label, data in pairs(retval["LABELS"]) do
if labels[label] and not retval["IGNOREDUP"] then
error("Label " .. label .. " defined in both [["
.. datamodule .. "]] and [[" .. labels[label].module .. "]].")
end
data.module = datamodule
labels[label] = data
end
end
if retval["RAW_CATEGORIES"] then
for category, data in pairs(retval["RAW_CATEGORIES"]) do
if raw_categories[category] and not retval["IGNOREDUP"] then
error("Raw category " .. category .. " defined in both [["
.. datamodule .. "]] and [[" .. raw_categories[category].module .. "]].")
end
data.module = datamodule
raw_categories[category] = data
end
end
if retval["HANDLERS"] then
for _, handler in ipairs(retval["HANDLERS"]) do
table.insert(handlers, { module = datamodule, handler = handler })
end
end
if retval["RAW_HANDLERS"] then
for _, handler in ipairs(retval["RAW_HANDLERS"]) do
table.insert(raw_handlers, { module = datamodule, handler = handler })
end
end
end
-- Add child categories to their parents
local function add_children_to_parents(hierarchy, raw)
for key, data in pairs(hierarchy) do
local parents = data.parents
if parents then
if type(parents) ~= "table" then
parents = {parents}
end
if parents.name or parents.module then
parents = {parents}
end
for _, parent in ipairs(parents) do
if type(parent) ~= "table" or not parent.name and not parent.module then
parent = {name = parent}
end
if parent.name and not parent.module and type(parent.name) == "string" and not parent.name:find("^Category:") then
local parent_is_raw
if raw then
parent_is_raw = not parent.is_label
else
parent_is_raw = parent.raw
end
-- Don't do anything if the child is raw and the parent is lang-specific, otherwise e.g.
-- "Lemmas subcategories by language" will be listed as a child of every "LANG lemmas" category.
-- FIXME: We need to rethink this mechanism.
if not raw or parent_is_raw then
local child_hierarchy = parent_is_raw and raw_categories or labels
if child_hierarchy[parent.name] then
local child = {name = key, sort = parent.sort, raw = raw}
if child_hierarchy[parent.name].children then
table.insert(child_hierarchy[parent.name].children, child)
else
child_hierarchy[parent.name].children = {child}
end
end
end
end
end
end
end
end
add_children_to_parents(labels)
add_children_to_parents(raw_categories, true)
return {
LABELS = labels, RAW_CATEGORIES = raw_categories,
HANDLERS = handlers, RAW_HANDLERS = raw_handlers
}
tho5xdi7wc2sj8rumals2nmwu5exqbg
Module:category tree/wiktionary maintenance
828
5939
17318
2025-07-01T14:22:45Z
Ayane Fumihiro
6766
+
17318
Scribunto
text/plain
local raw_categories = {}
local raw_handlers = {}
local m_template_parser = require("Module:template parser")
local get_lang = require("Module:languages").getByCode
local insert = table.insert
local is_internal_title = require("Module:pages").is_internal_title
local new_title = mw.title.new
local split_lang_label = require("Module:category tree").split_lang_label
local php_trim = require("Module:Scribunto").php_trim
local uses_hidden_category = require("Module:maintenance category").uses_hidden_category
-----------------------------------------------------------------------------
-- --
-- RAW CATEGORIES --
-- --
-----------------------------------------------------------------------------
raw_categories["Wiktionary maintenance"] = {
description = "Categories containing pages that are being tracked for attention and improvement by editors.",
breadcrumb = "Maintenance",
parents = "Wiktionary",
}
raw_categories["Empty categories"] = {
topright = "{{shortcut|CAT:EC}}",
description = "Categories with no members.",
additional = [=[Categories are placed here by [[Module:category tree]] when they contain no pages or subcategories.
Empty categories are not necessarily a problem, but they can clutter up their parent categories, or become orphaned if the structure of the category tree changes. This category therefore helps track down such cases, and allows them to be cleaned up.
Because of the way the wiki software works, categories will appear here for a while afterwards if they were empty at first but had entries added to them later. This can be fixed by simply performing a "null edit" on the category page: edit the page, and save without making any changes. (Alternatively, use the "null edit" option provided by the "purge tab" [[Special:Preferences#mw-prefsection-gadgets|gadget]].) This can be avoided by adding entries to categories before creating them. It also helps to create categories from the "bottom up": start at the lowest level that has entries, then create its parent categories, then the parent categories of that, and so on.]=],
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Categories with incorrect names"] = {
description = "Categories with names that do not match the expected form within the category tree.",
additional = [=[This usually happens when additional parameters have been given to {{tl|auto cat}} that don't match the name of the category, or when there is a problem with capitalization or spacing in the category name.
==See also==
* [[:Category:Categories that are not defined in the category tree]]]=],
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Categories that are not defined in the category tree"] = {
description = "Categories which use {{tl|auto cat}}, but which are not registered in the category tree data modules.",
additional = [=[See the error box displayed on any of these categories for more info.
==See also==
* [[:Category:Categories with incorrect names]]]=],
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Hidden categories"] = {
description = "Categories using the <code>[[mw:Help:Magic words#HIDDENCAT|<nowiki>__HIDDENCAT__</nowiki>]]</code> behavior switch, which hides the category from the lists of categories in its members and subcategories.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Huge categories"] = {
description = "Categories with more than 1 million members.",
additional = "Such categories have the [[mw:Extension:DynamicPageList (Wikimedia)|DynamicPageList]] extension disabled, which is normally used to list the newest and oldest pages in a category. This is because categories above that size load very slowly when it is enabled, and in some cases become inaccessible due to timing-out.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Indexed pages"] = {
description = "Pages using the <code>[[mw:Help:Magic words#INDEX|<nowiki>__INDEX__</nowiki>]]</code> behavior switch, which tells search engines to index the page.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Noindexed pages"] = {
description = "Pages using the <code>[[mw:Help:Magic words#NOINDEX|<nowiki>__NOINDEX__</nowiki>]]</code> behavior switch, which tells search engines not to index the page.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages using deprecated templates"] = {
description = "This category contains entries, reconstruction pages, appendixes, sign glosses and citations pages using deprecated templates—templates that have failed our deletion process, and/or that have been replaced by superior templates.",
additional = [=[This category is populated by {{tl|deprecated code}} and {{tl|deprecated lang param usage}}. The former is wrapped around templates that have been completely deprecated and remove from mainspace (particularly those in [[:Category:Successfully deprecated templates]]). The latter is wrapped around non-deprecated templates that accept the deprecated {{para|lang}} parameter; any use of that parameter will place the page in [[:Category:Pages using deprecated templates]]. Ideally, this category will be empty.
Any pages in this category, particularly those in the mainspace, need to have their deprecated template usages corrected. ]=],
breadcrumb = "Using deprecated templates",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages using lite templates"] = {
description = "Pages which use at least one of the lite templates.",
additional = "See [[:Category:Lua-free templates]].",
breadcrumb = "Using lite templates",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with tab characters"] = {
description = "Pages which contain a tab character in their wikitext.",
additional = "These should either be removed or replaced with spaces, because they go against [[WT:NORM]].",
breadcrumb = "Tab characters",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with language headings in the wrong order"] = {
description = "Pages in which the headings for each language's entry are in the wrong order.",
additional = "Level 2 language headings should be in alphabetical order, except for Translingual and English, which go at the top (in that order).",
breadcrumb = "Language headings in the wrong order",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with nonstandard language headings"] = {
description = "Pages which contain a level 2 heading which does not match any language's canonical name.",
additional = "The level 2 language heading for each language should always be that language's canonical name.",
breadcrumb = "Nonstandard language headings",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with unwanted L1 headings"] = {
description = "Pages which contain an unwanted level 1 heading.",
additional = "Level 1 headings are not used in Wiktionary content pages, and only occur due to user error or vandalism.",
breadcrumb = "Unwanted L1 headings",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with raw triple-brace template parameters"] = {
description = "Pages which contain raw template parameters in the form of triple braces.",
additional = "Triple-brace template parameters (e.g. {{param|param}}) are intended for use in templates, as they are substituted with the relevant template argument when the page is transcluded. Although they can theoretically be used on any page, there are currently no legitimate uses for them in content namespaces.\n\nTemplate parameters usually occur due to typos, or when {{tl|subst:}} has been used with a template that isn't supposed to be substed.",
breadcrumb = "Raw template parameters",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with DEFAULTSORT conflicts"] = {
topright = "{{shortcut|CAT:DEFAULTSORT}}",
description = "Pages on which the {{tl|DEFAULTSORT:}} magic word has been used multiple times with different values.",
additional = "In some (but not all) cases, this causes a warning to display on the page. In the vast majority of instances, an explicit use of {{tl|DEFAULTSORT:}} in wikitext should be <u>removed</u>.This is because the {{tl|head}} template handles it automatically. The only instances where it should be used in wikitext is outside of entries (i.e. outside of mainspace or the Reconstruction namespace)." ..
"\n\nSee also [[:Category:Pages with DISPLAYTITLE conflicts]].",
breadcrumb = "DEFAULTSORT conflicts",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with DISPLAYTITLE conflicts"] = {
topright = "{{shortcut|CAT:DISPLAYTITLE}}",
description = "Pages on which the {{tl|DISPLAYTITLE:}} magic word has been used multiple times with different values.",
additional = "In some (but not all) cases, this causes a warning to display on the page. In the vast majority of instances, an explicit use of {{tl|DISPLAYTITLE:}} in wikitext should be <u>removed</u>.This is because the {{tl|head}} template handles it automatically. The only instances where it should be used in wikitext is outside of entries (i.e. outside of mainspace or the Reconstruction namespace)." ..
"\n\nSee also [[:Category:Pages with DEFAULTSORT conflicts]].",
breadcrumb = "DISPLAYTITLE conflicts",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with raw sortkeys"] = {
description = "Pages on which a sortkey has been used with a raw category.",
additional = "For example, {{code|[[<nowiki/>Category:IPA symbols|B]]}}." ..
"\n\nThese are a priority to replace with category templates, since they are hard-coded and override the {{tl|DEFAULTSORT:}} value for the page. This causes problems if there are any changes to the sorting scheme for the category, because there is no way of changing them centrally.\n\n" ..
"By comparison, raw categories which have no sortkey are less of a problem, because they will use the {{tl|DEFAULTSORT:}} value; this can be centrally controlled and is designed to be language-neutral, so avoids the issue of different editors using multiple different sorting schemes for the same category. However, they should still be replaced with category templates, since there may be additional language-specific sorting rules which cannot otherwise be applied.",
breadcrumb = "Raw sortkeys",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with module errors"] = {
topright = "{{shortcut|CAT:E|CAT:ERR|CAT:ERROR}}",
description = "Pages that have errors in a [[Wiktionary:Scribunto|Lua]] module.",
additional = "If entries are listed here for more than a day or two, the error should probably be reported at [[Wiktionary:GP|the Grease Pit]]. Memory errors are a common source of these errors; see the discussion at [[Wiktionary:Lua memory errors]]." ..
"\n\nBecause the software does not immediately update pages when a change occurs in a template or module, errors listed here may have already been fixed. Therefore, please ensure that the error is still present before reporting problems. You can do this by performing a \"[[mw:Help:Dummy_edit#A_null_edit|null edit]]\" (editing the page and saving without making changes). If the error goes away then, it has already been fixed." ..
"\n\n<u>You can use [https://en.wiktionary.org/wiki/Special:ApiSandbox#action=purge&format=json&forcelinkupdate=1&generator=categorymembers&utf8=1&formatversion=2&gcmtitle=Category%3APages%20with%20module%20errors&gcmlimit=20 this link] and press \"Make request\" to purge the cache of up to 20 pages from this category in one click.</u> This number can be adjusted up to 5,000, but anything above 30–100 will likely cause time-outs (depending on the size of the pages)." ..
"\n\nThe contents of this category is controlled by [[Template:maintenance category]]. It is currently set to place talk pages, user pages{{,}} and user sandbox modules and templates in a separate category." ..
"\n\nSee also [[:Category:Pages with ParserFunction errors]].",
breadcrumb = "Module errors",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages with ParserFunction errors"] = {
topright = "{{shortcut|CAT:PFE}}",
description = "Pages that have errors in a [[mw:Help:Extension:ParserFunctions|ParserFunction]] magic word.",
additional = "Examples of these magic words are {{tl|#expr:}} and {{tl|#time:}}. If entries are listed here for more than a day or two, the error should probably be reported at [[Wiktionary:GP|the Grease Pit]]." ..
"\n\nBecause the software does not immediately update pages when a change occurs in a template or module, errors listed here may have already been fixed. Therefore, please ensure that the error is still present before reporting problems. You can do this by performing a \"[[meta:Help:Dummy_edit#Null_edit|null edit]]\" (editing the page and saving without making changes). If the error goes away then, it has already been fixed." ..
"\n\n<u>You can use [https://en.wiktionary.org/wiki/Special:ApiSandbox#action=purge&format=json&forcelinkupdate=1&generator=categorymembers&utf8=1&formatversion=2&gcmtitle=Category%3APages%20with%20ParserFunction%20errors&gcmlimit=20 this link] and press \"Make request\" to purge the cache of up to 20 pages from this category in one click.</u> This number can be adjusted up to 5,000, but anything above 30–100 will likely cause time-outs (depending on the size of the pages)." ..
"\n\nThe contents of this category is controlled by [[Template:maintenance category]]. It is currently set to place talk pages, user pages{{,}} and user sandbox modules and templates in a separate category." ..
"\n\nSee also [[:Category:Pages with module errors]].",
breadcrumb = "ParserFunction errors",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Requests for moves, mergers and splits"] = {
description = "Pages and categories which have been tagged with a request for them to be moved, merged or split.",
breadcrumb = "Moves, mergers and splits",
parents = {"Wiktionary maintenance", "Requests"},
can_be_empty = true,
hidden = true,
}
raw_categories["Pages to be merged"] = {
description = "Pages tagged to be merged by the {{tl|merge}} template.",
parents = "Requests for moves, mergers and splits",
can_be_empty = true,
}
raw_categories["Pages to be moved"] = {
description = "Pages tagged to be moved by the {{tl|move}} template.",
parents = "Requests for moves, mergers and splits",
can_be_empty = true,
}
raw_categories["Pages to be split"] = {
description = "Pages tagged to be split by the {{tl|split}} template.",
parents = "Requests for moves, mergers and splits",
can_be_empty = true,
}
raw_categories["Pages using invalid parameters when calling templates"] = {
description = "Pages that use unrecognized parameters when calling a template.",
breadcrumb = "Invalid template parameters",
parents = "Wiktionary maintenance",
can_be_empty = true,
}
raw_categories["Pages using catfix"] = {
description = "Pages that use the <code>[[MediaWiki:Gadget-catfix.js|catfix]]</code> gadget.",
additional = "This processes links to entries in language-specific categories by adding language-specific formatting, and points them to the language's section of the entry.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages calling Template:minitoc"] = {
description = "Pages that display a mini table of contents by calling {{tl|minitoc}}.",
additional = "This is is used on very large pages with many entries, to assist with navigation.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Categories calling Template:auto cat"] = {
description = "Categories that have been placed in another category by calling {{tl|auto cat}}.",
additional = "This is the preferred way for categories to be subcategorized. The chief reason for this category is to facilitate the finding of categories which are not using {{tl|auto cat}} through the use of negative searches (e.g. qualifying a search with {{code|-incategory:\"{{PAGENAME}}\"}}).",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Categories with categories using raw markup"] = {
description = "Categories that have been placed in another category using raw wiki markup (e.g. {{cl|Wiktionary}}). They should be added to the [[Module:category tree|category tree]] data instead.",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
raw_categories["Pages using deprecated source tags"] = {
description = "Pages that use the [[mw:Extension:SyntaxHighlight|SyntaxHighlight]] extension with legacy {{wt|source}} tags instead of {{wt|syntaxhighlight}}.",
breadcrumb = "Deprecated source tags",
parents = "Wiktionary maintenance",
can_be_empty = true,
hidden = true,
}
insert(raw_handlers, function(data)
local template_type = data.category:match("^Pages using invalid parameters when calling (.+) templates$")
if not template_type then
return
end
local parents = {{
name = "Pages using invalid parameters when calling templates",
sort = template_type == "general use" and "*" or template_type,
}}
local lang = require("Module:languages").getByCanonicalName(template_type, nil, true)
if lang then
insert(parents, {name = "entry maintenance", is_label = true, lang = lang:getCode()})
end
return {
lang = lang and lang:getCode() or nil,
description = "Pages that use unrecognized parameters when calling " .. template_type .. " templates.",
parents = parents,
breadcrumb = template_type,
}
end)
do
local prefixes = require("Module:table").listToSet{"list", "P", "R", "RQ", "table", "U"}
local function add_parent(parents, seen, cat_type, sortkey)
if seen[cat_type] then
return
end
insert(parents, {
name = ("Pages using invalid parameters when calling %s templates"):format(cat_type),
sort = sortkey,
})
seen[cat_type] = true
end
insert(raw_handlers, function(data)
local template = data.category:match("^Pages using invalid parameters when calling (.+)$")
if not template then
return
end
-- Resolve any redirects.
template = new_title(template)
while template do
local redirect = template.redirectTarget
if not (redirect and is_internal_title(redirect)) then
break
end
template = redirect
end
-- Disallow templates which would always hidden maintennace categories (e.g. sandboxes).
if not (template and not uses_hidden_category(template)) then
return
end
local prefixed_text, lang = template.prefixedText
if template.namespace == 10 then
local name = template.text
-- Remove the prefix if present (e.g. "R:" or "RQ:").
local prefix, text = name:match("^(.-):(.+)")
if not (prefix and prefixes[prefix]) then
text = name
end
-- Check the initial language code, chopping off hyphenated sections until there's a match or they run out.
local code = mw.ustring.match(text, "^[a-z][a-zA-Z-]*[a-zA-Z]%f[^%w]")
while code do
lang = get_lang(code)
if lang then
break
end
code = code:match("(.+)%-%a*$")
end
-- If no match and it's a list: or table: template, check if the template name ends "/CODE".
if not lang and (prefix == "list" or prefix == "table") then
code = text:match("%f[^/]%l[%a-]*%a$")
if code then
lang = get_lang(code)
end
end
end
local sortkey = template.text
local parents, seen = {}, {}
-- Categorize as language-specific if a language was found.
if lang then
add_parent(parents, seen, lang:getCanonicalName(), sortkey)
end
-- Also grab any language categories from the template page.
for _, cat in ipairs(template.categories) do
if cat:sub(-10) == " templates" or cat:sub(-13) == " subtemplates" then
local cat_lang = split_lang_label(new_title(cat).text)
if cat_lang then
add_parent(parents, seen, cat_lang:getCanonicalName(), sortkey)
end
end
end
-- If none were found, categorize as general use.
if #parents == 0 then
add_parent(parents, seen, "general use", sortkey)
end
-- Only add can_be_empty if the template exists and contains checkparams.
local content, can_be_empty = template:getContent()
if content then
-- Check for {{#invoke:checkparams|warn|...}}.
-- args[1] is the module and args[2] is the function name, so #INVOKE: will throw an error if either is not present.
for template in require("Module:template parser").find_templates(content) do
if template:get_name() == "#INVOKE:" then
local args = template:get_arguments()
local arg_2 = args[2]
if arg_2 and php_trim(args[1]) == "checkparams" and php_trim(arg_2) == "warn" then
can_be_empty = true
break
end
end
end
end
return {
canonical_name = "Pages using invalid parameters when calling " .. prefixed_text,
lang = lang and lang:getCode() or nil,
description = ("Pages that use unrecognized parameters when calling {{tl|%s}}.")
:format(m_template_parser.getTemplateInvocationName(template)),
additional = "These template calls should be reviewed and the invalid parameter(s) should be corrected or removed.",
breadcrumb = prefixed_text,
parents = parents,
can_be_empty = can_be_empty,
hidden = true,
}
end)
end
return {RAW_CATEGORIES = raw_categories, RAW_HANDLERS = raw_handlers}
lglxszzruvohq713tjcfamj41s07rls
Module:maintenance category
828
5940
17320
2025-07-01T14:23:37Z
Ayane Fumihiro
6766
+
17320
Scribunto
text/plain
local export = {}
local pages_module = "Module:pages"
local parameters_module = "Module:parameters"
local utilities_module = "Module:utilities"
local new_title = mw.title.new
local uses_hidden_category -- Defined below.
--[==[
Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==]
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function is_sandbox(...)
is_sandbox = require(pages_module).is_sandbox
return is_sandbox(...)
end
local function is_testcase_page(...)
is_testcase_page = require(pages_module).is_testcase_page
return is_testcase_page(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
--[==[
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
local current_title
local function get_current_title()
current_title, get_current_title = mw.title.getCurrentTitle(), nil
return current_title
end
function export.uses_hidden_category(title)
local namespace = title.namespace
-- Thread: and Summary: pages are named "Thread:PAGE" or "Summary:PAGE",
-- where PAGE is the page they relate to. How we treat them therefore
-- depends on what that page is.
while namespace == 90 or namespace == 92 do
title = new_title(title.text)
namespace = title.namespace
end
-- User: and all talk namespaces, as well as all sandboxes and testcase pages (including their documentation pages).
return (
namespace == 2 or
title.isTalkPage or
is_sandbox(title, "include documentation") or
is_testcase_page(title, "include documentation")
) and true or false
end
uses_hidden_category = export.uses_hidden_category
function export.get_category(name, cat)
if uses_hidden_category(current_title or get_current_title()) then
name = name .. "/hidden"
end
return cat and format_categories(name, nil, "-", nil, true) or name
end
function export.template(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, default = ""},
["cat"] = {type = "boolean", default = false}
})
return export.get_category(args[1], args.cat)
end
return export
0k9xe0i9582irnmc4uhevzdi2o9uso3