This module implements the translation templates {{t}}, {{t+}}, {{trans-top}}, {{trans-bottom}} and {{trans-see}}. See their documentation for more information.


local html_create = mw.html.create
local require = require
local load_data = mw.loadData

local param_process = require("Module:parameters").process
local m_params_data = load_data("Module:parameters/data")

local export = {}

-- Implements {{t}} and {{t+}}.
function export.show(frame)
	local args = param_process(
		frame:getParent().args,
		m_params_data.translations.show,
		nil,
		"translations",
		"show"
	)
	
	local terminfo = {
		lang = require("Module:languages").getByCode(args[1], 1, "allow etym"),
		sc = args.sc and require("Module:scripts").getByCode(args.sc, "sc") or nil,
		track_sc = true,
		term = args[2] or mw.title.getCurrentTitle().namespace == 10 and "term",
		alt = args.alt,
		id = args.id,
		genders = args[3],
		tr = args.tr,
		ts = args.ts,
		lit = args.lit,
		interwiki = frame.args.interwiki,
	}
	
	return export.show_terminfo(terminfo)
end

local function interwiki(terminfo, lang, langcode, term, m_links, m_data)
	-- Don't show interwiki link if the term contains links (for SOP translations)
	if term:find("[[", nil, true) then
		terminfo.interwiki = false
		return
	end
	
	local wmlangs
	local interwiki_langcode = m_data.interwiki_langs[langcode]
	if interwiki_langcode then
		wmlangs = {require("Module:wikimedia languages").getByCode(interwiki_langcode)}
	else
		wmlangs = lang:getWikimediaLanguages()
	end
	
	-- Don't show the interwiki link if the language is not recognised by Wikimedia.
	if #wmlangs == 0 then
		terminfo.interwiki = false
		return
	end
	
	local sc = terminfo.sc
	
	local target_page = m_links.get_link_page(term, lang, sc)
	local split = m_links.split_on_slashes(target_page)
	if not split[1] then
		terminfo.interwiki = false
		return
	end
	target_page = split[1]
	
	local wmlangcode = wmlangs[1]:getCode()
	local interwiki_link = m_links.language_link{
		lang = lang,
		sc = sc,
		term = wmlangcode .. ":" .. target_page,
		alt = "(" .. wmlangcode .. ")",
		tr = "-"
	}
	
	terminfo.interwiki = tostring(mw.html.create("span")
		:addClass("tpos")
		:wikitext(" " .. interwiki_link))
end

function export.show_terminfo(terminfo)
	local m_data = load_data("Module:translations/data")
	local lang = terminfo.lang
	-- Translations must be for mainspace languages
	if not lang:hasType("regular") then
		error("Translations must be for attested and approved main-namespace languages.")
	else
		local err_msg = m_data.disallowed[lang:getCode()]
		if err_msg then
			local name = lang:getCanonicalName()
			error("Translations not allowed in " .. name .. " (" .. lang:getCode() .. "). " .. name .. " translations should " .. err_msg)
		end
	end
	
	local langcode = lang:getCode()
	local term = terminfo.term
	local m_links = require("Module:links")
	
	-- Check if there is a term. Don't show the interwiki link if there is nothing to link to.
	if term and terminfo.interwiki then
		interwiki(terminfo, lang, langcode, term, m_links, m_data)
	else
		-- Track entries that don't provide a term.
		-- FIXME: This should be a category.
		local track = require("Module:debug/track")
		track("translations/no term")
		track("translations/no term/" .. langcode)
	end
	
	if lang and m_data.need_super[langcode] then
		local tr = terminfo.tr
		terminfo.tr = tr and tr:gsub("(%d%-?%d?)", "<sup>%1</sup>")
	end
	
	return m_links.full_link(terminfo, "translation")
end

