Jump to content

Module:letters

From Wiktionary, the free dictionary

This template is used by {{letters}} and {{letter names}}, and all the language-specific list templates that rely on them, such as the English templates {{list:Latin script letters/en}} and {{list:Latin script letter names/en}}.


local export = {}

local m_parameters = require("Module:parameters")
local m_languages = require("Module:languages")
local m_links = require("Module:links")
local m_scripts = require("Module:scripts")
local m_script_utils = require("Module:script utilities")
local data = mw.loadData("Module:letters/data")

-- Copied from Module:links/templates (function: export.l_term_t), and adapted.
local function link(term, lang, sc, face)
	-- Forward the information to full_link
	return m_links.full_link( { term = term, lang = lang, sc = sc, tr = "" }, face)
end

local function linkNoTag(term, lang)
	return m_links.language_link{ term = term, lang = lang }
end

local function tag(term, lang, sc)
	return m_script_utils.tag_text(term, lang, sc)
end

--The main function, that returns the formatted list of letters.
function export.letters(frame)
	local args = frame:getParent().args
	
	local fullpagename = mw.title.getCurrentTitle().fullText
	if fullpagename:sub(1, 16) ~= "Appendix:Letters" then
		return export.letters2(frame)
	end

	-- The variable "result" is going to contain the end text.
	local result = {}

	-- l = the language code, such as "en" for English
	local l = args[1]
	local langObject = m_languages.getByCode(l) or m_languages.err(l, 1)
	local langName = langObject:getCanonicalName()

	-- sc = the script code, such as "Latn" for Latin
	local sc = args["sc"] or nil
	local scObject = nil
	local scName = nil

	-- The first categories.
	table.insert(result, "[[Category:Letter appendices|" .. langName .. "]]")
	table.insert(result, "[[Category:" .. langName .. " appendices|Letters]]")

	-- The beginning of the result text, a link to the script appendix between parentheses.
	if sc then
		scObject = m_scripts.getByCode(sc)
		scName = scObject:getCanonicalName()

		table.insert(result, "(''[[Appendix:" .. scName .. " script|" .. scName .. " script]]'') ")
		table.insert(result, "[[Category:" .. scName .. " script appendices|" .. langName .. "]]")
	else
		table.insert(result, "(''? script'') ")
	end

	-- colonArgs and numberedArgs are going to be filled below.
	local colonArgs = {}
	local numberedArgs = {}

	-- k = key, it is the key to "v"
	-- v = value, each argument given in Template:letters
	for k, v in pairs(args) do

		-- It does not contain "sc=", which is a named argument.
		-- The argument "1" is not added in numberedArgs. It is the language code.
		if mw.ustring.find(v, ":", 1, true) then
			table.insert(colonArgs, args[k])
		elseif tonumber(k) ~= nil and k ~= 1 then
			table.insert(numberedArgs, args[k])
		end
	end

	-- kk = key, it is the key to "vv"
	-- vv = value, each numbered argument, like "Aa", "Bb", "Cc"
	for kk, vv in pairs(numberedArgs) do
		if kk ~= 1 then
			table.insert(result, ", ")
		end

		-- currentLetter = a single value like "Aa"
		local currentLetter = numberedArgs[kk]

		-- About "letterCases":
		-- If currentLetter contains "[" (as in: [[A]][[a]]), letterCases is a table with only the currentLetter.
		-- Otherwise, letterCases is a table with each letter, unformatted.
		local letterCases = {}
		if mw.ustring.find(currentLetter, "[", 1, true) or mw.ustring.find(currentLetter, "<", 1, true) then
			letterCases[1] = currentLetter
		else
			for i=1, mw.ustring.len(currentLetter) do
				letterCases[i] = mw.ustring.sub(currentLetter, i, i)
			end
		end

		-- kkk = key, it is the key to "vvv"
		-- vvv = value, each letter in letterCases
		for kkk, vvv in pairs(letterCases) do

			-- Formats with "link" each letter in letterCases.
			-- The result is added in the "result" text.
			table.insert(result, link(letterCases[kkk], langObject, scObject))

		end

		-- Adds the letter category, like [[Category:Dd]].
		table.insert(result, "[[Category:" .. currentLetter .. "|" .. langName .. "]]")
	end

	-- kkkk = key, it is the key to "vvvv"
	-- vvvv = value, it is the value, as in "Aa:⠁"
	for kkkk, vvvv in pairs(colonArgs) do

		if kkkk ~= 1 then
			table.insert(result, ", ")
		end

		local equalSignSplit = mw.text.split (vvvv, ": ", true)
		local partOne = equalSignSplit[1]
		local partTwo = equalSignSplit[2]

		-- The result is added in the "result" text.
		table.insert(result, "'''" .. partOne .. "'''" .. ": " .. link(partTwo, langObject, scObject))

		-- Adds the letter category, like [[Category:Dd]].
		table.insert(result, "[[Category:" .. partOne .. ": " .. partTwo .. "|" .. langName .. "]]")

	end

	return table.concat(result)
