Module:Spoken Wikipedia
From KYNNpedia
Documentation for this module may be created at Module:Spoken Wikipedia/doc
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 '<span class="fn">[[' .. page .. ']]</span>' 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( '<span class="min">%s</span> %s', intervals.minutes or 0, intervals.minutes == 1 and cfg.i18n.minute or cfg.i18n.minutes ) if intervals.hours then ret = string.format( '<span class="h">%s</span> %s and %s', intervals.hours, intervals.hours == 1 and cfg.i18n.hour or cfg.i18n.hours, ret ) end return '<span class="duration">' .. ret .. '</span>' 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 <ol> 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