Module:Nomenclature: Difference between revisions
Jump to navigation
Jump to search
MannedTooth (talk | contribs) (saving progress) |
TriforceTony (talk | contribs) mNo edit summary |
||
(170 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | 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 | ||
local | 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 | |||
return | 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 | end | ||
function | function h.printNomenclatureTable(translationsByLang, hasMeanings, displayGames) | ||
local | 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") | |||
:wikitext( | 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 | ||
end | end | ||
return | 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 | 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 | end | ||
return | return result | ||
end | end | ||
function | function h.list(items) | ||
local | local list = mw.html.create("ul"):addClass("plainlist") | ||
for i, item in ipairs(items) do | |||
list:tag("li"):wikitext(item) | |||
return | end | ||
return tostring(list) | |||
end | end | ||
return p | return p |
Latest revision as of 16:33, 14 April 2024
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 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("[[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