模組:Category tree/poscatboiler/data/lang-specific

This is the documentation page for the main language-specific data module for Module:category tree/poscatboiler, as well as for its submodules. Collectively, these modules handle generating the descriptions and categorization for language-specific category pages of the format "LANG LABEL" (e.g. Category:Bulgarian conjugation 2.1 verbs and Category:Russian velar-stem neuter-form nouns). "Language-specific" means that the category labels (in these examples, "conjugation 2.1 verbs" and "velar-stem neuter-form nouns") are specialized to apply only to particular languages, unlike a category such as Category:Bulgarian verbs or Category:Russian nouns, where the labels "verbs" and "nouns" apply to all languages.

To understand how these data modules work, you should first familiarize yourself with how poscatboiler labels and handlers work in general. See Module:category tree/poscatboiler/data/doc for information on this.

Language-specific labels and handlers work almost identically to non-language-specific labels and handlers. Labels have the same fields, and handlers are called with the same arguments and should return the same types of objects. The only real difference is that language-specific categories don't normally have corresponding umbrella categories, so there is no need to set the umbrella or umbrella_parents fields.

The language-specific module for a given language should be named Module:category tree/poscatboiler/data/lang-specific/LANGCODE where LANGCODE is the language code for the language in question, e.g. Module:category tree/poscatboiler/data/lang-specific/bg for Bulgarian. To add a new data submodule, copy an existing submodule and modify its contents. Then, add its language code to the langs_with_modules list at the top of Module:category tree/poscatboiler/data/lang-specific. Note that the module for a given language is only loaded when a category referencing that particular language is encountered and the category's label is unrecognized.

The text of any category page using this module should simply read {{auto cat}}.
The correct way to invoke this module on a given category page that it handles is through {{auto cat}}. You should not normally invoke {{poscatboiler}} directly. If you find a category page that directly invokes {{poscatboiler}}, it is probably old, from before when {{auto cat}} was created, and should be changed.

Adding, removing or modifying categories

A sample entry is as follows (in this case, found in Module:category tree/poscatboiler/data/lang-specific/be):

labels["verbs by class and accent pattern"] = {
	description = "Belarusian verbs categorized by class and accent pattern.",
	parents = {{name = "verbs by inflection type", sort = "class and accent pattern"}},
}

See Module:category tree/poscatboiler/data/doc for more information.

Handlers

A sample handler follows (in this case for Belarusian categories of the form Category:Belarusian class 2 verbs or Category:Belarusian class 4c verbs):

table.insert(handlers, function(data)
	local cls, pattern = data.label:match("^class ([0-9]*)([abc]?) verbs")
	if cls then
		if pattern == "" then
			return {
				description = "Belarusian class " .. cls .. " verbs.",
				breadcrumb = cls,
				parents = {{name = "verbs by class", sort = cls}},
			}
		else
			return {
				description = "Belarusian class " .. cls .. " verbs of " ..
					"accent pattern " .. pattern .. ". " .. (
					pattern == "a" and "With this pattern, all forms are stem-stressed."
					or pattern == "b" and "With this pattern, all forms are ending-stressed."
					or "With this pattern, the first singular present indicative and all forms " ..
					"outside of the present indicative are ending-stressed, while the remaining " ..
					"forms of the present indicative are stem-stressed."
				),
				breadcrumb = cls .. pattern,
				parents = {
					{name = "class " .. cls .. " verbs", sort = pattern},
					{name = "verbs by class and accent pattern", sort = cls .. pattern},
				},
			}
		end
	end
end)

Another example, for categories like Category:Dutch prefixed verbs with ver-:

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

table.insert(handlers, function(data)
	local pref = data.label:match("^prefixed verbs with (.+%-)$")
	if pref then
		local link = require("Module:links").full_link({ lang = lang, term = pref }, "term")
		local altlink = require("Module:links").full_link({ lang = lang, alt = pref }, "term")
		return {
			description = "Dutch prefixed verbs with the prefix " .. link .. ".",
			displaytitle = "Dutch prefixed verbs with " .. altlink,
			breadcrumb = altlink,
			parents = {{name = "prefixed verbs", sort = pref}},
		}
	end
end)

Here, we use displaytitle= to italicize the prefix in the title (and also italicize it in the breadcrumb and description).

See Module:category tree/poscatboiler/data/doc for more information.

Subpages


-- This module contains language-specific labels and handlers.

-- This module contains a list of languages with lang-specific modules.

