Module:MediaWiki message helper


Module:mh-IPA
Module:temp
Category:List of Proto-Indo-European roots
Template:quote book (replace space with hyphen)
Template:lexico (add prefix, search case-insensitively)
Category:Abkhazian language
Category:Qashqa'i language
Template:1911 (add prefix)
Template:R:Newman & Weitlaner (find template with year and lowercase letter)
Template:Meillet (find template with range of years)
Template:R:Meillet
Template:R:xcl:Meillet
Template:Asatryan (find template with year slash year)
Template:R:Asatryan
Template:Lane
Template:R:Lane
Template:R:Diakonoff (add language code and space and year)
Template:R:afa-pro:Diakonoff (add space and year)
Template:R:Hashemi (add language code and colon and year)
Template:R:ae:Hashemi (add colon and year)
Category:en
Category:Abkhaz
Category:Dendi (canonical name category should be first)
Category:sit
Category:Nastaliq script
Category:Nastaliq

local m_str_utils = require("Module:string utilities")

local pattern_escape = m_str_utils.pattern_escape
local php_trim = m_str_utils.php_trim
local ufind = m_str_utils.find
local ugsub = m_str_utils.gsub
local ulower = m_str_utils.lower
local uupper = m_str_utils.upper

local export = {}

local function print_suggestions(suggestions)
	if #suggestions == 0 then
		return ""
	else
		local prefix = "* Did you mean "
		local suffix
		if #suggestions > 1 then
			prefix = prefix .. " any of these?\n"
			suggestions = suggestions:map(function(link) return "** " .. link end)
			suffix = ""
		else
			suffix = "?"
		end
		return prefix .. suggestions:concat "\n" .. suffix
	end
end

-- For [[MediaWiki:Noarticletext]] on uncreated category pages.
function export.category_suggestions(frame)
	local output = require("Module:array")()
	
	local function make_suggestion(title, suffix)
		output:insert("'''[[:Category:" .. title .. "]]'''" .. (suffix or ""))
	end
	
	local title = frame.args.title and mw.title.new(frame.args.title).text or mw.title.getCurrentTitle().text
	title = ugsub(title, "^.", uupper)
	
	local function check_for_page_from_function(func)
		local suggestion = func(title)
		if mw.title.new("Category:" .. suggestion).exists then
			make_suggestion(suggestion)
			return true
		end
		return false
	end
	
	local function check_for_page_with_suffix(suffix)
		return check_for_page_from_function(function(title)
			return title .. " " .. suffix
		end)
	end
	
	local function check_for_page_with_prefix_removed(prefix)
		return check_for_page_from_function(function(title)
			return title:gsub(pattern_escape(prefix), "")
		end)
	end
	
	check_for_page_with_prefix_removed("List of ")
	check_for_page_with_prefix_removed("list of ")
	
	local has_language_category = check_for_page_with_suffix("language")
	check_for_page_with_suffix("Language")
	check_for_page_with_suffix("languages")
	local has_script_category = check_for_page_with_suffix("script")
	
	local function check_other_names_of_languages(language_name)
		for code, data in pairs(require("Module:languages/data/all")) do
			local function check_name_list(list)
				if list then
					for _, name in ipairs(list) do
						-- The aliases and varieties are recursive,
						-- with subtables that themselves contain names.
						if type(name) == "table" then
							check_name_list(name)
						else
							if name == language_name then
								local object = require("Module:languages").makeObject(code, data)
								make_suggestion(object:getCategoryName())
							end
						end
					end
				end
			end
			check_name_list(data.otherNames)
			check_name_list(data.aliases)
			check_name_list(data.varieties)
		end
	end
	
	-- If title looks like a language category, then check if the language name
	-- in it is a valid canonical name, or one of the otherNames for some
	-- language.
	-- If the title looks like a language code, check for a language or a script
	-- with that code.
	local function check_language_name(language_name, is_language_category, has_language_category)
		local ret = false
		if not has_language_category then
			if require("Module:languages/canonical names")[language_name] then
				if not is_language_category then
					make_suggestion(language_name .. " language")
				else
					output:insert("* '''" .. language_name .. "''' is a valid Wiktionary language name.")
				end
				ret = true
			end
		end
		
		-- Some otherNames are the canonical name of another language.
		check_other_names_of_languages(language_name)
		
		return ret
	end
	local language_name = title:match "^(.+) language$" or title:match "^(.+ Language)$"
	check_language_name(language_name or title, language_name ~= nil, has_language_category)
	
	-- Most languages (7965/8085 by last count) have uppercase letters at
	-- beginning of the name and after whitespace and punctuation characters,
	-- and lowercase everywhere else. Exceptions include languages
	-- with apostrophes, such as Yup'ik, and languages with tone letters,
	-- such as ǃXóõ.
	local fixed_capitalization = ugsub(ulower(language_name or title), "%f[^%z%s%p]%a", uupper)
	if fixed_capitalization ~= (language_name or title) then
		check_language_name(fixed_capitalization)
	end
	
	if title:find "^[%a-]+$" then
		local function check_for_valid_code(code, ...)
			for _, module_name in ipairs { ... } do
				local object = require("Module:" .. module_name).getByCode(code)
				if object then
					make_suggestion(object:getCategoryName(),
						" (code <code>" .. code .. "</code>)")
				end
			end
		end
		local code = title:lower()
		check_for_valid_code(code, "languages", "etymology languages", "scripts", "families")
		check_for_valid_code(code .. "-pro", "languages", "etymology languages")
	end
	
	local function check_script_name(script_name, is_script_category, has_script_category)
		if not has_script_category then
			local object = require("Module:scripts").getByCanonicalName(script_name)
			if object then
				if is_script_category then
					output:insert("* " .. script_name .. " is a valid Wiktionary script name.")
				else
					make_suggestion(object:getCategoryName())
				end
			end
		end
		for code, data in pairs(require("Module:scripts/data")) do
			local function check_other_names_of_script(list)
				if list then
					for _, name in ipairs(list) do
						if type(name) == "table" then
							check_other_names_of_script(name)
						elseif script_name == name then
							local object = require("Module:scripts").makeObject(code, data)
							make_suggestion(object:getCategoryName())
						end
					end
				end
			end
			check_other_names_of_script(data.otherNames)
			check_other_names_of_script(data.varieties)
			check_other_names_of_script(data.aliases)
		end
	end
	
	local script_name = title:match "^(.+) script$"
	check_script_name(script_name or title, script_name ~= nil, has_script_category)
	
	return print_suggestions(output)
