Module:Nomenclature

From Zelda Wiki, the Zelda encyclopedia
Revision as of 13:05, 21 September 2022 by PhantomCaleb (talk | contribs) (Merge name and meaning into one column if the name is the same as in English.)
Jump to navigation Jump to search

This is the main module for Template:Nomenclature.

Lua error in package.lua at line 80: module 'Module:Tab2' not found.


local p = {}
local h = {}

local cargo = mw.ext.cargocs
local expgame = require('Module:Exp Game')
local tab2 = require('Module:Tab2')
local File = require("Module:File")
local Franchise = require("Module:Franchise")
local Term = require('Module:Term')
local translation = require('Module:Translation')
local utilsError = require('Module:UtilsError')
local utilsLanguage = require('Module:UtilsLanguage')
local utilsMarkup = require("Module:UtilsMarkup")
local utilsString = require("Module:UtilsString")
local utilsTable = require('Module:UtilsTable')

-- temporary to remove {{Names}}
function p.HasTranslationsStored(frame)
	local term = frame.args["term"]
	if utilsString.isEmpty(term) then
		term = mw.title.getCurrentTitle().subpageText
	end
	if #translation.fetchTranslations(term) > 0 then
		return true
	else
		return false
	end
end

-- For creating nomenclature tables
function p.Main( frame )
	local term = frame.args["term"]
	if utilsString.isEmpty(term) then
		term = mw.title.getCurrentTitle().subpageText
	end
	local cargoData = translation.fetchTranslations(term)
	local displayGames = false
	local skipMeanings = true
	for key, row in ipairs(cargoData) do
		if cargoData[1]["game"] ~= row["game"] or Franchise.isRemake(row.game) or Franchise.hasRemakes(row.game) then
			displayGames = true
		end
		if not utilsString.isEmpty(row["meaning"]) then
			skipMeanings = false
		end
	end
	local resultTable = h.CreateTable(skipMeanings)
	resultTable = h.CreateRows(resultTable, cargoData, skipMeanings, displayGames)
	resultTable:node(mw.html.create("tr"):node(mw.html.create("th"):attr("colspan", "4"):wikitext("<small>This table was generated using [[Data:Translations|translation pages]].<br>To request an addition, please <span class='plainlinks'>[https://discord.gg/eJnnvYb contact]</span> a [[Zelda Wiki:Staff|staff member]] with a [[Guidelines:References|reference]].</small>")))
	return resultTable
end

--Create an empty table with headers
function h.CreateTable(skipMeanings)
	--Table structure
	local resultTable = mw.html.create("table")
		:addClass("wikitable"):done()
	
	--Global header
	local headerRow = mw.html.create("tr"):done()
	local headerContent = mw.html.create("th")
		:wikitext("[[File:TMC Forest Minish Artwork.png|20px|link=]] Names in Other Regions [[File:TMC Jabber Nut Sprite.png|link=]]")
		:attr("colspan", "4")
		:css{
			["font-size"] = "110%",
		}:done()
	
	headerRow:node(headerContent)
	resultTable:node(headerRow)
	
	--Individual headers
	--Language
	headerRow = mw.html.create("tr"):done()
	headerContent = mw.html.create("th")
		:wikitext("Language")
		:attr("colspan", "2"):done()
	headerRow:node(headerContent)
	
	--Name
	headerContent = mw.html.create("th")
		:wikitext("Name"):done()
	headerRow:node(headerContent)
	
	--Meaning
	if not skipMeanings then
		headerContent = mw.html.create("th")
			:wikitext("Meaning"):done()
		headerRow:node(headerContent)
	end
	
	resultTable:node(headerRow)
	
	return resultTable
end

function h.CreateRows(output, cargoData, skipMeanings, displayGames)
	h.SortTranslations(cargoData)
	for _, row in ipairs(cargoData) do
		if not row.skip and row.translation ~= "N/A" then
			h.ProcessRow(output, cargoData, row, skipMeanings, displayGames)
		end
	end
	
	return output
end