local langs_with_modules = {
	["acw"] = true,
	["acy"] = true,
	["aeb"] = true,
	["afb"] = true,
	["ajp"] = true,
	["ang"] = true,
	["apc"] = true,
	["apd"] = true,
	["ar"] = true,
	["ary"] = true,
	["arz"] = true,
	["ayl"] = true,
	["az"] = true,
	["be"] = true,
	["bcl"] = true,
	["bg"] = true,
	["ca"] = true,
	["cbk"] = true,
	["ceb"] = true,
	["cs"] = true,
	["csb"] = true,
	["cu"] = true,
	["de"] = true,
	["el"] = true,
	["en"] = true,
	["enm"] = true,
	["es"] = true,
	["et"] = true,
	["eu"] = true,
	["fa"] = true,
	["fax"] = true,
	["fi"] = true,
	["fr"] = true,
	["gl"] = true,
	["gmh"] = true,
	["goh"] = true,
	["got"] = true,
	["grk-pro"] = true,
	["gmw-pro"] = true,
	["he"] = true,
	["hi"] = true,
	["hil"] = true,
	["hnn"] = true,
	["hrx"] = true,
	["hsb"] = true,
	["id"] = true,
	["ilo"] = true,
	["inc-ash"] = true,
	["ine-pro"] = true,
	["ira-pro"] = true,
	["it"] = true,
	["ja"] = true,
	["jpx"] = true,
	["klj"] = true,
	["kne"] = true,
	["krj"] = true,
	["la"] = true,
	["lo"] = true,
	["mdh"] = true,
	["mk"] = true,
	["mr"] = true,
	["mrw"] = true,
	["ms"] = true,
	["mt"] = true,
	["mul"] = true,
	["nan-hbl"] = true,
	["nb"] = true,
	["ne"] = true,
	["nl"] = true,
	["nn"] = true,
	["non"] = true,
	["orv"] = true,
	["pag"] = true,
	["pam"] = true,
	["phl"] = true,
	["pi"] = true,
	["pl"] = true,
	["pra"] = true,
	["pt"] = true,
	["qfa-kor"] = true,
	["ro"] = true,
	["ru"] = true,
	["rue"] = true,
	["sa"] = true,
	["sc"] = true,
	["sei"] = true,
	["sga"] = true,
	["shn"] = true,
	["shu"] = true,
	["sk"] = true,
	["tg"] = true,
	["th"] = true,
	["tl"] = true,
	["tpw"] = true,
	["tsg"] = true,
	["uk"] = true,
	["ur"] = true,
	["vep"] = true,
	["vi"] = true,
	["war"] = true,
	["yrl"] = true,
	["zh"] = true, -- should be moved to zhx
	["zle-ono"] = true,
	["zlw-ocs"] = true,
}


--------------------------- Generic driver handler ----------------------------

local function get_family_modules(lang)
	local obj = lang
	local seen = {}
	local modules = {}
	
	repeat
		local code = obj:getCode()
		mw.log('Checking code: ' .. code)
		if langs_with_modules[code] then
			mw.log('Found module for: ' .. code)
			table.insert(modules, "Module:category tree/poscatboiler/data/lang-specific/" .. code)
		end
		seen[code] = true
		obj = obj:getFamily()
		if obj then
			mw.log('Found family: ' .. obj:getCode())
		end
	until not obj or seen[obj:getCode()]
	
	return modules
end

local function lang_specific_handler(data)
	if not data.lang then
		mw.log('No language provided')
		return nil
	end
	
	mw.log('Handling label: ' .. data.label)
	
	-- 建立用來收集標籤的臨時表
	local all_labels = {}
	
	-- Get all relevant modules in the language family chain
	local modules = get_family_modules(data.lang)
	
	-- Try each module in order
	for _, module_name in ipairs(modules) do
		mw.log('Trying to load: ' .. module_name)
		local success, module = pcall(require, module_name)
		if success then
			mw.log('Successfully loaded: ' .. module_name)
			
			-- 處理直接回傳 {LABELS = labels} 的模組
			if module.LABELS then
				mw.log('Module has direct LABELS table')
				for label, def in pairs(module.LABELS) do
					all_labels[label] = def
				end
			end
			
			-- 處理使用 add_labels 的模組
			if module.add_labels then
				mw.log('Module has add_labels function')
				module.add_labels(all_labels, data.lang)
			end
			
			-- 檢查是否找到我們要的標籤
			local retval = all_labels[data.label]
			if retval then
				mw.log('Found label "' .. data.label .. '" in ' .. module_name)
				if retval.umbrella == nil and retval.umbrella_parents == nil then
					retval.umbrella = false
				end
				retval.module = retval.module or module_name
				return retval
			end
			
			-- 處理處理器
			if module.HANDLERS or module.add_handlers then
				local handlers = {}
				if module.HANDLERS then
					handlers = module.HANDLERS
				end
				if module.add_handlers then
					module.add_handlers(handlers, data.lang, require("Module:languages"))
				end
				
				for i, handler in ipairs(handlers) do
					mw.log('Trying handler #' .. i)
					local handler_retval, args_handled = handler(data)
					if handler_retval then
						mw.log('Handler #' .. i .. ' returned a result')
						if handler_retval.umbrella == nil and handler_retval.umbrella_parents == nil then
							handler_retval.umbrella = false
						end
						handler_retval.module = handler_retval.module or module_name
						return handler_retval, args_handled
					end
				end
			end
		else
			mw.log('Failed to load module: ' .. module)
		end
	end
	
	mw.log('No matching label or handler found')
	return nil
end

return {LABELS = {}, HANDLERS = {lang_specific_handler}}