Modul:category tree/poscatboiler/data/wiktionary

Pendokumenan untuk modul ini boleh diciptakan di Modul:category tree/poscatboiler/data/wiktionary/doc

local raw_categories = {}
local raw_handlers = {}


-----------------------------------------------------------------------------
--                                                                         --
--                              RAW CATEGORIES                             --
--                                                                         --
-----------------------------------------------------------------------------


raw_categories["Wiktionary"] = {
	description = "Kategori peringkat tinggi untuk bahan tentang Wiktionary dan pengendaliannya.",
	parents = {
		"Asas",
	},
}

raw_categories["Pengguna Wikikamus"] = {
	description = "Halaman menyenaraikan Ahli Wikikamus mengikut hak pengguna dan kategori mereka menyenaraikan Ahli Wiktionarian mengikut keupayaan linguistik dan pengekodan mereka.",
	breadcrumb = "Pengguna",
	additional = "Untuk senarai semua pengguna yang dijana secara automatik, lihat [[Special:ListUsers]].",
	parents = {
		{name = "Wiktionary", sort = "Pengguna"},
	},
}

raw_categories["Isu keberbilangan bahasa Wikikamus"] = {
	description = "Kategori menyenaraikan isu berkenaan keberbilangan bahasa di Wikikamus.",
	parents = {
		"Pengguna Wikikamus",
	},
}

raw_categories["Bahasa pengguna"] = {
	description = "Kategori menyenaraikan ahli Wikikamus mengikut keupayaan linguistik mereka.",
	parents = {
		"Pengguna Wikikamus",
		"Isu keberbilangan bahasa Wikikamus",
	},
}

raw_categories["Bahasa pengguna dengan kod tak sah"] = {
	description = "Categories listing Wiktionarians according to their linguistic abilities, where the language code is invalid for Wiktionary.",
	additional = "Most of these codes are valid ISO 639-3 codes but are invalid in Wiktionary for various reasons, " ..
	"typically due to different choices made regarding splitting and merging languages.",
	parents = {
		{name = "Bahasa pengguna", sort = " "},
	},
}

raw_categories["Tulisan pengguna"] = {
	description = "Kategori menyenaraikan ahli Wikikamus mengikut kebolehan mereka membaca tulisan yang diberikan.",
	parents = {
		"Pengguna Wikikamus",
		"Isu keberbilangan bahasa Wikikamus",
	},
}

raw_categories["Pengekod pengguna"] = {
	description = "Categories listing Wiktionarians according to their coding abilities.",
	parents = {
		"Pengguna Wikikamus",
	},
}

raw_categories["Tajuk tak tersokong"] = {
	description = "Pages with titles that are not supported by the MediaWiki software.",
	additional = "For an explanation of the reasons why certain titles are not supported, see [[Lampiran:Tajuk tak tersokong]].",
	parents = {"Wiktionary"},
	hidden = true,
}


-----------------------------------------------------------------------------
--                                                                         --
--                                RAW HANDLERS                             --
--                                                                         --
-----------------------------------------------------------------------------


-- Fancy version of ine() (if-not-empty). Converts empty string to nil, but also strips leading/trailing space.
local function ine(arg)
	if not arg then return nil end
	arg = mw.text.trim(arg)
	if arg == "" then return nil end
	return arg
end