end

function export.template_suggestions(frame)
	local title = frame.args.title and mw.title.new(frame.args.title).text
		or mw.title.getCurrentTitle().text
	
	local output = require("Module:array")()
	
	local function make_suggestion(title, suffix)
		output:insert("'''[[:Template:"
			.. title .. "]]'''" .. (suffix or ""))
	end
	
	local function check_for_page_with_prefix(prefix)
		local suggestion = prefix .. title
		if mw.title.new("Template:" .. suggestion).exists then
			make_suggestion(suggestion)
			return true
		end
		return false
	end
	
	if title:find " " then
		local with_hyphen = title:gsub(" ", "-")
		if mw.title.new("Template:" .. with_hyphen).exists then
			make_suggestion(with_hyphen)
		end
	end
	
	local prefixes = frame.args.prefixes
	if prefixes then
		local prefix_separator = frame.args.prefix_separator or ","
		for prefix in prefixes:gmatch("[^" .. prefix_separator .. "]+") do
			check_for_page_with_prefix(prefix)
		end
	end
	
	local prefix, rest = title:match "^([^: ]+) ?:(.+)$"
	if prefix then
		prefix = prefix:upper()
	else
		prefix, rest = "", title
	end
	
	if prefix == "" or prefix == "R" or prefix == "RQ" then
		local templates = require("Module:MediaWiki message helper/R: and RQ: templates")
		local rest_pattern = pattern_escape(rest)
			:gsub(
				"%l",
				function(letter)
					return "[" .. letter:upper() .. letter:lower() .. "]"
				end)
		
		for match in templates:gmatch("%f[^%z\n][Rr][Qq]? ?:[a-z-]*[-:]?"
				.. rest_pattern
				.. "[ :]?%d?%d?%d?%d?[/-]?%d?%d?%d?%d?%l?%f[%z\n]") do
			make_suggestion(match)
		end
	end
	
	return print_suggestions(output)
end

function export.module_suggestions(frame)
	local title = frame.args.title and mw.title.new(frame.args.title).text
		or mw.title.getCurrentTitle().text
	
	local output = require("Module:array")()
	
	local function make_suggestion(title)
		output:insert("'''[[:Module:"
			.. title .. "]]'''")
	end
	
	local pronunciation_suffixes = require("Module:array"){"IPA", "pronunc", "pronunciation"}
	
	if pronunciation_suffixes:some(function(suffix) return title:find("%-" .. suffix .. "$") end) then
		for _, suggestion in ipairs(pronunciation_suffixes:map(function (suffix) return title:gsub("%-%w+$", "-" .. suffix) end)) do
			if mw.title.new("Module:" .. suggestion).exists then
				make_suggestion(suggestion)
			end
		end
	end
	
	-- Look for the modules actually invoked by the template with the same name
	-- as the module.
	local template_title = mw.title.new(title, "Template")
	local template_text = template_title:getContent()
	if template_text then
		for template in require("Module:template parser").find_templates(template_text) do
			if template:get_name() == "#INVOKE:" then
				local args = template:get_arguments()
				if args[2] then -- args[2] is the function name, so #INVOKE: will throw an error if not present
					make_suggestion(php_trim(args[1])) -- args[1] is the module name
				end
			end
		end
	end
	
	return print_suggestions(output)
end

function export.is_data_module_not_documentation(frame)
	local page = frame.args.title and mw.title.new(frame.args.title)
		or mw.title.getCurrentTitle()
	if page.namespace == 828 and require("Module:pages").pagetype(page) ~= "module documentation page" then
		return ufind(page.text, "^" .. (frame.args[1] or "") .. "$")
	end
end

return export