Module:Translation Page

local File = require("Module:File") local Franchise = require("Module:Franchise") local Term = require("Module:Term") local Translation = require("Module:Translation") local utilsArg = require("Module:UtilsArg") local utilsError = require("Module:UtilsError") local utilsLanguage = require("Module:UtilsLanguage") local utilsLayout = require("Module:UtilsLayout") local utilsMarkup = require("Module:UtilsMarkup") local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable") local utilsVar = require("Module:UtilsVar")

local p = {} local h = {}

local VAR_DATA_PAGE = "dataPage"

local subpages = { {		name = "Characters", content = "every named character", },	{		name = "Enemies", content = "every named Series:", },	{		name = "Items", content = "every named Series: and Series:", },	{		name = "Locations", content = "every named location" },	{		name = "Miscellaneous", content = "miscellaneous subjects", }, } local subpagesWithAll = utilsTable.concat(subpages, {	{		name = "All",		content = "every named character, boss, enemy, location and item"	} }) local subpagesLookup = utilsTable.keyBy(subpages, "name")

function p.BasepageHeader(frame) local templateSpec = p.Templates["Translation Header Basepage"] -- Allow utilsArg to parse params for providing references to supplementary material -- We don't put them in the p.Templates object with the rest to avoid polluting the doc local refParams = {} for i, langCode in ipairs(utilsLanguage.enum) do		refParams[langCode] = { type = "string" }	end templateSpec.params = utilsTable.merge(templateSpec.params, refParams) local args, err = utilsArg.parse(frame:getParent.args, templateSpec) local errorCategories = utilsMarkup.categories(err and err.categories or {}) local result = p.basePageHeader(args.game, args.languagesGame, args.languagesSupplementary, args) return result..errorCategories end

function p.SubpageHeader(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates["Translation Header Subpage"]) if err then return utilsMarkup.categories(err.categories) else return p.subpageHeader(args.game, args.subpage) end end

-- Template:Translation Page function p.CreateTranslationTables(frame) local args = frame:getParent.args local languageGroups = {} local index = 0 while true do		index = index + 1 if utilsString.isEmpty(args["tab" .. index]) then break else table.insert(languageGroups, args["tab" .. index]) end end return p.createTranslationTables(args["game"], args["filetype"], args["header"], args["subjects"], languageGroups) end

function p.basePageHeader(game, languagesGame, languagesSupplementary, supplementaryRefs) local header = "" -- This template is used on the base page but the base page itself is transcluded from the subpage. The output must differ depending on where we are currently local title = mw.title.getCurrentTitle local page = title.text local isBasePage = title.text == title.subpageText local isAllSubpage = title.subpageText == "All" if isBasePage then header = header..":Notice: Zelda Wiki splits game translations into sections.\n\n" end local gameLink = Franchise.link(game) or game local gameDisplay = Franchise.display(game) or game

local gameLanguages, supplementaryLanguages = p.printLanguageLists(languagesGame or {}, languagesSupplementary or {}, isBasePage and nil or supplementaryRefs, true) -- we only show supplementary refs on the basepage header = header..string.format("%s has been released in the following languages: %s", isBasePage and gameLink or gameDisplay, gameLanguages) if supplementaryLanguages ~= "" then header = header..string.format(" Supplementary material for %s has been released in %s", gameDisplay, supplementaryLanguages) end header = header .. "\n\n" local subpageLinks = utilsTable.map(subpages, function(subpage)		return string.format("%s", page, subpage.name, subpage.name)	end) local subpageList = utilsMarkup.bulletList(subpageLinks) if isBasePage then header = header..string.format("The translation sections for %s are as follows: %s", gameDisplay, subpageList) header = header..string.format("\n\nAlternatively, you may view all translations at once, although this is not recommended due to the immense size of the page.", page) header = header.."\n\n" end return header end

function p.printLanguageLists(languagesGame, languagesSupplementary, supplementaryRefs) local gameLanguagesList = utilsTable.map(languagesGame, function(langCode)		return {			text = utilsLanguage.printLect(langCode) or langCode		}	end) gameLanguagesList = p.phraseList(gameLanguagesList) local supplementaryLanguagesList = utilsTable.map(languagesSupplementary or {}, function(langCode)		local refs = supplementaryRefs[langCode]		refs = refs and mw.text.decode(mw.text.unstripNoWiki(refs))		return {			text = utilsLanguage.printLect(langCode) or langCode,			refs = refs,		}	end) supplementaryLanguagesList = p.phraseList(supplementaryLanguagesList) return gameLanguagesList, supplementaryLanguagesList end

function p.phraseList(items) if #items == 0 then return "" end local result = "" for i, item in ipairs(items) do		if item.text then result = result..item.text local refs = item.refs or "" if i == #items then result = result.."."..refs elseif i == (#items - 1) then result = result..","..refs .." and " else result = result..","..refs.." " end end end return result end