local function get_level_params(data)
	local speak_verb = "bertutur"
	if data.typ == "lang" then
		local is_sign_language = data.obj and data.obj:getFamilyCode():find("^sgn") or data.name:find("Bahasa Isyarat$")
		speak_verb = data.args.verb or is_sign_language and "berkomunikasi dalam" or "bertutur"
	end
	return {
		["-"] = {
			leftcolor = "#99B3FF",
			rightcolor = "#E0E8FF",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME.",
			script = "Pengguna tersebut boleh membaca NAME.",
			coder = "Pengguna tersebut tahu bagaimana mengekod dalam NAME.",
		},
		["0"] = {
			leftcolor = "#FFB3B3",
			rightcolor = "#FFE0E8",
			lang = "Pengguna tersebut tidak faham akan NAME (atau memahaminya dengan kesukaran yang agak tinggi).",
			script = "Pengguna tersebut '''tidak boleh''' membaca NAME.",
			coder = "Pengguna tersebut tahu '''sedikit''' berkenaan NAME dan hanya meniru penggunaan kod sedia ada.",
		},
		["1"] = {
			leftcolor = "#C0C8FF",
			rightcolor = "#F0F8FF",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME pada tahap '''asas'''.",
			script = "Pengguna tersebut boleh membaca NAME pada tahap '''asas'''.",
			coder = "Pengguna tersebut tahu '''asas''' bagaimana menulis kod NAME kod dan buat pengubahsuaian kecil.",
		},
		["2"] = {
			leftcolor = "#77E0E8",
			rightcolor = "#D0F8FF",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME pada tahap '''sederhana'''.",
			script = "Pengguna tersebut boleh membaca NAME pada tahap '''sederhana'''.",
			coder = "Pengguna tersebut have a '''fair command''' of NAME, and can understand some scripts written by others.",
		},
		["3"] = {
			leftcolor = "#99B3FF",
			rightcolor = "#E0E8FF",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME pada tahap '''lanjutan''' .",
			script = "Pengguna tersebut boleh membaca NAME pada tahap '''lanjutan''' .",
			coder = "Pengguna tersebut can write '''more complex''' NAME code, and can understand and modify most scripts written by others.",
		},
		["4"] = {
			leftcolor = "#CCCC00",
			rightcolor = "#FFFF99",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME pada tahap '''hampir asli'''.",
			script = "Pengguna tersebut boleh baca NAME pada tahap '''hampir asli'''.",
			coder = "Pengguna tersebut boleh tulis dan faham akan kod NAME yang '''amat kompleks'''.",
		},
		["5"] = {
			leftcolor = "#FF5E5E",
			rightcolor = "#FF8080",
			lang = "Pengguna tersebut " .. speak_verb .. " NAME pada tahap '''profesional'''.",
			script = "Pengguna tersebut boleh baca NAME pada tahap '''profesional'''.",
			coder = "Pengguna tersebut boleh tulis dan faham akan NAME code pada tahap'''profesional'''.",
		},
		["N"] = {
			leftcolor = "#6EF7A7",
			rightcolor = "#C5FCDC",
			lang = "Pengguna tersebut merupakan penutur '''asli''' NAME.",
			script = "Tulisan '''asli''' pengguna tersebut ialah NAME.",
		},
	}
end


local coder_links = {
	Bash = "w:Bash (Unix shell)",
	C = "w:C (programming language)",
	["C++"] = "w:C++",
	["C Sharp"] = {link = "w:C Sharp", name = "C#"},
	CSS = "w:Lembaran Gaya Lata",
	Go = "w:Go (bahasa pengaturcaraan)",
	HTML = "w:HTML",
	Java = "w:Java (bahasa pengaturcaraan)",
	JavaScript = "w:JavaScript",
	Julia = "w:Julia (bahasa pengaturcaraan)",
	Lisp = "w:LISP",
	Lua = "Wiktionary:Pengekodan",
	Perl = "w:Perl",
	Python = "w:Python",
	Ruby = "w:Ruby",
	Scala = "w:Scala (bahasa pengaturcaraan)",
	Scheme = "w:Scheme (bahasa pengaturcaraan)",
	template = {link = "Wiktionary:Templat", name = "templat wiki"},
	VBScript = "w:VBScript",
}


