Module:Nomenclature
Jump to navigation
Jump to search
This is the main module for Template:Nomenclature.
local p = {}
local h = {}
local Franchise = require("Module:Franchise")
local Language = require("Module:Language")
local Term = require("Module:Term")
local Util = {
cargo = {
all = require("Module:Util/cargo/all"),
query = require("Module:Util/cargo/query"),
},
tables = {
find = require("Module:Util/tables/find"),
groupBy = require("Module:Util/tables/groupBy"),
_groupBy = require("Module:Util/tables/_groupBy"),
invert = require("Module:Util/tables/invert"),
keys = require("Module:Util/tables/keys"),
mapValues = require("Module:Util/tables/mapValues"),
sortBy = require("Module:Util/tables/sortBy"),
},
}
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 = Util.cargo.all({
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 " ..Util.cargo.all({
term = term
}, "subject NOT LIKE '%)'") -- without this, requesting "Wood" would also fetch data for Wood (Character)
end
whereClause = Util.cargo.all(whereClause, "translation != 'N/A'")
local translations = Util.cargo.query("Translations", "game, term, lang, translation, meaning, ref", {
where = whereClause
})
return translations
end
function h.formatData(translations)
local hasMeanings = Util.tables.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
local superseder = Franchise.superseder(game)
local hasRemakes = superseder and superseder ~= ""
if Franchise.isRemake(game) or hasRemakes then
hasRemakes = true
end
end
local displayGames = gameCount > 1 or hasRemakes
-- Group translations by language and then by name
local games = Util.tables.keys(seenGames)
games = Franchise.sort(games)
local gameOrderLookup = Util.tables.invert(games)
translations = Util.tables.sortBy(translations, function(translation)
return gameOrderLookup[translation.game] or 1000
end)
translations = Util.tables.groupBy(translations, "lang")
translations = Util.tables.mapValues(translations, Util.tables._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 = Util.tables.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("[[File:ZW Nomenclature Asset.png|20px|link=]] Names in Other Regions [[File:ZW Nomenclature Asset 2.png|link=]]")
: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("<small>This table was generated using [[Data:Translations|translation pages]].<br>To request an addition, please contact a [[Zelda Wiki:Staff|staff member]] with a [[Guidelines:References|reference]].</small>")
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