Pumunta sa nilalaman

Module:typing-aids

Mula Wiksiyonaryo


local export = {}

local reorderDiacritics = require("Module:grc-utilities").reorderDiacritics
local formatLink = require("Module:template link").format_link
local m_data = mw.loadData("Module:typing-aids/data")
local m_data_ae = mw.loadData("Module:typing-aids/data/ae")
local m_data_ar = mw.loadData("Module:typing-aids/data/ar")
local m_data_grc = mw.loadData("Module:typing-aids/data/grc")
local m_data_hit = mw.loadData("Module:typing-aids/data/hit")
local m_data_hy = mw.loadData("Module:typing-aids/data/hy")
local m_data_sa = mw.loadData("Module:typing-aids/data/sa")
local m_data_got = mw.loadData("Module:typing-aids/data/got")

--[=[	The first string is the subpage of [[Module:typing-aids/data]] that contains the language's replacements;
		the second is the index in the exported table of that module that contains
		the language's replacements.								]=]
data_modules = {
	["ae"] = { "ae", "ae", },
	["ae-tr"] = { "ae", "ae-tr", },
	["ar"] = { "ar" },
	["hit"] = { "hit", "hit" },
	["hit-tr"] = { "hit", "hit-tr" },
	["hy"] = { "hy", "hy", },
	["hy-tr"] = { "hy", "hy-tr", },
	["sa"] = { "sa", "sa" },
	["sa-tr"] = { "sa", "sa-tr" },
	["got"] = { "got", "got" },
	["got-tr"] = { "got", "got-tr" },
	["grc"] = { "grc" },
--	[""] = { "" },
}

local U = mw.ustring.char
local gsub = mw.ustring.gsub
local find = mw.ustring.find
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local sub = mw.ustring.sub

local acute = U(0x0301)
local macron = U(0x0304)

local function clone_args(frame)
	local args = frame.getParent and frame:getParent().args or frame
	local newargs = {}
	for k, v in pairs(args) do
		if v == "" then v = nil end
		if v then
			newargs[k] = v
		end
	end
	return newargs
end
			
local function tag(text, lang)
	if  lang and not find(lang, "%-tr$") then
		return '<span lang="' .. lang .. '">' .. text .. '</span>'
	else
		return text
	end
end

local acute_decomposer = {
	["á"] = "a" .. acute,
	["é"] = "e" .. acute,
	["í"] = "i" .. acute,
	["ó"] = "o" .. acute,
	["ú"] = "u" .. acute,
	["ý"] = "y" .. acute,
	["ḗ"] = "ē" .. acute,
	["ṓ"] = "ō" .. acute,
	["Á"] = "A" .. acute,
	["É"] = "E" .. acute,
	["Í"] = "I" .. acute,
	["Ó"] = "O" .. acute,
	["Ú"] = "U" .. acute,
	["Ý"] = "Y" .. acute,
	["Ḗ"] = "Ē" .. acute,
	["Ṓ"] = "Ō" .. acute,
}

-- compose Latin text, then decompose into sequences of letter and combining
-- accent, either partly or completely depending on the language.
local function compose_decompose(text, lang)
	text = mw.ustring.toNFC(text)
	if lang == "sa" or lang == "hy" or lang == "xcl" then
		text = gsub(text, ".", acute_decomposer)
	else
		text = mw.ustring.toNFD(text)
	end
	return text
end

local function _replace(text, replacements)
	for shortcut, symbol in pairs(replacements) do
		if type(symbol) == "table" then
			local before =
				symbol.before and { "("..symbol.before..")", "%1" }
				or { "", "" }
			local after =
				symbol.after and { "("..symbol.after..")", symbol.before and  "%2" or "%1" }
				or { "", "" }
			
			text = gsub(text, before[1]..shortcut..after[1], before[2]..symbol[1]..after[2])
		elseif type(symbol) == "string" then
			text = gsub(text, shortcut, symbol)
		end
	end
	text = mw.text.trim(text)
	return text
end

local function interpretShortcuts(text, origlang)
	if not text or type(text) ~= "string" then
		return nil
	end

	local lang = origlang
	if lang == "xcl" then lang = "hy" end
	local module_name = data_modules[lang]
	local data_module
	if module_name then
		data_module = mw.loadData("Module:typing-aids/data/" .. module_name[1])
	else
		data_module = mw.loadData("Module:typing-aids/data")
	end
	
	local replacements
	if not module_name then
		if lang then
			replacements = data_module[lang]
		else
			replacements = data_module.all
		end
	elseif module_name[2] then
		replacements = data_module[module_name[2]]
	else
		replacements = data_module
	end
	
	if not replacements then
		error("The language code \"" .. tostring(origlang) .. "\" does not have a set of replacements in Module:typing-aids/data or its submodules.")
	end

	text = compose_decompose(text, lang)
	
	if lang == "ae" or lang == "sa" or lang == "got" or lang == "hy" or lang == "xcl" then
		local transliterationTable
		if lang == "sa" then
			transliterationTable = m_data_sa["sa-tr"]
		elseif lang == "ae" then
			transliterationTable = m_data_ae["ae-tr"]
		elseif lang == "got" then
			transliterationTable = m_data_got["got-tr"]
		elseif lang == "hy" or lang == "xcl" then
			transliterationTable = m_data_hy["hy-tr"]
		end
		
		for ordering, table in ipairs(transliterationTable) do
			for symbol, symbolWithDiacritic in pairs(table) do
				text = gsub(text, symbol, symbolWithDiacritic)
			end
		end
		
		text = compose_decompose(text, lang)
		
		for i, replacementsTable in ipairs(replacements) do
			text = _replace(text, replacementsTable)
		end
	else
		if replacements[1] then
			for i, replacementsTable in ipairs(replacements) do
				text = _replace(text, replacementsTable)
			end
		else
			text = _replace(text, replacements)
		end
		
		if lang == "grc" then
			text = reorderDiacritics(text)
		end
	end
	
	return text
end

local function intoHittite(text)
	local replacements = m_data_hit["hit"]
	
	for k, v in pairs(replacements.pre) do
		text = gsub(text, k, v)
	end
	
	local output = {}
	-- Find groups of characters that aren't hyphens or whitespace.
	for symbol in text:gmatch("([^%-%s]+)") do
		table.insert(output, replacements[symbol] or symbol)
	end
	
	return table.concat(output)
end

local function addParameter(list, args, key, content)
	if not content then content = args[key] end
	args[key] = nil
	if not content then return false end

	if find(content, "=") or type(key) == "string" then
		table.insert(list, key .. "=" .. content)
	else
		while list.maxarg < key - 1 do
			table.insert(list, "")
			list.maxarg = list.maxarg + 1
		end
		table.insert(list, content)
		list.maxarg = key
	end
	return true
end

local function addAndConvertParameter(list, args, key, altkey1, altkey2, trkey, lang)
	if altkey1 and args[altkey1] then
		addAndConvertParameter(list, args, key, nil, nil, nil, lang)
		key = altkey1
	elseif altkey2 and args[altkey2] then
		addAndConvertParameter(list, args, key, nil, nil, nil, lang)
		key = altkey2
	end
	local content = args[key]
	if trkey and args[trkey] then
		if not content then
			content = args[trkey]
			args[trkey] = nil
		else
			error("Can't specify manual translit " .. trkey .. "=" ..
				args[trkey] .. " along with parameter " .. key .. "=" .. content)
		end
	end
	if not content then return false end
	local trcontent = nil
	-- If Sanskrit and there's an acute accent specified somehow or other
	-- in the source content, preserve the translit, which includes the
	-- accent when the Devanagari doesn't.
	if lang == "sa" then
		local proposed_trcontent = interpretShortcuts(content, "sa-tr")
		if find(proposed_trcontent, acute) then
			trcontent = proposed_trcontent
		end
	end
	-- If Gothic and there's a macron specified somehow or other
	-- in the source content that remains after canonicalization, preserve
	-- the translit, which includes the accent when the Gothic doesn't.
	if lang == "got" then
		local proposed_trcontent = interpretShortcuts(content, "got-tr")
		if find(proposed_trcontent, macron) then
			trcontent = proposed_trcontent
		end
	end
	content = interpretShortcuts(content, lang)
	addParameter(list, args, key, content)
	if trcontent then
		addParameter(list, args, trkey, trcontent)
	end
	return true
end

local isCompound = {}
for _, templateName in pairs{ "affix", "suffix", "prefix" } do
	isCompound[templateName] = true
end
local isLinkTemplate = {}
for _, templateName in pairs{ "m", "l", "ll", "cog", "noncog", "cognate", "ncog", "m-self", "l-self", "desc" } do
	isLinkTemplate[templateName] = true
end
local isTwoLangLinkTemplate = {}
for _, templateName in pairs{ "der", "inh", "bor" } do
	isTwoLangLinkTemplate[templateName] = true
end
local isTransTemplate = {}
for _, templateName in pairs{ "t", "t+", "t-check", "t+check" } do
	isTransTemplate[templateName] = true
end

local function printTemplate(args)
	local parameters = {}
	for key, value in pairs(args) do
		parameters[key] = value
	end
	
	local template = parameters[1]
	
	local result = { }
	local lang = nil
	result.maxarg = 0
	
	addParameter(result, parameters, 1)
	lang = parameters[2]
	addParameter(result, parameters, 2)
	if isLinkTemplate[template] then
		addAndConvertParameter(result, parameters, 3, "alt", 4, "tr", lang)
		for _, param in ipairs({ 5, "gloss", "t" }) do
			addParameter(result, parameters, param)
		end
	elseif isTwoLangLinkTemplate[template] then
		lang = parameters[3]
		addParameter(result, parameters, 3)
		addAndConvertParameter(result, parameters, 4, "alt", 5, "tr", lang)
		for _, param in ipairs({ 6, "gloss", "t" }) do
			addParameter(result, parameters, param)
		end
	elseif isTransTemplate[template] then
		addAndConvertParameter(result, parameters, 3, "alt", nil, "tr", lang)
		local i = 4
		while true do
			if not parameters[i] then
				break
			end
			addParameter(result, parameters, i)
		end
	elseif isCompound[template] then
		local i = 1
		while true do
			local sawparam = addAndConvertParameter(result, parameters, i + 2, "alt" .. i, nil, "tr" .. i, lang)
			if not sawparam then
				break
			end
			for _, param in ipairs({ "id", "lang", "sc", "t", "pos", "lit" }) do
				addParameter(result, parameters, param .. i)
			end
			i = i + 1
		end
	else
		error("Unrecognized template name '" .. template .. "'")
	end
	-- Copy any remaining parameters
	for k, v in pairs(parameters) do
		addParameter(result, parameters, k)
	end
	return "{{" .. table.concat(result, "|") .. "}}"
end

function export.link(frame)
	local args = frame.args or frame
	
	return printTemplate(args)
end

function export.replace(frame)
	local args = clone_args(frame)
	local text, lang
	
	if args[3] or args.tr then
		return printTemplate(args)
	else
		if args[2] then
			lang, text = args[1], args[2]
		else
			lang, text = "all", args[1]
		end
	end
	
	if lang == "hit" then
		return intoHittite(text)
	else
		text = interpretShortcuts(text, lang)
	end
	
	return text or ""
end

function export.example(frame)
	local args = clone_args(frame)
	
	local text, lang
	
	if args[2] then
		lang, text = args[1], args[2]
	else
		lang, text = "all", args[1]
	end
	
	local textparam
	if find(text, "=") then
		textparam = "2="..text -- Currently, "=" is only used in the shortcuts for Greek, and Greek is always found in the second parameter, since the first parameter specify the language, "grc".
	else
		textparam = text
	end
	
	local template = {
		[1] = "subst:chars",
		[2] = lang ~= "all" and lang or textparam,
		[3] = lang ~= "all" and textparam or nil,
	}
	
	local output = { formatLink(template) }
	table.insert(output, "\n| ")
	table.insert(output, lang ~= "all" and "<span lang=\""..lang.."\">" or "")
	table.insert(output, export.replace({lang, text}))
	table.insert(output, lang ~= "all" and "</span>" or "")
	
	return table.concat(output)
end

function export.examples(frame)
	local args = frame.getParent and frame:getParent().args or frame.args[1] and frame.args or frame
	
	local examples = args[1] and mw.text.split(args[1], ";%s+") or error('No content in the first parameter.')
	local lang = args["lang"]
	
	local output = {
[[
{| class="wikitable"
! shortcut !! result
]]
	}
	
	local row = [[
|-
| templateCode || result
]]
	
	for _, example in pairs(examples) do
		local textparam
		if find(example, "=") then
			textparam = "2=" .. example -- Currently, "=" is only used in the shortcuts for Greek, and Greek is always found in the second parameter, since the first parameter specify the language, "grc".
		else
			textparam = example
		end
		
		local template = {
			[1] = "subst:chars",
			[2] = lang or textparam,
			[3] = lang and textparam,
		}
		
		local result = export.replace{lang, example}
		
		local content = {
			templateCode = formatLink(template),
			result = tag(result, lang),
		}
		
		local function addContent(item)
			if content[item] then
				return content[item]
			else
				return 'No content for "' .. item .. '".'
			end
		end
		
		local row = gsub(row, "%a+", addContent)
		
		table.insert(output, row)
	end
	
	return table.concat(output) .. "|}"
end

return export