function p.subpageHeader(game, subpage) utilsVar.set(VAR_DATA_PAGE, "Data:"..game.."/"..subpage) local headerText = string.format("The following page is a list of the names of every %s appearing in %s in every release of the game. ", subpagesLookup[subpage].content, Franchise.link(game)) headerText = headerText .. mw.getCurrentFrame:expandTemplate({		title = ":"..mw.title.getCurrentTitle.baseText -- Transclude the base page header to get its text and the language variables	}) headerText = headerText.."\n\n" headerText = headerText.."*Empty cells indicate that a name has not yet been found for that particular term in that language.\n" headerText = headerText.."*Cells with an em dash (−) indicate there is no given name for that particular term in that language.\n" return headerText end

function p.createTranslationTables(game, filetype, header, subjects, languageGroups) subjects = utilsString.split(subjects) if filetype == "Screenshot" then filetype = "" end if utilsString.isEmpty(header) then header = "Subject" end local tabData = {} for key, languageGroup in ipairs(languageGroups) do		local languages = utilsString.split(languageGroup, '%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 .. " " .. 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		local tabContent = tostring(content) .. " Return to top " .. utilsMarkup.categories(errs)		-- Formatting tab names		for key2, language in ipairs(languages) do			languages[key2] = utilsLanguage.printLanguage(language, true) end languages = utilsTable.unique(languages) local tabLabel = table.concat(languages, ", ") table.insert(tabData, {			label = tabLabel,			content = tabContent,		}) end return utilsLayout.tabs(tabData, {		tabOptions = {			collapse = true,			stretch = true,		}	}) end function h.printRow(img, term, languages, translations) local row = mw.html.create("tr") :node(mw.html.create("td")			:addClass("centered")			:wikitext(img .. " " .. 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, " ")) end row:node(cell):done end return row end

p.Templates = { ["Translation Page"] = { format = "block", purpose = "This template works in conjunction with its header to generate tables that display subjects (such as characters or items), images of those subjects, and their names in various languages.", usage = "The following code is to be placed in each section of a game's translation page. This template supports up to six tabs.", boilerplate = { separateRequiredParams = false, },		paramOrder = {"game", "filetype", "header", "tab", "subjects"}, repeatedGroup = { name = "tabs", params = {"tab"}, counts = {2, 3, 4, 5, 6}, },		params = { game = { required = true, type = "string", enum = Franchise.enum, desc = "The relevant game code.", },			filetype = { required = true, type = "string", desc = "The type of image displayed for each subject.", },			header = { required = true, type = "string", desc = "The type of subject being translated and displayed." },			tab = { required = false, type = "string", desc = "Depends on the number of languages defined in the Header template.", },			subjects = { required = true, type = "string", desc = "A list of all the subjects to be translated.", },		},	},	["Translation Header Basepage"] = { wip = true, format = "block", purpose = "To be used on translation base pages such as The Legend of Zelda Translations. Works in conjuction with Template:Translation Page to autogenerate translation pages.", paramOrder = {"game", "languagesGame", "languagesSupplementary"}, params = { game = { required = true, type = "string", enum = Franchise.enum, desc = "A game code." },			languagesGame = { required = true, type = "string", enum = utilsLanguage.enum, desc = "A comma-separated list of language codes indicating which languages the game was officially released in.", split = true, trim = true, nilIfEmpty = true, },			languagesSupplementary = { required = false, type = "string", enum = utilsLanguage.enum, desc = " A comma-separated list of language codes indicating languages in which there exists official supplementary material for the game, though the game itself was not released in that language. One or more references to the sources of supplementary material may be added as a separate argument. See examples below. ", split = true, trim = true, nilIfEmpty = true, },		},		boilerplate = { before = " ", after = " ", },		examples = { wrapLines = true, {				desc = "The use of nowiki tags around the references is needed for correct rendering.", args = { game = "BotW", languagesGame = "ja, zhS, zhT, nl, frC, frF, de, he, hu, it, ko, pl, ptP, ru, esS, esL", languagesSupplementary = "he, hu, pl, ptP", he = " ", hu = " ", },			},			{				game = "BotW", languagesGame = "ja, zhS, zhT, nl, frC, frF, de, he, hu, it, ko, pl, ptP, ru, esS, esL", languagesSupplementary = "he, hu, pl, ptP", notALanguage = " ", },			{				game = "notAGame", languagesGame = "ja", },			{				game = "BotW", languagesGame = "ja, frC, frF, notALanguage", },		},	},	["Translation Header Subpage"] = { wip = true, purpose = "To be used on translation subpages such as The Legend of Zelda Translations/Characters. Only works if Template:Translation Header Basepage is placed on the base page. Works in conjuction with Template:Translation Page to autogenerate translation pages.", params = { [1] = {				name = "game", required = true, type = "string", enum = Franchise.enum, desc = "A game code." }, 			[2] = {				name = "subpage", required = true, desc = "The name of the subpage. For The Legend of Zelda Translations/Characters, this would be .", type = "string", enum = utilsTable.map(subpages, "name"), }		}	} }

return p