-- Generic implementation of competency handler for (natural) languages, scripts, and "coders" (= programming languages).
local function competency_handler(data)
	local category = data.category
	local langtext = data.langtext
	local typ = data.typ
	local obj = data.obj
	local args = data.args
	local code = data.code
	local name = data.name
	local namecat = data.namecat
	local level = data.level
	local parents = data.parents
	local topright = data.topright
	local data_addl = data.additional

	local parts = {}
	local function ins(txt)
		table.insert(parts, txt)
	end
	local level_params = get_level_params(data)

	local params = level_params[level or "-"]
	if not params then
		error(("Ralat dalaman: Tiada param untuk kod '%s', aras %s"):format(code, level or "-"))
	end
	local function insert_text()
		if langtext then
			ins(langtext)
			ins("<hr />")
		end
		if not params[typ] then
			error(("Tiada teks bahasa Melayu untuk kod '%s', jenis '%s', aras %s"):format(code, typ, level or "-"))
		end
		ins(params[typ]:gsub("NAME", ("'''" .. namecat .. "'''"):format(name)))
	end

	local additional
	if level then
		additional = ("Untuk disertakan dalam senarai ini, tambah <code>{{tl|Babel|%s}}</code> pada halaman pengguna anda. " ..
			"Panduan lengkap ada di [[Wiktionary:Babel]]."):format(level == "N" and code or ("%s-%s"):format(code, level)) ..
			(data_addl and "\n\n" .. data_addl or "")
	else
		additional = ("Untuk disertakan dalam senarai ini, gunakan <code>{{tl|Babel}}</code> pada halaman pengguna anda. " ..
			"Panduan lengkap ada di [[Wiktionary:Babel]].") ..
			(data_addl and "\n\n" .. data_addl or "")
	end

	if level then
		ins(('<div style="float:left;border:solid %s 1px;margin:1px">'):format(params.leftcolor))
		ins(('<table cellspacing="0" style="width:238px;background:%s"><tr>'):format(params.rightcolor))
		ins(('<td style="width:45px;height:45px;background:%s;text-align:center;font-size:14pt">'):format(params.leftcolor))
		ins(("'''%s-%s'''</td>"):format(code, level))
		ins('<td style="font-size:8pt;padding:4pt;line-height:1.25em">')
		insert_text()
		ins('</td></tr></table></div><br clear="left">')

		return {
			description = table.concat(parts),
			additional = additional,
			breadcrumb = "Aras " .. level,
			parents = parents,
		}, not not args
	else
		ins(('<div style="float:left;border:solid %s 1px;margin:1px;">\n'):format(params.leftcolor))
		ins(('{| cellspacing="0" style="width:260px;background:%s;"\n'):format(params.rightcolor))
		ins(('| style="width:45px;height:45px;background:%s;text-align:center;font-size:14pt;" | '):format(params.leftcolor))
		ins(("'''%s'''\n"):format(code))
		ins('| style="font-size:8pt;padding:4pt;line-height:1.25em;text-align:center;" | ')
		insert_text()
		ins('\n|}</div><br clear="left">')

		return {
			topright = topright,
			description = table.concat(parts),
			additional = additional,
			breadcrumb = name,
			parents = parents,
		}, not not args
	end
end


