Module:Nomenclature

local p = {} local h = {}

local Franchise = require("Module:Franchise") local Language = require("Module:Language") local Term = require("Module:Term") local utilsCargo = require("Module:UtilsCargo") local utilsTable = require('Module:UtilsTable')

local DISCORD_URL = require("Module:Constants/url/discord")

-- For creating nomenclature tables function p.Main(frame) local subject = frame.args["term"] if subject == nil or subject == "" then subject = mw.title.getCurrentTitle.subpageText end local translations = h.fetchTranslations(subject) local translations, hasMeanings, displayGames = h.formatData(translations) local nomenclatureTable = h.printNomenclatureTable(translations, hasMeanings, displayGames) return nomenclatureTable end

function h.fetchTranslations(page) local whereClause = utilsCargo.allOf({   	subject = page	}) -- Fetch translations of synonyms local term = Term.fetchTerm(page) if term and not string.find(page, "%)$") then -- without this ) check, Wood (Character) would also fetch data for BotW Wood term = string.gsub(term, "#", "") -- terms with # in them are stored in a version of the page without the #, because MediaWiki. Also Cargo doesn't allow queries with # in them. whereClause = whereClause .. " OR " ..utilsCargo.allOf({	   	term = term		}, "subject NOT LIKE '%)'") -- without this, requesting "Wood" would also fetch data for Wood (Character)	end	local translations = utilsCargo.query("Translations", "game, term, lang, translation, meaning, ref", { where = whereClause })	return translations end

function h.formatData(translations) local hasMeanings = utilsTable.find(translations, function(translation)		return translation.meaning == nil and translation.meaning ~= "" and translation.term ~= translation.translation	end) -- Determine whether to display Exp Game local seenGames = {} local gameCount = 0 local hasRemakes = false for i, translation in ipairs(translations) do		local game = translation.game if not seenGames[game] then gameCount = gameCount + 1 seenGames[game] = true end if Franchise.isRemake(game) or Franchise.hasRemakes(game) then hasRemakes = true end end local displayGames = gameCount > 1 or hasRemakes -- Group translations by language and then by name local gameOrderLookup = utilsTable.invert(Franchise.enum) translations = utilsTable.sortBy(translations, function(translation)		return gameOrderLookup[translation.game] or 1000	end) translations = utilsTable.groupBy(translations, "lang") translations = utilsTable.mapValues(translations, utilsTable._groupBy("translation")) -- Creates a list of unique translations grouped by language -- For each unique translation, lists which games have that translation, assigns a meaning to it, and creates the refs -- If multiple games have different meanings for the same translation, we use the latest game local hasMeanings = false local translationLists = {} for lang, langTranslations in pairs(translations) do		local translationList = {} for translation, translationGames in pairs(langTranslations) do			local translationListItem = { translation = translation, games = {}, meaning = " ", term = translationGames[1].term, refs = "", }			for i, translationGame in ipairs(translationGames) do				local meaning = translationGame.meaning if meaning ~= nil and meaning ~= "" then translationListItem.meaning = meaning hasMeanings = true end table.insert(translationListItem.games, translationGame.game) translationListItem.refs = translationListItem.refs..h.printRef(translation, translationGame.ref) end table.insert(translationList, translationListItem) end -- Sort translations by their earliest appearance translationList = utilsTable.sortBy(translationList, function(translation)			return gameOrderLookup[translation.games[1]]		end) translationLists[lang] = translationList end return translationLists, hasMeanings, displayGames end

local refCount = 0 local refNamePrefix = "nomenclature-" local seenCitations = {} -- to prevent duplicate citations in the ==References== section on the page local seenRefs = {} -- to prevent duplicate reference markers in a given Nomenclature table row (e.g. Bomb Simplified Chinese) function h.printRef(translation, citation) if citation == nil or citation == "" then return "" end seenRefs[translation] = seenRefs[translation] or {} local refSeen = seenRefs[translation][citation] local citationIndex = seenCitations[citation] local refContent if refSeen then -- Do nothing, the ref is already being shown for this translation due to it being the same in multiple games -- (happens when the source is a book like E)		return "" elseif citationIndex then -- refContent stays nil since we're re-using an existing ref refContent = nil seenRefs[translation][citation] = true else -- create a new ref refCount = refCount + 1 citationIndex = refCount refContent = citation seenCitations[citation] = citationIndex seenRefs[translation][citation] = true end local frame = mw.getCurrentFrame if frame:getParent.args[1] then -- workaround if Nomenclature is used multiple times per page local subject = frame.args["term"] return frame:extensionTag({		name = "ref",		args = { name = refNamePrefix..subject..'-'..citationIndex },		content = refContent,	}) end return frame:extensionTag({		name = "ref",		args = { name = refNamePrefix..citationIndex },		content = refContent,	}) end

function h.printNomenclatureTable(translationsByLang, hasMeanings, displayGames) local html = mw.html.create("table") :addClass("wikitable") :tag("tr") :tag("th") :addClass("nomenclature__header") :attr("colspan", hasMeanings and 3 or 2) :wikitext(" Names in Other Regions ") :done :done :done local columns = html:tag("tr") columns:tag("th"):wikitext("Language") columns:tag("th"):wikitext("Names") if hasMeanings then columns:tag("th"):wikitext("Meanings") end for i, lang in ipairs(Language.enum) do		local translations = translationsByLang[lang] if translations then h.addRow(html, hasMeanings, displayGames, lang, translations) end end local footerText = mw.getCurrentFrame:preprocess(" This table was generated using translation pages. To request an addition, please a staff member with a reference. ") html:tag("tr") :tag("th") :attr("colspan", "3") :wikitext(footerText) return tostring(html:allDone) end

function h.addRow(html, hasMeanings, displayGames, lang, translations) local row = html:tag("tr") local langCell = mw.html.create("td"):addClass("nomenclature__cell nomenclature__cell--language") local nameCell = mw.html.create("td"):addClass("nomenclature__cell nomenclature__cell--name") local meaningCell = mw.html.create("td"):addClass("nomenclature__cell nomenclature__cell--meanings") local lect = Language.getLect(lang) langCell:tag("div") :addClass("nomenclature__language") :tag("div") :addClass("nomenclature__language-flags") :wikitext(unpack(lect.flags)) :done :tag("div") :addClass("nomenclature__language-name") :wikitext(lect.abbr) :done :done local names = {} local meanings = {} for i, translation in ipairs(translations) do		names[i] = h.printTranslationName(translation, displayGames)..translation.refs meanings[i] = translation.meaning end names = #names == 1 and names[1] or h.list(names) meanings = #meanings == 1 and meanings[1] or h.list(meanings) nameCell:wikitext(names) meaningCell:wikitext(meanings) -- When the foreign name is the exact same as the NoA name (see TotK page for example) if #translations == 1 and translations[1].translation == translations[1].term then nameCell:attr("colspan", 2) meaningCell = nil end

row:node(langCell) row:node(nameCell) if hasMeanings and meaningCell then row:node(meaningCell) end end

function h.printTranslationName(translationData, displayGames) local result = translationData.translation if displayGames then result = result .. " " .. mw.getCurrentFrame:expandTemplate({			title = "Exp Game",			args = {table.concat(translationData.games, ", ")}		}) end return result end

function h.list(items) local list = mw.html.create("ul"):addClass("plainlist") for i, item in ipairs(items) do		list:tag("li"):wikitext(item) end return tostring(list) end

return p