Pergi ke kandungan

Modul:pendokumenan/translit-like

Daripada Wikikamus


local export = {}

local m_module_categorization = require("Module:module categorization")
local m_table = require("Module:table")
local title_exists = require("Module:title/exists")
local languages_module = "Module:languages"
local scripts_module = "Module:scripts"
local debug_track_module = "Module:debug/track"
local insert = table.insert
local concat = table.concat

local operations = {
	translit = {
		expected_suffix = "translit",
		verb = "transliterate",
		cap_verb_3s = "Transliterates",
		action_noun = "transliteration",
		cat_action_noun = "Transliteration",
		template = "xlit",
		funcname = "tr",
		languages_func = "transliterate",
		by_module = "byTranslitModule",
	},
	["strip diacritics"] = {
		expected_suffix = "stripdiacritics",
		verb = "generate diacritic-stripped text for",
		cap_verb_3s = "Strips diacritics from",
		action_noun = "diacritic stripping",
		cat_action_noun = "Diacritic-stripping",
		template = "strip diacritics",
		funcname = "stripDiacritics",
		languages_func = "stripDiacritics",
		by_module = "byStripDiacriticsModule",
	},
	sortkey = {
		expected_suffix = "sortkey",
		verb = "sort",
		cap_verb_3s = "Generates a sortkey for",
		action_noun = "sort",
		cat_action_noun = "Sortkey-generating",
		template = "sortkey",
		funcname = "makeSortKey",
		languages_func = "makeSortKey",
		by_module = "bySortkeyModule",
	},
}

local function get_operation_data(operation)
	if not operations[operation] then
		error(("Internal error: Unrecognized operation '%s' in [[Module:documentation/translit-like]]"):format(operation))
	end
	return operations[operation]
end

local function get_by_code(code)
	return require(languages_module).getByCode(code, nil, true, true) or require(scripts_module).getByCode(code)
end

local function get_code_from_title_without_namespace(title_without_namespace, expected_suffix)
	local prefix = title_without_namespace:match("^(.+)%-" .. expected_suffix .. "%f[/%z]")
	if not prefix then
		error("Base segment of title should end in -" .. expected_suffix .. ": " .. title_without_namespace)
	end
	local code = prefix
	local lang_or_family_or_script = get_by_code(code)
	local secondary_script, tertiary_script
	if not lang_or_family_or_script then
		-- Accommodate modules with multiple codes in the title.
		-- The first code should be used.
		-- Right now it strips segments from the end until it finds a match:
		-- Module:Deva-Beng-translit -> Deva-Beng -> Deva
		-- Module:pra-Deva-translit -> pra-Deva -> pra
		-- Module:Deva-mnc-Mong-translit -> Deva-mnc-Mong -> Deva-mnc -> Deva
		while true do
			local new_code, secondary_script_code = code:match("^(.+)%-([^%-]+)$")
			if new_code then
				code = new_code
			else
				break
			end
			lang_or_family_or_script = get_by_code(new_code)
			if secondary_script_code then
				if secondary_script then
					tertiary_script = secondary_script
				end
				secondary_script = get_by_code(secondary_script_code)
			end
			if lang_or_family_or_script then
				break
			end
		end
	end

	return code, lang_or_family_or_script, secondary_script, tertiary_script
end