function h.SortTranslations(translations)
	local lookupLang = utilsTable.invert(utilsLanguage.enum())
	local lookupGame = utilsTable.invert(Franchise.enumGames())
	table.sort(translations, function (a,b)
			if (lookupLang[a.language] or 0) == (lookupLang[b.language] or 0) then
				return (lookupGame[a.game] or 0) < (lookupGame[b.game] or 0)
			else
				return (lookupLang[a.language] or 0) < (lookupLang[b.language] or 0)
			end
		end
	)
end

function h.ProcessRow(output, cargoData, row, skipMeanings, displayGames)
	local meanings = h.GetMeanings(cargoData, row)
	local langText, flag = utilsLanguage.printLanguage(row.language)
	local tr = output:tag('tr')
		:tag("td")
			:addClass("nomenclature-flag")
			:wikitext(flag)
			:done()
		:tag("td")
			:wikitext(langText)
			:done()
	
	local sameNameAsEnglish = row.translation == row.term
	h.PrintNames(tr, cargoData, row, displayGames, {
		-- name and meaning get merged into one column if the name is the same as the English name
		-- See The Legend of Zelda: Tears of the Kingdom, for example
		colspan = sameNameAsEnglish and 2 or nil,
	})
	h.MarkRowsToSkip(cargoData, row)
	if not skipMeanings and not sameNameAsEnglish then
		h.PrintMeanings(tr, meanings)
	end
	
end