-- Implements {{trans-top}} and part of {{trans-top-also}}.
local function top(args, title, navhead)
	local insert = table.insert
	
	local column_width = (args["column-width"] == "wide" or args["column-width"] == "narrow") and "-" .. args["column-width"] or ""
	
	local div = html_create("div")
		:addClass("NavFrame")
		:node(navhead)
		:tag("div")
			:addClass("NavContent")
			:tag("table")
				:addClass("translations")
				:attr("role", "presentation")
				:css("width", "100%")
				:attr("data-gloss", title or "")
				:tag("tr")
					:tag("td")
						:addClass("translations-cell multicolumn-list" .. column_width)
						:css("background-color", "#ffffe0")
						:css("vertical-align", "top")
						:css("text-align", "left")
						:attr("colspan", "3")
						:allDone()
	
	local id = args.id or title
	div = id and div:attr("id", "Translations-" .. id) or div
	div = tostring(div)
	
	local categories = {}
	
	if not title and mw.title.getCurrentTitle().namespace == 0 then
		insert(categories, "Translation table header lacks gloss")
	end
	
	local pagename = load_data("Module:headword/data").encoded_pagename
		:gsub("/translations$", function()
			insert(categories, "Translation subpages")
			return ""
		end)
	
	if #categories > 0 then
		categories = require("Module:utilities").format_categories(
			categories,
			require("Module:languages").getByCode("en"),
			nil,
			pagename
		)
	else
		categories = ""
	end
	
	return (div:gsub("</td></tr></table></div></div>$", "")) .. categories
end

-- Entry point for {{trans-top}}.
function export.top(frame)
	local args = param_process(
		frame:getParent().args,
		m_params_data.translations.top,
		nil,
		"translations",
		"top"
	)
	
	local title = args[1]
	title = title and require("Module:links").remove_links(title)
	
	local navhead = html_create("div")
		:addClass("NavHead")
		:css("text-align", "left")
		:css("cursor", "pointer")
		:wikitext(title or "Translations")
		
	return top(args, title, navhead)
end

-- Entry point for {{checktrans-top}}.
function export.check_top(frame)
	local args = param_process(
		frame:getParent().args,
		m_params_data.translations.check_top,
		nil,
		"translations",
		"check_top"
	)
	
	local text = "\n:''The translations below need to be checked and inserted above into the appropriate translation tables. See instructions at " ..
		frame:expandTemplate{
			title = "section link",
			args = {"Wiktionary:Entry layout#Translations"}
		} ..
		".''\n"
	
	local header = html_create("div")
		:addClass("checktrans")
		:wikitext(text)
		:allDone()
		
	local title = "Translations to be checked"
	if args[1] then
		title = title .. "&zwnj;: \"" .. args[1] .. "\""
	end
	
	local navhead = html_create("div")
		:addClass("NavHead")
		:css("text-align", "left")
		:css("cursor", "pointer")
		:wikitext(title or "Translations")
	
	return tostring(header) .. "\n" .. top(args, title, navhead)
end

-- Implements {{trans-bottom}}.
function export.bottom(frame)
	-- Check nothing is being passed as a parameter.
	param_process(
		frame:getParent().args,
		m_params_data.translations.bottom,
		nil,
		"translations",
		"bottom"
	)
	return "</table></div></div>"
end

-- Implements {{trans-see}} and part of {{trans-top-also}}.
local function see(args, see_text)
	local table = table
	local insert = table.insert
	
	local navhead = html_create("div")
		:addClass("NavHead")
		:css("text-align", "left")
		:wikitext(args[1] .. " ")
		:tag("span")
			:css("font-weight", "normal")
			:wikitext("— ")
			:tag("i")
				:wikitext(see_text)
				:allDone()
	
	local data = {}
	data.id = args["id"] and "Translations-" .. args["id"]
	
	local terms = {}
	if #args[2] == 0 then
		table.insert(args[2], args[1])
	end
	
	local plain_link = require("Module:links").plain_link
	for _, term in ipairs(args[2]) do
		data.term = term
		insert(terms, plain_link(data))
	end
	
	return navhead:wikitext(table.concat(terms, ",&lrm; "))
end

-- Entry point for {{trans-see}}.
function export.see(frame)
	local args = param_process(
		frame:getParent().args,
		m_params_data.translations.see,
		nil,
		"translations",
		"see"
	)
	local navhead = see(args, "see ")
	return tostring(html_create("div")
		:addClass("pseudo NavFrame")
		:node(navhead))
end

-- Entry point for {{trans-top-also}}.
function export.top_also(frame)
	local args = param_process(
		frame:getParent().args,
		m_params_data.translations.top_also,
		nil,
		"translations",
		"top_also"
	)
	
	local title = args[1]
	title = title and require("Module:links").remove_links(title)
	
	local navhead = see(args, "see also ")
	return top(args, title, navhead)
end
	
return export