local function generate_documentation(data)
	local operation, opdata, code, lang_or_family_or_script, secondary_script, tertiary_script, explanation,
		title_without_namespace =
			data.operation, data.opdata, data.code, data.lang_or_family_or_script, data.secondary_script,
			data.tertiary_script, data.explanation, data.title_without_namespace
	local verb, cap_verb_3s, action_noun, cat_action_noun, template, funcname, languages_func, by_module =
		opdata.verb, opdata.cap_verb_3s, opdata.action_noun, opdata.cat_action_noun, opdata.template, opdata.funcname,
		opdata.languages_func, opdata.by_module

	if not lang_or_family_or_script then
		return "Language code in page name (<code>" .. code .. "</code>) not recognized."
	end

	local category_link = lang_or_family_or_script:makeCategoryLink()
	local script_lang = lang_or_family_or_script:hasType("language") and lang_or_family_or_script or nil
	local secondary_script_category_link = secondary_script and secondary_script:makeCategoryLink(script_lang) or nil
	local tertiary_script_category_link = tertiary_script and tertiary_script:makeCategoryLink(script_lang) or nil

	local action_input
	if lang_or_family_or_script:hasType("script") then
		if secondary_script_category_link then
			action_input = "text between the " .. category_link .. " and the " ..
				secondary_script_category_link
		else
			action_input = "text in the " .. category_link
		end
	else
		if lang_or_family_or_script:hasType("family") then
			action_input = "text in one of the " .. category_link
		else
			action_input = category_link .. " text"
		end
		if tertiary_script_category_link then
			action_input = action_input .. " between the " .. secondary_script_category_link .. " and the " ..
				tertiary_script_category_link
		elseif secondary_script_category_link then
			action_input = action_input .. " in the " .. secondary_script_category_link
		end
	end

	local tr_page = operation == "translit" and "WT:" .. mw.ustring.upper(code) .. " TR" or nil

	local parts = {}
	local function ins(txt)
		insert(parts, txt)
	end

	ins("This module will " .. verb .. " " .. action_input .. (explanation and " " .. explanation or ""))
	if tr_page and title_exists(tr_page) then
		ins(" per [[" .. tr_page .. "]]")
	end
	ins(". ")

	title_without_namespace = title_without_namespace:gsub("/documentation$", "")

	local language_objects = require("Module:languages/" .. by_module)(title_without_namespace)

	local categories = {}
	if language_objects[1] then
		local agreement = language_objects[2] and "s" or ""
		insert(categories, "[[Category:" .. cat_action_noun .. " modules used by " ..
			#language_objects .. " language" .. agreement .. "]]")
	end

	local function insert_script_cat(script)
		-- If language objects available, use the appropriate script name(s). Otherwise,
		-- fall back to the default script name.
		if language_objects[1] then
			for _, langobj in ipairs(language_objects) do
				m_table.insertIfNot(categories,
					"[[Category:" .. script:getCategoryName(nil, langobj) .. "]]")
			end
		else
			insert(categories, "[[Category:" .. script:getCategoryName() .. "]]")
		end
	end
	if lang_or_family_or_script:hasType("script") then
		insert_script_cat(lang_or_family_or_script)
	end
	if secondary_script then
		insert_script_cat(secondary_script)
	end
	if tertiary_script then
		insert_script_cat(tertiary_script)
	end

	if not title_exists("Module:" .. title_without_namespace .. "/testcases") then
		insert(categories, "[[Category:" .. cat_action_noun .. " modules without a testcases subpage]]")
	end

	-- Filter out the language code in the module name, since we list that language first.
	local new_language_objects = {}
	local code_in_pagename_in_list = false
	for _, langobj in ipairs(language_objects) do
		local result = langobj:getCode() ~= code
		code_in_pagename_in_list = code_in_pagename_in_list or result
		if result then
			insert(new_language_objects, langobj)
		end
	end
	language_objects = new_language_objects

	if language_objects[1] then
		table.sort(language_objects, function(lang1, lang2)
			return lang1:getCode() < lang2:getCode()
		end)
		local lang_category_links = {}
		for _, langobj in ipairs(language_objects) do
			insert(lang_category_links, langobj:makeCategoryLink())
		end
		local langs = m_table.serialCommaJoin(lang_category_links)
		ins("It is " .. (code_in_pagename_in_list and "also" or "") ..
			" used to " .. verb .. " " .. langs .. ".")
	end

	ins(([=[

The module should preferably not be called directly from templates or other modules.
To use it from a template, use <code>{{[[Template:%s|%s]]}}</code>.
Within a module, use [[Module:languages#Language:%s]].

For testcases, see [[Module:]=]):format(template, template, languages_func) ..
	title_without_namespace .. ([=[/testcases]].

== Functions ==
; <code>%s(text, lang, sc)</code>
: %s a given piece of <code>text</code> written in the script specified by the code <code>sc</code>, and language specified by the code <code>lang</code>.
: When %s fails, returns <code>nil</code>.]=]):format(funcname, cap_verb_3s, action_noun)
	)
	ins(concat(categories))
	local langlist_codes = {}
	insert(langlist_codes, code)
	for _, langobj in ipairs(language_objects) do
		insert(langlist_codes, langobj:getCode())
	end
	ins(m_module_categorization.categorize_module {
		pagename = title_without_namespace,
		langlist = concat(langlist_codes, ","),
	})
	return concat(parts)
end

function export.documentation(data)
	local operation, code, lang_or_family_or_script, secondary_script, tertiary_script, title_without_namespace,
		explanation =
			data.operation, data.code, data.lang_or_family_or_script, data.secondary_script, data.tertiary_script,
			data.title_without_namespace, data.explanation
	local opdata = get_operation_data(operation)
	if not code then
		code, lang_or_family_or_script, secondary_script, tertiary_script =
			get_code_from_title_without_namespace(title_without_namespace, opdata.expected_suffix)
	end
	local docdata = {
		operation = operation,
		opdata = opdata,
		code = code,
		lang_or_family_or_script = lang_or_family_or_script,
		secondary_script = secondary_script,
		tertiary_script = tertiary_script,
		explanation = explanation,
		title_without_namespace = title_without_namespace,
	}
	return generate_documentation(docdata)
end

function export.documentation_template(frame)
	local iparams = frame.args
	local operation = iparams[1]
	local opdata = get_operation_data(operation)
	-- Parameters to {{OPERATION module documentation}}:
	-- |code|description
	-- Ignore code because we get it from the page name.
	local pagename = mw.title.getCurrentTitle().text -- DO NOT replace with mw.loadData("Module:headword/data").pagename as we need the root portion
	local args = frame:getParent().args
	if args[1] and get_code_from_title_without_namespace(pagename, opdata.expected_suffix) ~= args[1] then
		-- [[Special:WhatLinksHere/Wiktionary:Tracking/OPERATION/input different from title]]
		require(debug_track_module)(operation .. "/input different from title")
	end
	if args[1] then
		return export.documentation {
			operation = operation,
			code = args[1],
			lang_or_family_or_script = get_by_code(args[1]),
			secondary_script = args.sc and get_by_code(args.sc) or nil,
			tertiary_script = args.sc2 and get_by_code(args.sc2) or nil,
			explanation = args[2],
			title_without_namespace = pagename,
		}
	else
		return export.documentation {
			operation = operation,
			explanation = args[2],
			title_without_namespace = pagename,
		}
	end
end

return export