Module:Spoken Wikipedia

local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local Date = require('Module:Date')._Date local lang = mw.language.new('en') local cfg = mw.loadData('Module:Spoken Wikipedia/configuration')

p = {}

local function wikiError(message) local ret = mw.html.create('div') :addClass(cfg.i18n.class.err) :wikitext(message) :done return tostring(ret) end

local function category(c, nocat) if nocat then return '' else return c	end end

local function formatPageText(page) if page then return ' ' .. page .. ' ' end if mw.title.getCurrentTitle.namespace == 0 then return cfg.i18n.this_article else return cfg.i18n.this_page end end

local function formatFileLength(filenames) local length = 0 for _, filename in ipairs(filenames) do		local fileTitle = mw.title.new(filename, 'Media') if fileTitle and fileTitle.file and fileTitle.file.exists then length = length + fileTitle.file.length end end

-- Add 30 to offset the rounding down local intervals = lang:getDurationIntervals(length + 30, { 'hours', 'minutes' }) local ret = string.format(		' %s %s',		intervals.minutes or 0,		intervals.minutes == 1 and cfg.i18n.minute or cfg.i18n.minutes	) if intervals.hours then ret = string.format(			' %s %s and %s',			intervals.hours,			intervals.hours == 1 and cfg.i18n.hour or cfg.i18n.hours,			ret		) end return ' ' .. ret .. ' ' end

local function formatHeader(filenames, page) local listento = mw.html.create('span') :addClass(cfg.i18n.class.listento) :wikitext(string.format( cfg.i18n.listento, formatPageText(page) ))		:done local file_length if #filenames > 1 then file_length = string.format(			cfg.i18n.n_files_length,			tostring(#filenames),			formatFileLength(filenames)		) else file_length = string.format(			cfg.i18n.one_file_length,			formatFileLength(filenames)		) end return mw.html.create('div') :addClass(cfg.i18n.class.header) :node(listento) :wikitext(file_length) :done end

local function formatIcon return mw.html.create('div') :addClass(cfg.i18n.class.icon) :wikitext(cfg.i18n.icon) :done end

local function formatFiles(filenames, nocat) if #filenames == 0 then return wikiError(cfg.i18n.err.no_filename) .. category(cfg.i18n.cat.no_filename, nocat) end -- TODO: the else branch really wants to be a mw.html  object rather than wikitext -- version of the same, so that we can style the numbers nicer local files = {} if #filenames == 1 then table.insert(files, string.format(cfg.i18n.one_file, filenames[1])) else for i, filename in ipairs(filenames) do			table.insert(files, string.format(cfg.i18n.n_files, filename, i)) end end

return mw.html.create('div') :addClass(cfg.i18n.class.files) :wikitext(table.concat(files)) :done :newline end

local function formatDateText(frame, dateArg, nocat) local d = dateArg and Date(dateArg) or nil return d and frame:expandTemplate{ title = 'Start date', args = { d.year, d.month, d.day, df='y'		} } or (wikiError(cfg.i18n.err.no_date) .. category(cfg.i18n.cat.no_date, nocat)) end

local function formatDisclaimer(frame, filenames, page, dateArg, nocat) local thisFileText = '' local disclaimer if #filenames == 1 then thisFileText = filenames[1] disclaimer = cfg.i18n.one_file_disclaimer else disclaimer = cfg.i18n.n_files_disclaimer end return mw.html.create('div') :addClass(cfg.i18n.class.disclaimer) :wikitext(string.format( disclaimer, thisFileText, formatPageText(page), formatDateText(frame, dateArg, nocat) ))		:done end

local function formatFooter return mw.html.create('div') :addClass(cfg.i18n.class.footer) :wikitext(cfg.i18n.footer) :done end

local function formatTopicon(frame, filenames) local wikilink if #filenames > 0 then wikilink = 'File:' .. filenames[1] else wikilink = cfg.i18n.topicon_multiwikilink end return frame:expandTemplate{ title = "Top icon", args = { imagename = 'Sound-icon.svg', wikilink = wikilink, text = 'Listen to this article', id = 'spoken-icon' }	} end

local function extractFilenames(args) local filenames = {} for key, rawValue in ipairs(args) do		local value = mw.text.trim(rawValue) if type(key) == "number" and value ~= '' then table.insert(filenames, value) end end return filenames end

local function sidebox(nodes) root = mw.html.create('div') :addClass(cfg.i18n.class.box) for _, node in ipairs(nodes) do		root:node(node) end return root end

function main(frame) local args = getArgs(frame)

-- Mandatory parameters local filenames = extractFilenames(args) local dateArg = args['date'] -- Optional parameters local page = args['page'] local nocat = yesno(args['nocat'], false) or false

local root = sidebox({		formatHeader(filenames, page),		formatFiles(filenames, nocat),		formatIcon,		formatDisclaimer(frame, filenames, page, dateArg, nocat),		formatFooter	})

if mw.title.getCurrentTitle.namespace == 0 then root:wikitext(formatTopicon(frame, filenames)) root:wikitext(category(cfg.i18n.cat.articles, nocat)) end

return frame:extensionTag{ name = 'templatestyles', args = { src = cfg.templatestyles } } .. tostring(root) end

p.main = main

return p