Module:TrainingPages
Appearance
The master version of this module comes from English Wikipedia: w:Module:TrainingPages.
However here on multilingual Meta, it is being fixed to handle translations using the Translate extension:
- This code requires template expansion when parsing the index list pages (containing transclusions of TNTN (because "Special:MyLanguage/" prefixes are still not supported)
- Wikilinks that are present in noinclude sections of the index page will no longer be indexed for navigation (these links are also hidden when trascluding index pages in the main training page); but are accessible when viewing the index pages directly (from the link present under the topic name in the training page header)
- It fixes another issue with the "/en" suffix which may appear in links once a training page has been prepared for translation (not all of them are translated at once, this avoids breaking existing trainings or new trainings in preparation that are still not ready for translation).
The module will then now work with or without translations (but most trainings in Meta or Commons should be translated). A localized Wiki may decide to only import one translated version and make it the default by dropping language code suffixes, or by renaming them after the import (leaving redirects which may break things)
The current code assumes English is the default language of the current wiki (true on Meta-Wiki) but is easy to fix if you import this module on a non-English localized wiki.
--[[
The purpose of this module is to take a list of linked page,
and use it to determine the next and previous page in the list
as well as the total number of pages.
--]]
local p = {}
function anonymize(name)
return mw.ustring.gsub(name, "^" .. mw.site.siteName, "Project") or name
end
function out(name)
return mw.ustring.gsub(name, "^Project", mw.site.siteName) or name
end
function keyize(pagename)
-- there was a complaint about "_" breaking things. Do all lookups with _ in place of any space.
-- also spaces in the index file (non-module) were causing trouble
pagename = mw.text.trim(pagename)
pagename = mw.ustring.gsub(pagename, " ", "_")
pagename = mw.uri.decode(pagename)
pagename = anonymize(pagename)
return pagename
end
function p.main(frame, displacement, varstoreturn)
local parent = frame.getParent(frame)
local currentpage, indexmodule, defaultpage, noerr, anonymizereturn
local returnpage, currentpagenumber, totalpages
---- args in the #invoke itself trump args in the parent frame
currentpage = frame.args.page and mw.text.trim(frame.args.page)
defaultpage = frame.args.defaultpage and mw.text.trim(frame.args.defaultpage)
indexmodule = frame.args.index and mw.text.trim(frame.args.index)
displacement = displacement or frame.args.displacement -- can be passed from the other function names at the end
noerr = frame.args.noerr -- used as boolean
anonymizereturn = frame.args.anonymize -- used as boolean
---- args in the parent frame come next
if parent then
currentpage = currentpage or (parent.args.page and mw.text.trim(parent.args.page))
indexmodule = indexmodule or (parent.args.index and mw.text.trim(parent.args.index)) -- index is a module: return {'page1', 'page2', ...} or a page containing wikilinks
defaultpage = defaultpage or (parent.args.defaultpage and mw.text.trim(parent.args.defaultpage))
noerr = noerr or parent.args.noerr
anonymizereturn = anonymizereturn or parent.args.anonymize
end
-- Default values if parameters aren't provided.
defaultpage = defaultpage or "" -- Don't know where to send people by default.
if not(indexmodule) then
returnpage = "[[Module:TrainingPages]] error: no index parameter specified"
if noerr then returnpage = "" end
if not(varstoreturn) then return returnpage else return returnpage, nil, nil, true end
end
if not(currentpage) then
local pp = mw.title.getCurrentTitle()
if not pp then -- This shouldn't happen anyway, I think...
returnpage = "[[Module:TrainingPages]] error: failed to access getCurrentTitle"
if noerr then returnpage = "" end
if not(varstoreturn) then return returnpage else return returnpage, nil, nil, true end
end
currentpage = pp.fullText
end
local index = {}
if mw.ustring.sub(indexmodule, 1, 6) == "Module" then
-- Get a table of the pages in order from indexmodule.
index = mw.loadData(indexmodule)
else pp = mw.title.new(indexmodule)
-- Get a table of the pages in order from a page containing a set of wikilinks.
if not(pp) or pp.id == 0 then
returnpage = "[[Module:TrainingPages]] error (''index'' parameter): failed to access mw.title.new(\"" .. tostring(indexmodule) .. "\") to load the index file"
if noerr then returnpage = "" end
if not(varstoreturn) then return returnpage else return returnpage, nil, nil, true end
end
--[==[
Note that this still does not work with wikilinks going to the "Special:"
namespace, notably "Special:MyLanguage/<namespace>:<pagename>".
A workaround is to use [[{{TNTN|<namespace>:<pagename>}}|...]] in listed
links. So each wikilink target containing transclusions must be
expanded.
The links which may be present in noinclude parts of the index page are
now also excluded from the navigation (and not counted) by this expansion
(this hides links only accessible when viewing the index page directly).
]==]
local textindex = frame:expandTemplate{title = ':' .. pp.prefixedText} -- was = pp.getContent(pp)
if not textindex then
returnpage = "[[Module:TrainingPages]] error (''index'' parameter): failed to access mw.title.new(\"" .. indexmodule .. "\"):getContent() to load the index data"
if noerr then returnpage = "" end
if not(varstoreturn) then return returnpage else return returnpage, nil, nil, true end
end
index = {}
prowl = mw.ustring.gmatch(textindex, "%[%[(.-)[%]|]") -- first half of any wikilink
while true do
link = prowl() -- iterate to next match
if not(link) then break end -- no more match
link = mw.text.trim(link)
if link ~= "" then table.insert(index, link) end
end
end
displacement = displacement or 0 -- assume a null parameter is just display the same
--[[
Set up the reverse lookup in lookup.
It would be faster to set this up in the indexmodule,
but we don't want inconsistencies from user input!
]]
local lookup = {}
local i = 1
while true do
local j = index[i]
if not j then break end
lookup[keyize(j)] = i -- lookup["namespace:pagename"] => page number
i = i + 1
end
--- get the page to return
totalpages = #index
if tonumber(currentpage) then
currentpagenumber = tonumber(currentpage)
returnpage = index[currentpagenumber + displacement] or defaultpage
elseif (lookup[keyize(currentpage)]) then
currentpagenumber = lookup[keyize(currentpage)]
returnpage = index[currentpagenumber + displacement] or defaultpage
elseif (lookup[keyize(currentpage .. "/en")]) then
--[==[
English may exist both as base of translation and as a translated subpage
The index page will expand to one or the other, depending if the page
was prepared for translation or not.
This is not necessary for other translations using language suffixes
(but their suffixe is not variable. This code assumes that there will
never be any page named like "namespace:pagename/languagecode/en")
--]==]
currentpagenumber = lookup[keyize(currentpage .. "/en")]
returnpage = index[currentpagenumber + displacement] or defaultpage
else
returnpage = defaultpage
end
if anonymizereturn then
returnpage = anonymize(returnpage)
else
returnpage = out(returnpage)
end
if returnpage then returnpage = mw.text.trim(returnpage) end
returnpage = tostring(returnpage)
if not(varstoreturn) then return returnpage else return returnpage, currentpagenumber, totalpages end
end
--[[
Return the next page in the index.
* Used like this if on the current page that is part of the index:
{{#invoke:TrainingPages|next_page
| index = Project:Training/For students/Editing module index
}}
* Used like this to find the next page after a specified page:
{{#invoke:TrainingPages|next_page
| index = Project:Training/For students/Editing module index
| currentpage = Project:Training/For students/My sandbox
}}
]]
function p.next_page(frame)
local returnpage, pagenumber, totalpages, errcode = p.main(frame, 1, true)
return returnpage
end
-- Abbreviated alias.
p.next = p.next_page
-- Same as above, but returns the previous page.
function p.last_page(frame)
local returnpage, pagenumber, totalpages, errcode = p.main(frame, -1, true)
return returnpage
end
-- Abbreviated alias.
p.last = p.last_page
-- Return the current page number as ordered in the index.
function p.page_number(frame)
local returnpage, pagenumber, totalpages, errcode = p.main(frame, 0, true)
if errcode then return returnpage else return pagenumber end
end
-- Abbreviated alias.
p.page = p.page_number
-- Return the total number of pages listed in the index.
function p.total_pages(frame)
local returnpage, pagenumber, totalpages, errcode = p.main(frame, 0, true)
if errcode then return returnpage else return totalpages end
end
-- Abbreviated alias.
p.total = p.total_pages
return p