end

--Returns the list of letter names.
function export.letterNames(frame)
	local namespace = mw.title.getCurrentTitle().nsText
	if namespace ~= "Appendix" then
		return export.letterNames2(frame)
	end
	
	local args = frame:getParent().args
	local colonArgs = {}

	-- The variable "result" is going to contain the end text.
	local result = {}

	-- sc = the script code, such as "Latn" for Latin
	local sc = args["sc"] or nil

	-- l = the language code, such as "en" for English
	local l = args[1]
	local langObject = m_languages.getByCode(l) or m_languages.err(l, 1)

	for k, v in pairs(args) do
		if mw.ustring.find(v, ":", 1, true) then
			table.insert(colonArgs, args[k])
		end
	end

	-- k = key, it is the key to "v"
	-- v = value, it is the value, as in "Bb: bee"
	for k, v in pairs(colonArgs) do

		if k ~= 1 then
			table.insert(result, ", ")
		end

		local equalSignSplit = mw.text.split (v, ": ", true)
		local partOne = equalSignSplit[1]
		local partTwo = equalSignSplit[2]

		-- The result is added in the "result" text.
		table.insert(result, "'''" .. partOne .. "'''" .. ": " .. link(partTwo, langObject, scObject))

	end

	return table.concat(result)
end

local function qualifier(content)
	if content then
		return 
		'<span class="ib-brac qualifier-brac">(</span>'
		.. '<span class="ib-content qualifier-content">'
		.. content .. '</span>'
		.. '<span class="ib-brac qualifier-brac">)</span> '
	end
end
	

function export.letters2(frame)
	local output, list, categories = {}, {}, {}
	
	local namespace = mw.title.getCurrentTitle().nsText
	
	local params = {
		[1] = { list = true },
		["native name"] = {},
		["lang"] = { required = true },
		["sc"] = {},
		["qual"] = {},
	}
	
	local args = m_parameters.process(frame:getParent().args, params)
	
	local lang = m_languages.getByCode(args.lang) or m_languages.err(args.lang, "lang")
	local langName = lang:getCanonicalName()
	local sc = m_scripts.getByCode(args.sc) or lang:findBestScript(text) or error("Script could not be identified.")
	local scName = sc:getCanonicalName()
	local scCode = sc:getCode()
	local data = data.list[args.lang] and data.list[args.lang][args.sc] and data.list[args.lang][args.sc] or data
	
	local qualifierContent = args.qual or '[[Appendix:' .. scName .. ' script|' .. scName .. '-script]] letters'
	table.insert(
		output,
		qualifier(qualifierContent)
		)
	
	local native_name = data.native_name or args["native name"]
	if native_name then
		native_name = link(native_name, lang, sc, "bold")
		table.insert(output, native_name .. "; ")
	end
	
	if data.letters then
		for i,v in ipairs(data.letters) do
			table.insert(list, link(v[1], lang, sc) .. "&nbsp;" .. link(v[2], lang, sc))
		end
	else
		for i, letterParameter in ipairs(args[1]) do
			if scCode == "Latn" then
				--[[	If script is Latin, no transliteration is needed, so language span
						is applied to whole list, and individual list items are linked and not language-tagged. ]]
				local open_par, uppercase, lowercase, close_par
				
				if mw.ustring.find(letterParameter, "/") then
					open_par, uppercase, lowercase, close_par = mw.ustring.match(letterParameter, "(%(?)([^/]+)/([^%)]+)(%)?)")
				elseif mw.ustring.find(letterParameter, "%u.*%l") then
					open_par, uppercase, lowercase, close_par = mw.ustring.match(letterParameter, "^(%(?)(%u)(%l)(%)?)$")
				else
					open_par, letters, close_par = mw.ustring.match(letterParameter, "^(%(?)([^%(%)]+)(%)?)$")
				end
				
				if open_par and close_par then
					if uppercase and lowercase then	
						uppercase, lowercase = linkNoTag(uppercase, lang, sc), linkNoTag(lowercase, lang, sc)
						
						table.insert(list, open_par .. uppercase .. "&nbsp;" .. lowercase .. close_par)
					elseif letters then
						letters = linkNoTag(letters, lang, sc)
						
						table.insert(list, open_par .. letters .. close_par)
					end
				else
					letterParameter = linkNoTag(letterParameter, lang, sc)
					
					table.insert(list, letterParameter)
				end
			else
				--[[	If script is non-Latin, add transliteration to
						and tag each item on the list individually.		]]
				local letters = {}
				local uppercase, lowercase
				local open_par, letterParameter, close_par = mw.ustring.match(letterParameter, "(%(?%s*)([^%)]+)(%s*%)?)")
				
				if mw.ustring.find(letterParameter, "/") then
					uppercase, lowercase = mw.ustring.match(letterParameter, "([^/]+)/(.+)")
					uppercase = "[[" .. uppercase .. "]]"
					lowercase = "[[" .. lowercase .. "]]"
				elseif mw.ustring.find(letterParameter, "^%*.") then
					letters = { "[[" .. mw.ustring.gsub(letterParameter, "^*", "") .. "]]" }
				else
					for letter in mw.ustring.gmatch(letterParameter, ".") do
						 table.insert(letters, "[[" .. letter .. "]]")
					end
				end
				
				if uppercase and lowercase then	
					letters = open_par .. link(uppercase .. "&nbsp;" .. lowercase, lang, sc) .. close_par
				elseif letters then
					letters = table.concat(letters, "&nbsp;")
					letters = open_par .. link(letters, lang, sc) .. close_par
				end
				
				table.insert(list, letters)
			end
		end
	end
	
	if namespace == "Template" then
		table.insert(categories, "[[Category:" .. langName .. " list templates|letters]]")
		table.insert(categories, "[[Category:Character list templates|" .. langName .. "]]")
	end

	list = table.concat(list, ", ")
	list = mw.ustring.gsub(list, "%), %(", ", ")
	list = mw.ustring.gsub(list, ", %(", " (")
	
	--[[	Add language tagging to whole list for Latin script,
			because individual letters were not tagged.			]]
	if scCode == "Latn" then
		list = tag(list, lang, sc)
	end
	
	table.insert(output, list)
	
	return table.concat(output) .. table.concat(categories)