table.insert(raw_handlers, function(data)
	local code, level
	if not code then
		code, level = data.category:match("^Pengguna ([a-z][a-z][a-z]?)%-([0-5N])$")
	end
	if not code then
		code, level = data.category:match("^Pengguna ([a-z][a-z][a-z]?%-[a-zA-Z-]+)%-([0-5N])$")
	end
	if not code then
		code = data.category:match("^Pengguna ([a-z][a-z][a-z]?)$")
	end
	if not code then
		code = data.category:match("^Pengguna ([a-z][a-z][a-z]?%-[a-zA-Z-]+)$")
	end
	if not code then
		return
	end
	local lang = require("Module:languages").getByCode(code, nil, "allow etym")
	if not lang then
		-- If unrecognized language and called from inside, we're handling the parents and breadcrumb for a
		-- higher-level category, so at least return something.
		if not level and data.called_from_inside then
			return {
				breadcrumb = {name = code, nocap = true}, -- FIXME, scrape langname= category?
				parents = {
					{name = "Bahasa pengguna dengan kod tak sah", sort = code},
				}
			}, true
		end
				
		if not ine(data.args.langname) then
			return
		end
	end

	local params = {
		text = {},
		verb = {},
		langname = {},
		commonscat = {},
	}

	local args = require("Module:parameters").process(data.args, params)

	local langname = args.langname or lang:getCanonicalName()

	-- Insert text, appropriately script-tagged, unless already script-tagged (we check for '<span'), in which case we
	-- insert it directly. Also handle <<...>> in text and convert to bolded link to parent category.
	local function wrap(txt)
		if not txt then
			return
		end
		-- Substitute <<...>> (where ... is supposed to be the native rendering of the language) with a link to the
		-- top-level 'User CODE' category (e.g. [[:Category:User fr]] or [[:Category:User fr-CA]]) if we're in a
		-- sublevel category, or to the top-level language category (e.g. [[:Category:French language]] or
		-- [[:Category:Canadian English]]) if we're in a top-level 'User CODE' category.
		txt = txt:gsub("<<(.-)>>", function(inside)
			if level then
				return ("'''[[:Kategori:Pengguna %s|%s]]'''"):format(code, inside)
			elseif lang then
				return ("'''[[:Kategori:%s|%s]]'''"):format(lang:getCategoryName(), inside)
			else
				return ("'''%s'''"):format(inside)
			end
		end)
		if txt:find("<span") or not lang then
			return txt
		else
			return require("Module:script utilities").tag_text(txt, lang)
		end
	end

	local function insert_request_cats(parents)
		if args.text or code == "ms" or code:find("^ms%-") then
			return
		end
		local num_pages = mw.site.stats.pagesInCategory(data.category, "pages")
		local count_cat, count_sort
		if num_pages == 0 then
			count_cat = "Permintaan untuk terjemahan dalam kategori kecekapan pengguna dengan 0 pengguna"
			count_sort = "*" .. code
		elseif num_pages == 1 then
			count_cat = "Permintaan untuk terjemahan dalam kategori kecekapan pengguna dengan 1 pengguna"
			count_sort = "*" .. code
		else
			local lowernum, uppernum
			lowernum = 2
			while true do
				uppernum = lowernum * 2 - 1
				if num_pages <= uppernum then
					break
				end
				lowernum = lowernum * 2
			end
			count_cat = ("Permintaan untuk terjemahan dalam kategori kecekapan pengguna dengan %s-%s pengguna"):format(
				lowernum, uppernum)
			count_sort = "*" .. ("%0" .. #(tostring(uppernum)) .. "d"):format(num_pages)
		end

		table.insert(parents, {
			name = "Permintaan untuk terjemahan dalam kategori kecekapan pengguna mengikut bahasa",
			sort = code,
		})
		table.insert(parents, {
			name = count_cat,
			sort = count_sort,
		})
	end

	local invalid_lang_warning
	if not lang then
		invalid_lang_warning = "'''AMARAN''': Kod bahasa yang dinyatakan tidak sah di Wikikamus. Tolong pindahkan semua " ..
			"penilaian kecekapan kepada kod sah terdekat."
	end

	local parents
	if level then
		parents = {
			{name = ("Pengguna %s"):format(code), sort = level},
		}
	elseif lang then
		parents = {
			{name = "Bahasa pengguna", sort = code},
			{name = lang:getCategoryName(), sort = "Pengguna"},
		}
		if lang:hasType("etymology-only") then
			table.insert(parents, {name = lang:getNonEtymological():getCategoryName(), sort = " " .. code})
		end
	else
		parents = {
			{name = "Bahasa pengguna dengan kod tak sah", sort = code},
		}
	end
	insert_request_cats(parents)

	local topright
	if args.commonscat then
		local commonscat = require("Module:yesno")(args.commonscat, "+")
		if commonscat == "+" or commonscat == true then
			commonscat = data.category
		end
		if commonscat then
			topright = ("{{commonscat|%s}}"):format(commonscat)
		end
	end

	local namecat
	if level then
		namecat = ("[[:Kategori:Pengguna %s|%%s]]"):format(code)
	elseif lang then
		namecat = ("[[:Kategori:%s|%%s]]"):format(lang:getCategoryName())
	else
		namecat = "[[%s]]"
	end

	local additional
	if level then
		additional = ("Untuk disertakan dalam senarai ini, tambahkan <code>{{tl|Babel|%s}}</code> pada halaman pengguna anda. " ..
			"Panduan lengkap wujud di [[Wiktionary:Babel]]."):format(level == "N" and code or ("%s-%s"):format(code, level)) ..
			(invalid_lang_warning and "\n\n" .. invalid_lang_warning or "")
	else
		additional = ("Untuk disertakan dalam senarai ini, gunakan <code>{{tl|Babel}}</code> pada halaman pengguna anda. " ..
			"Panduan lengkap wujud di [[Wiktionary:Babel]].") ..
			(invalid_lang_warning and "\n\n" .. invalid_lang_warning or "")
	end
	return competency_handler {
		category = data.category,
		langtext = wrap(args.text),
		typ = "lang",
		args = args,
		obj = lang,
		code = code,
		name = langname,
		namecat = namecat,
		level = level,
		parents = parents,
		topright = topright,
		additional = invalid_lang_warning,
	}
end)


table.insert(raw_handlers, function(data)
	local code, level
	if not code then
		code, level = data.category:match("^Pengguna ([A-Z][a-z][a-z][a-z][a-z]?)%-([0-5N])$")
	end
	if not code then
		code = data.category:match("^Pengguna ([A-Z][a-z][a-z][a-z][a-z]?)$")
	end
	if not code then
		code, level = data.category:match("^Pengguna ([a-z][a-z][a-z]?%-[A-Z][a-z][a-z][a-z][a-z]?)%-([0-5N])$")
	end
	if not code then
		code = data.category:match("^Pengguna ([a-z][a-z][a-z]?%-[A-Z][a-z][a-z][a-z][a-z]?)$")
	end
	if not code then
		return
	end
	local sc = require("Module:scripts").getByCode(code)
	if not sc then
		return
	end

	local parents
	if level then
		parents = {
			{name = ("Pengguna %s"):format(code), sort = level},
		}
	else
		parents = {
			{name = "Tulisan pengguna", sort = code},
			{name = sc:getCategoryName(), sort = "Pengguna"},
		}
	end

	local namecat
	local catname = sc:getCanonicalName()
	-- Better to display 'Foo script' than just 'Foo', as so many scripts are the same as language names.
	if level then
		namecat = ("[[:Kategori:Pengguna %s|%s]]"):format(code, sc:getCategoryName())
	else
		namecat = ("[[:Kategori:%s|%s]]"):format(sc:getCategoryName(), sc:getCategoryName())
	end

	return competency_handler {
		category = data.category,
		typ = "script",
		obj = sc,
		code = code,
		name = sc:getCanonicalName(),
		namecat = namecat,
		level = level,
		parents = parents,
	}
end)


table.insert(raw_handlers, function(data)
	local code, level
	if not code then
		code, level = data.category:match("^Pengguna pengekod ([A-Za-z+-]+)-([0-5N])$")
	end
	if not code then
		code = data.category:match("^Pengguna pengekod ([A-Za-z+-]+)")
	end
	if not code or not coder_links[code] then
		return
	end

	local parents
	if level then
		parents = {
			{name = ("Pengguna pengekod %s"):format(code), sort = level},
		}
	else
		parents = {
			{name = "Pengekod pengguna", sort = code},
		}
	end

	local langdata = coder_links[code]
	if type(langdata) == "string" then
		langdata = {link = langdata}
	end

	local namecat = ("[[%s|%%s]]"):format(langdata.link)

	return competency_handler {
		category = data.category,
		typ = "coder",
		code = code,
		name = langdata.name or code,
		namecat = namecat,
		level = level,
		parents = parents,
	}
end)


return {RAW_CATEGORIES = raw_categories, RAW_HANDLERS = raw_handlers}