function h.GetMeanings(cargoData, row)
	local ret = { row.meaning }
	for _, row2 in ipairs(cargoData) do
		if h.SameLangDifTranslations(row, row2) then
			ret[#ret+1] = row2.meaning
		end
	end
	return ret
end

function h.PrintNames(tr, cargoData, row, displayGames, options)
	local td = tr:tag('td')
		:wikitext(table.concat(h.GetNamesAndTheirGames(cargoData, row, displayGames), '<br>'))
	if options.colspan then
		td:attr("colspan", options.colspan)
	end
end

function h.GetNamesAndTheirGames(cargoData, row, displayGames)
	local ret = { h.GetOneNameAndGames(cargoData, row, displayGames) }
	for _, row2 in ipairs(cargoData) do
		if h.SameLangDifTranslations(row, row2) then
			games = h.GamesWithSameTranslation(row2, cargoData)
			ret[#ret+1] = h.GetOneNameAndGames(cargoData, row2, displayGames)
		end
	end
	return ret
end

function h.GetOneNameAndGames(cargoData, row, displayGames)
	local games = h.GamesWithSameTranslation(row, cargoData)
	local result = row.translation
	if displayGames == true then
		result = result .. " " .. expgame.printGames(games)
	end
	
	local refs = h.RefsWithSameTranslation(row, cargoData)
	for key, ref in ipairs(refs) do
		if not utilsString.isEmpty(ref) then
			result = result .. mw.getCurrentFrame():extensionTag("ref", ref)
		end
	end
	return result
end

function h.GamesWithSameTranslation(row, cargoData)
	local ret = {}
	for _, row2 in ipairs(cargoData) do
		if h.SameLangSameTranslation(row, row2) then
			ret[#ret+1] = row2.game
		end
	end
	return ret
end

function h.RefsWithSameTranslation(row, cargoData)
	local ret = {}
	for _, row2 in ipairs(cargoData) do
		if h.SameLangSameTranslation(row, row2) then
			ret[#ret+1] = row2.reference
		end
	end
	return ret
end

function h.SameLangSameTranslation(row1, row2)
	return row1.language == row2.language and row1.translation == row2.translation
end

function h.SameLangDifTranslations(row1, row2)
	return row1.language == row2.language and row1.translation ~= row2.translation
end

function h.SameLang(row1, row2)
	return row1.language == row2.language
end

function h.PrintMeanings(tr, meanings)
	local meaningsDisplays = h.ProcessMeanings(meanings)
	td = tr:tag('td')
		:wikitext(table.concat(meaningsDisplays, '<br>'))
end

function h.MarkRowsToSkip(cargoData, row)
	for _, row2 in ipairs(cargoData) do
		if h.SameLang(row, row2) then
			row2.skip = true
		end
	end
end

function h.ProcessMeanings(meanings)
	local ret = {}
	for k, v in pairs(meanings) do
		if utilsString.isEmpty(v) then
			ret[#ret+1] = '&nbsp;'
		else
			ret[#ret+1] = v
		end
	end
	return ret
end

-- TRANSLATION PAGES
function p._CreateTranslationTables(frame)
	local args = frame:getParent().args
	
	local tabs = {}
	local index = 0
	while true do
		index = index + 1
		if utilsString.isEmpty(args["tab" .. index]) then
			break
		else
			table.insert(tabs, {tabName = args["tab" .. index], tabContent = args["subjects"]})
		end
	end
	
	return p.CreateTranslationTables(args["game"], args["filetype"], args["header"], tabs, args["subjects"])
end

function p.CreateTranslationTables(game, filetype, header, tabs, subjects)
	subjects = utilsString.split(subjects)
	
	if filetype == "Screenshot" then
		filetype = ""
	end
	
	if utilsString.isEmpty(header) then
		header = "Subject"
	end
	
	for key, tab in ipairs(tabs) do
		local languages = utilsString.split(tab["tabName"], '%s*,%s*')
		--Creating tab contents
		local headerRow = mw.html.create("tr")
			:node(mw.html.create("th"):wikitext(header)):done()
		for key2, language in ipairs(languages) do
			local langText, flag = utilsLanguage.printLanguage(language)
			headerRow:node(
				mw.html.create("th")
					:wikitext(flag .. "<br>" .. langText)
					:css("width", 100 / (#languages + 1) .. "%")
				)
				:done()
		end
		
		local content = mw.html.create("table")
			:addClass("wikitable")
			:css("width", "100%")
			:node(headerRow)
		
		--Creating rows
		local errs = {}
		local translations = translation.fetchTranslationsByGame(game, subjects)
		for key2, subject in ipairs(subjects) do
			local term, err = Term.fetchTerm(subject, game)
			if not term then
				utilsError.warn(string.format("Page %s does not store any terms.", utilsMarkup.code(subject)))
				errs = utilsTable.concat(errs, err)
			else
				-- Assume that by default, the file is named according to the term. If term+game cannot uniquely identify the subject, assume the file name matches the page name.
				-- Example A: Given subject Wood (Character) and game ST, the filename is inferred to be "ST Wood Model.png". In ST, the term "Wood" uniquely identifies the subject.
				-- Example B: Given subject Link (Goron) and game MM, the file name is inferred to be "MM Link (Goron) Model.png. In MM, the term 'Link' refers to two characters and does not uniquely identify the subject.
				local fileIdentifier = term
				if utilsString.endsWith(subject, ")") and #Term.fetchSubjects(term, game) > 1 then
					fileIdentifier = subject 
				end
				local img = File.gameImage(game, fileIdentifier, filetype, {
					size = "150x150px",
					checkExists = false, -- checking for file existence has too much of a time cost for translation pages
				})
				term = Term.printTerm({
					page = subject,
					game = game,
					link = "link",
				})
				local row = h.printRow(img, term, languages, translations[subject] or {})
				content:node(row)
			end
		end
			
		tab["tabContent"] = tostring(content) .. "<small>Return to [[#top|top]]</small>" .. utilsMarkup.categories(errs)
		
		-- Formatting tab names
		for key2, language in ipairs(languages) do
			languages[key2] = utilsLanguage.printLanguage(language, true)
		end
		languages = utilsTable.unique(languages)
		tab["tabName"] = table.concat(languages, ", ")
	end
	
	if #tabs == 1 then
		return tabs[1]["tabContent"]
	else
		return tab2.Main(tabs, 1, "top", #tabs, "", "", "", "left")
	end
end

function h.printRow(img, term, languages, translations)
	local row = mw.html.create("tr")
		:node(mw.html.create("td")
			:addClass("centered")
			:wikitext(img .. "<br>" .. utilsMarkup.bold(term)))
		
	for _, language in ipairs(languages) do
		outputs = {}
		for _, translation in ipairs(translations) do
			if translation["language"] == language then
				table.insert(outputs, translation["translation"])
			end
		end

		local cell = mw.html.create("td"):addClass("centered")
		if outputs[1] == "N/A" then
			cell:wikitext("—")
		else
			cell:wikitext(table.concat(outputs, "<br>"))
		end
		row:node(cell):done()
	end
	return row
end

return p