end

function export.letterNames2(frame)
	local output, list = {}, {}
	
	local namespace = mw.title.getCurrentTitle().nsText
	
	local params = {
		[1] = { list = true, required = true },
		["native name"] = {},
		["lang"] = { required = true },
		["sc"] = {},
		["qual"] = {},
	}
	
	local output = {}
	
	local args = m_parameters.process(frame:getParent().args, params)
	
	local lang = m_languages.getByCode(args.lang) or m_languages.err(args.lang, "lang")
	local sc = args.sc or "Latn"
	sc = m_scripts.getByCode(sc)
	
	local qualifierContent = args.qual or sc:getCanonicalName() .. "-script letter names"
	table.insert(
		output,
		qualifier(qualifierContent)
		)
	
	local native_name =  args["native name"]
	if native_name then
		native_name = link(native_name, lang, sc, "bold")
		table.insert(output, native_name .. "; ")
	end
	
	if sc:getCode() == "Latn" then
		local alternative_names
		for i, letter_name in ipairs(args[1]) do
			alternative_names = mw.text.split(letter_name, "%s*/%s*")
			
			local letterNames = {}
			for i, letter_name in ipairs(alternative_names) do
				table.insert(letterNames, link(letter_name, lang, sc) )
				if alternative_names[i + 1] then
					table.insert(letterNames, " / ")
				end
			end
			
			table.insert(list, table.concat(letterNames))
		end
	end
	
	list = table.concat(list, ", ")
	
	table.insert(output, list)
	
	return table.concat(output)
end

function export.definition(frame)
	local parameters = {
		[1] = { list = true },
		["alphabet name"] = {},
		["name"] = {},
		["trans"] = {},
		[""] = {},
	}
	
	local args = m_parameters.process(frame:getParent().args, parameters)
	
	local types = {
		letter = {
			text = table.concat {
				'<span class="use-with-mention">',
				'The {{{ordinal}}} [[letter]] of the {{{canonical name}}} [[alphabet]]{{{alphabet name}}}, ',
				'called {{{letter names list}}} ',
				'and written in the {{{Latin script}}}.'
				},
			},
		name = {
			text = table.concat {
				'<span class="use-with-mention">',
				'The name of the {{{Latin-script}}} letter ',
				'{{{uppercase}}}{{{separator}}}{{{lowercase}}}.</span>',
				},
			},
		diacritic = {},
		ordinal = {},
		syllable = {},
	}
	
	local lang = m_languages.getByCode(args[1][1]) or m_languages.err(args[1][1], 1)
	local type = args[1][2]
	
	local alphabet_name = args["alphabet name"]
	if alphabet_name then
		alphabet_name = " (" .. alphabet_name .. ")"
	else
		alphabet_name = ""
	end
	
	local data
	if type then
		if types[type] then
			data = types[type]
		else
			error('The type of definition "' .. tostring(type) .. '" is not recognized.')
		end
	else
		error("Select a type of definition using parameter 2: letter, letter name, diacritic, ordinal, or syllable.")
	end
	
	local text = {data.text}
	
	if #text > 0 then
		text.add = function(self, code, item)
			if self and self[1] then
				self[1] = mw.ustring.gsub(self[1], "{{{" .. code .. "}}}", item)
			end
		end
		
		text:add("canonical name", lang:getCanonicalName() )
		text:add("Latin-script", "[[Appendix:Latin script|Latin-script]]")
		text:add("alphabet name", alphabet_name)
	else
		error('The type "' .. type .. '" does not have text defined.')
	end
	
	return text[1]
end

return export