<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.chaosvermittlung.de/index.php?action=history&amp;feed=atom&amp;title=Module%3ATemplateBox</id>
	<title>Module:TemplateBox - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.chaosvermittlung.de/index.php?action=history&amp;feed=atom&amp;title=Module%3ATemplateBox"/>
	<link rel="alternate" type="text/html" href="https://wiki.chaosvermittlung.de/index.php?title=Module:TemplateBox&amp;action=history"/>
	<updated>2026-04-11T23:43:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.chaosvermittlung.de/index.php?title=Module:TemplateBox&amp;diff=406&amp;oldid=prev</id>
		<title>PhilmacFLy: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://wiki.chaosvermittlung.de/index.php?title=Module:TemplateBox&amp;diff=406&amp;oldid=prev"/>
		<updated>2017-01-15T15:29:13Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[&lt;br /&gt;
    @exports&lt;br /&gt;
        usagesample( frame )&lt;br /&gt;
        argcount( frame )&lt;br /&gt;
        args2table( args, onGetKey, forCustom )&lt;br /&gt;
        paramtable( frame )&lt;br /&gt;
        description( frame )&lt;br /&gt;
        templatedata( frame )&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Helper function, not exposed&lt;br /&gt;
function tobool(st)&lt;br /&gt;
    if type( st ) == &amp;#039;string&amp;#039; then&lt;br /&gt;
        return st == &amp;#039;true&amp;#039;&lt;br /&gt;
    else&lt;br /&gt;
        return not not st&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Required to determine in which languages the interface texts without langcode are&lt;br /&gt;
local contentLangcode = mw.language.getContentLanguage():getCode()&lt;br /&gt;
-- Forward declaration&lt;br /&gt;
local msg, langIsInit, userLang&lt;br /&gt;
local messagePrefix = &amp;quot;templatedata-doc-&amp;quot;&lt;br /&gt;
local i18n = {}&lt;br /&gt;
i18n[&amp;#039;params&amp;#039;] = &amp;quot;Template parameters&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-name&amp;#039;] = &amp;quot;Parameter&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-desc&amp;#039;] = &amp;quot;Description&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-type&amp;#039;] = &amp;quot;Type&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-default&amp;#039;] = &amp;quot;Default&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status&amp;#039;] = &amp;quot;Status&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-optional&amp;#039;] = &amp;quot;optional&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-required&amp;#039;] = &amp;quot;required&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-suggested&amp;#039;] = &amp;quot;suggested&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-status-deprecated&amp;#039;] = &amp;quot;deprecated&amp;quot;&lt;br /&gt;
i18n[&amp;#039;param-default-empty&amp;#039;] = &amp;quot;empty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function initLangModule()&lt;br /&gt;
    if langIsInit then&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    --! From [[:de:Modul:Expr]]; by [[:de:User:PerfektesChaos]]; &lt;br /&gt;
    --! Derivative work: Rillke&lt;br /&gt;
    userLang = mw.getCurrentFrame():preprocess( &amp;#039;{{int:lang}}&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    msg = function( key )&lt;br /&gt;
        -- Retrieve localized message string in content language&lt;br /&gt;
        -- Precondition:&lt;br /&gt;
        --     key  -- string; message ID&lt;br /&gt;
        -- Postcondition:&lt;br /&gt;
        --     Return some message string&lt;br /&gt;
        -- Uses:&lt;br /&gt;
        --     &amp;gt;  messagePrefix&lt;br /&gt;
        --     &amp;gt;  i18n&lt;br /&gt;
        --     &amp;gt;  userLang&lt;br /&gt;
        --     mw.message.new()&lt;br /&gt;
        local m = mw.message.new( messagePrefix .. key )&lt;br /&gt;
        local r = false&lt;br /&gt;
        if m:isBlank() then&lt;br /&gt;
            r = i18n[ key ]&lt;br /&gt;
        else&lt;br /&gt;
            m:inLanguage( userLang )&lt;br /&gt;
            r = m:plain()&lt;br /&gt;
        end&lt;br /&gt;
        if not r then&lt;br /&gt;
            r = &amp;#039;(((&amp;#039;.. key .. &amp;#039;)))&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        return r&lt;br /&gt;
    end -- msg()&lt;br /&gt;
    &lt;br /&gt;
    langIsInit = true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- A &amp;quot;hash&amp;quot; / table of everything TemplateData takes&lt;br /&gt;
-- to ease maintenance.&lt;br /&gt;
&lt;br /&gt;
-- The type is automatically determined if t is omitted.&lt;br /&gt;
-- If the type does not match or can&amp;#039;t be converted, an error will be thrown!&lt;br /&gt;
-- Available types (LUA-Types with exceptions): &lt;br /&gt;
--      InterfaceText, boolean, number, selection, table, string&lt;br /&gt;
-- selection*: - requires a selection-string of pipe-separated possibilities to be supplied&lt;br /&gt;
-- InterfaceText*: A free-form string (no wikitext) in the content-language of the wiki, or, &lt;br /&gt;
-- an object containing those strings keyed by language code.&lt;br /&gt;
local paraminfoTemplate = {&lt;br /&gt;
    description = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;desc&amp;#039;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
local paraminfoTLParams = {&lt;br /&gt;
    label = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    required = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local req = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;required&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or req )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    suggested = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local sugg = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;suggested&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or sugg )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    description = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;InterfaceText&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;d&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    deprecated = {&lt;br /&gt;
        default = false,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local depr = (pargs[number .. &amp;#039;stat&amp;#039;] == &amp;#039;deprecated&amp;#039;)&lt;br /&gt;
            return tobool( paramVal or depr )&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    aliases = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;table&amp;#039;,&lt;br /&gt;
        extract = function(pargs, number, paramVal)&lt;br /&gt;
            local key = number .. &amp;#039;aliases&amp;#039;&lt;br /&gt;
            local tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
            local aliases = pargs[tdkey] or pargs[key]&lt;br /&gt;
            if aliases then&lt;br /&gt;
                aliases = mw.text.split( aliases, &amp;#039;/&amp;#039;, true )&lt;br /&gt;
            end&lt;br /&gt;
            return aliases&lt;br /&gt;
        end&lt;br /&gt;
    },&lt;br /&gt;
    default = {&lt;br /&gt;
        default = &amp;#039;&amp;#039;,&lt;br /&gt;
        t = &amp;#039;string&amp;#039;,&lt;br /&gt;
        alias = &amp;#039;def&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    type = {&lt;br /&gt;
        default = &amp;#039;unknown&amp;#039;,&lt;br /&gt;
        t = &amp;#039;selection&amp;#039;,&lt;br /&gt;
        selection = &amp;#039;unknown|number|string|string/wiki-user-name|string/wiki-page-name|string/line|line|wiki-page-name|wiki-file-name|wiki-user-name|content|unbalanced-wikitext&amp;#039;&lt;br /&gt;
    },&lt;br /&gt;
    inherits = {&lt;br /&gt;
        default = nil,&lt;br /&gt;
        t = &amp;#039;string&amp;#039;&lt;br /&gt;
    }&lt;br /&gt;
    -- sets will be treated differently because we can only have a plain structure in wikitext&lt;br /&gt;
}&lt;br /&gt;
local tableLayout = {&lt;br /&gt;
    {&lt;br /&gt;
        col = &amp;#039;param-name&amp;#039;,&lt;br /&gt;
        width = &amp;#039;15%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local alias, param = &amp;#039;&amp;#039;, item.key&lt;br /&gt;
            local aliasTT = &amp;#039;&amp;lt;tt style=&amp;quot;color:#777; border:1px solid #6A6A6A&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
            param = &amp;#039;&amp;lt;code&amp;gt;&amp;#039; .. param .. &amp;#039;&amp;lt;/code&amp;gt;&amp;#039;&lt;br /&gt;
            if item.aliases then&lt;br /&gt;
                alias = aliasTT .. table.concat(item.aliases, &amp;#039;&amp;lt;/tt&amp;gt;&amp;lt;br /&amp;gt;&amp;#039; .. aliasTT) .. &amp;#039;&amp;lt;/tt&amp;gt;&amp;#039;&lt;br /&gt;
                param = table.concat({param, &amp;#039;&amp;lt;br /&amp;gt;&amp;lt;div&amp;gt;&amp;#039;, alias, &amp;#039;&amp;lt;/div&amp;gt;&amp;#039;})&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(param, colspan)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-desc&amp;#039;,&lt;br /&gt;
        cols = 2,&lt;br /&gt;
        width = &amp;#039;65%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local label = item.label or &amp;#039;&amp;#039;&lt;br /&gt;
            label = monolingual(label)&lt;br /&gt;
            local labelLen = #label&lt;br /&gt;
            local colspan = 2 - labelLen&lt;br /&gt;
        &lt;br /&gt;
            if labelLen &amp;gt; 0 then&lt;br /&gt;
                renderCell(label)&lt;br /&gt;
            end&lt;br /&gt;
        &lt;br /&gt;
            renderCell(monolingual(item.description), colspan)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-default&amp;#039;,&lt;br /&gt;
        width = &amp;#039;10%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local def = monolingual(item.default) or &amp;#039;&amp;#039;&lt;br /&gt;
            if #def == 0 then&lt;br /&gt;
                def = &amp;#039;&amp;lt;span class=&amp;quot;mw-templatedata-doc-muted&amp;quot; style=&amp;quot;color:#777; font-variant:small-caps&amp;quot;&amp;gt;&amp;#039; .. msg(&amp;#039;param-default-empty&amp;#039;) .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(def)&lt;br /&gt;
        end&lt;br /&gt;
    },  {&lt;br /&gt;
        col = &amp;#039;param-status&amp;#039;,&lt;br /&gt;
        width = &amp;#039;10%&amp;#039;,&lt;br /&gt;
        extract = function(item, renderCell, monolingual)&lt;br /&gt;
            local stat = msg(&amp;#039;param-status-optional&amp;#039;)&lt;br /&gt;
            if item.required then&lt;br /&gt;
                stat = &amp;#039;&amp;lt;b&amp;gt;&amp;#039; .. msg(&amp;#039;param-status-required&amp;#039;) .. &amp;#039;&amp;lt;/b&amp;gt;&amp;#039;&lt;br /&gt;
            elseif item.deprecated then&lt;br /&gt;
                stat = msg(&amp;#039;param-status-deprecated&amp;#039;)&lt;br /&gt;
            elseif item.suggested then&lt;br /&gt;
                stat = msg(&amp;#039;param-status-suggested&amp;#039;)&lt;br /&gt;
            end&lt;br /&gt;
            renderCell(stat)&lt;br /&gt;
        end&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Initialize param info&lt;br /&gt;
-- Avoids having to add redundant information to the preceding tables&lt;br /&gt;
function init( which )&lt;br /&gt;
    local setDefault = function(v)&lt;br /&gt;
        if v.t == nil and v.default ~= nil then&lt;br /&gt;
            v.t = type( v.default )&lt;br /&gt;
        end&lt;br /&gt;
        if v.selection then&lt;br /&gt;
            v.selection = &amp;#039;|&amp;#039; .. v.selection .. &amp;#039;|&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    for a, v in pairs( which ) do&lt;br /&gt;
        setDefault(v)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
function initParamTables()&lt;br /&gt;
    init( paraminfoTemplate )&lt;br /&gt;
    init( paraminfoTLParams )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
-------------------- USAGE PART ----------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
function p.argcount( frame )&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local ac = 0&lt;br /&gt;
    for i, arg in pairs( pargs ) do&lt;br /&gt;
        if (&amp;#039;number&amp;#039; == type(i)) then&lt;br /&gt;
            ac = ac + 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ac&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.usagesample( frame )&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local multiline = (pargs.lines == &amp;#039;multi&amp;#039; or pargs.print == &amp;#039;multi&amp;#039; or pargs.print == &amp;#039;infobox&amp;#039;)&lt;br /&gt;
    local align = pargs.print == &amp;#039;infobox&amp;#039;&lt;br /&gt;
    if not pargs.lines and not pargs.print and pargs.type == &amp;#039;infobox&amp;#039; then&lt;br /&gt;
        multiline = true&lt;br /&gt;
        align = true&lt;br /&gt;
    end&lt;br /&gt;
    local sepStart = &amp;#039; |&amp;#039;&lt;br /&gt;
    local sepEnd = multiline  and &amp;#039;\n&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local sep = sepEnd&lt;br /&gt;
    local subst = #(pargs.mustbesubst or &amp;#039;&amp;#039;) &amp;gt; 0 and &amp;#039;subst:&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local beforeEqual = multiline  and &amp;#039; &amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local equal = beforeEqual .. &amp;#039;= &amp;#039;&lt;br /&gt;
    local templateTitle = pargs.name or &amp;#039;&amp;#039;&lt;br /&gt;
    local args, argName, result = {}&lt;br /&gt;
    local maxArgLen, eachArg = 0&lt;br /&gt;
    sep = sep .. sepStart&lt;br /&gt;
    &lt;br /&gt;
    local comapareLegacyVal = function(val)&lt;br /&gt;
        return val == &amp;#039;optional-&amp;#039; or val == &amp;#039;deprecated&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    local shouldShow = function(i)&lt;br /&gt;
        if comapareLegacyVal(pargs[i .. &amp;#039;stat&amp;#039;]) or&lt;br /&gt;
            comapareLegacyVal(pargs[i .. &amp;#039;stat-td&amp;#039;]) or&lt;br /&gt;
            pargs[i .. &amp;#039;deprecated&amp;#039;] == true then &lt;br /&gt;
                return false&lt;br /&gt;
            end&lt;br /&gt;
        return true&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    eachArg = function(cb)&lt;br /&gt;
        for i, arg in pairs( pargs ) do&lt;br /&gt;
            if (&amp;#039;number&amp;#039; == type(i)) then&lt;br /&gt;
                argName = mw.text.trim( arg or &amp;#039;&amp;#039; )&lt;br /&gt;
                if #argName == 0 then&lt;br /&gt;
                    argName = tostring(i)&lt;br /&gt;
                end&lt;br /&gt;
                &lt;br /&gt;
                if shouldShow(i) then&lt;br /&gt;
                    cb(argName)&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if align then&lt;br /&gt;
        eachArg(function( arg )&lt;br /&gt;
            local argL = #arg&lt;br /&gt;
            maxArgLen = argL &amp;gt; maxArgLen and argL or maxArgLen&lt;br /&gt;
        end)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    eachArg(function( arg )&lt;br /&gt;
        local space = &amp;#039;&amp;#039;&lt;br /&gt;
        if align then&lt;br /&gt;
            space = (&amp;#039;&amp;amp;nbsp;&amp;#039;):rep(maxArgLen - #arg)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert( args, argName .. space .. equal )&lt;br /&gt;
    end)&lt;br /&gt;
    &lt;br /&gt;
    if #args == 0 then&lt;br /&gt;
        sep = &amp;#039;&amp;#039;&lt;br /&gt;
        sepEnd = &amp;#039;&amp;#039;&lt;br /&gt;
        sepStart = &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    if #templateTitle == 0 then&lt;br /&gt;
        templateTitle = mw.title.getCurrentTitle().text&lt;br /&gt;
    end&lt;br /&gt;
    result = table.concat( args, sep )&lt;br /&gt;
    result = table.concat({ mw.text.nowiki(&amp;#039;{{&amp;#039;), subst, templateTitle, sep, result, sepEnd, &amp;#039;}}&amp;#039; })&lt;br /&gt;
    if multiline then&lt;br /&gt;
        -- Preserve whitespace in front of new lines&lt;br /&gt;
        result = frame:callParserFunction{ name = &amp;#039;#tag&amp;#039;, args = { &amp;#039;poem&amp;#039;, result } }&lt;br /&gt;
    end&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
------------------- GENERAL PART ---------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
function p.args2table(args, onGetKey, consumer)&lt;br /&gt;
    initParamTables()&lt;br /&gt;
    &lt;br /&gt;
    local sets, asParamArray, laxtype, processParams, processDesc&lt;br /&gt;
    if &amp;#039;paramtable&amp;#039; == consumer then&lt;br /&gt;
        asParamArray = true&lt;br /&gt;
        processParams = true&lt;br /&gt;
        laxtype = true&lt;br /&gt;
    elseif &amp;#039;templatedata&amp;#039; == consumer then&lt;br /&gt;
        sets = true&lt;br /&gt;
        processParams = true&lt;br /&gt;
        processDesc = true&lt;br /&gt;
        unstrip = true&lt;br /&gt;
    elseif &amp;#039;description&amp;#039; == consumer then&lt;br /&gt;
        processDesc = true&lt;br /&gt;
        laxtype = true&lt;br /&gt;
    end&lt;br /&gt;
    -- All kind of strange stuff with the arguments is done, so play safe and make a copy&lt;br /&gt;
    local pargs = mw.clone( args )&lt;br /&gt;
    -- Array-like table containing all parameter-numbers that were passed&lt;br /&gt;
    local templateArgs = {}&lt;br /&gt;
    -- Arguments that are localized (i.e. the user passed  1desc-en=English description of parameter one)&lt;br /&gt;
    local i18nTemplateArgs = {}&lt;br /&gt;
    -- Ensure that tables end up as array/object (esp. when they are empty)&lt;br /&gt;
    local tdata = {description=&amp;quot;&amp;quot;, params={}, sets={}}&lt;br /&gt;
    local isArray  = { __tostring = function() return &amp;quot;JSON array&amp;quot;  end }    isArray.__index  = isArray&lt;br /&gt;
    setmetatable(tdata.sets, isArray)&lt;br /&gt;
    onGetKey = onGetKey or function( prefix, alias, param )&lt;br /&gt;
        local key, key2, tdkey, tdkey2&lt;br /&gt;
        key = prefix .. (alias or param)&lt;br /&gt;
        key2 = prefix .. param&lt;br /&gt;
        tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
        tdkey2 = key2 .. &amp;#039;-td&amp;#039;&lt;br /&gt;
        return tdkey, tdkey2, key, key2&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local extractData = function( pi, number )&lt;br /&gt;
        local prefix = number or &amp;#039;&amp;#039;&lt;br /&gt;
        local ppv, paramVal&lt;br /&gt;
        local key1, key2, key3, key4&lt;br /&gt;
        local paramKey, paramTable, processKey&lt;br /&gt;
        if number then&lt;br /&gt;
            paramKey = mw.text.trim( pargs[number] )&lt;br /&gt;
            if &amp;#039;&amp;#039; == paramKey then&lt;br /&gt;
                paramKey = tostring( number )&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            paramTable = {}&lt;br /&gt;
            if asParamArray then&lt;br /&gt;
                paramTable.key = paramKey&lt;br /&gt;
                table.insert(tdata.params, paramTable)&lt;br /&gt;
            else&lt;br /&gt;
                tdata.params[paramKey] = paramTable&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        for p, info in pairs( pi ) do&lt;br /&gt;
            key1, key2, key3, key4 = onGetKey(prefix, info.alias, p)&lt;br /&gt;
            paramVal = nil&lt;br /&gt;
            &lt;br /&gt;
            processKey = function(key)&lt;br /&gt;
                if paramVal ~= nil then return end&lt;br /&gt;
                local plain, multilingual = pargs[key], i18nTemplateArgs[key]&lt;br /&gt;
                paramVal = multilingual or plain&lt;br /&gt;
            end&lt;br /&gt;
            processKey( key1 )&lt;br /&gt;
            processKey( key2 )&lt;br /&gt;
            processKey( key3 )&lt;br /&gt;
            processKey( key4 )&lt;br /&gt;
            &lt;br /&gt;
            -- Ensure presence of entry in content language&lt;br /&gt;
            ppv = pargs[key1] or pargs[key2] or pargs[key3] or pargs[key4] or info.default&lt;br /&gt;
            if &amp;#039;table&amp;#039; == type( paramVal ) then&lt;br /&gt;
                if (nil == paramVal[contentLangcode]) then&lt;br /&gt;
                    paramVal[contentLangcode] = ppv&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                paramVal = ppv&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            if &amp;#039;function&amp;#039; == type( info.extract ) then&lt;br /&gt;
                if &amp;#039;string&amp;#039; == type( paramVal ) then&lt;br /&gt;
                    paramVal = mw.text.trim( paramVal )&lt;br /&gt;
                    if &amp;#039;&amp;#039; == paramVal then&lt;br /&gt;
                        paramVal = nil&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
                paramVal = info.extract( pargs, number, paramVal )&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            local insertValue = function()&lt;br /&gt;
                if number then&lt;br /&gt;
                    paramTable[p] = paramVal&lt;br /&gt;
                else&lt;br /&gt;
                    tdata[p] = paramVal&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            if info.selection then&lt;br /&gt;
                if info.selection:find( paramVal, 1, true ) then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                end&lt;br /&gt;
            elseif &amp;#039;InterfaceText&amp;#039; == info.t then&lt;br /&gt;
                if ({ table=1, string=1 })[type( paramVal )] then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                local paramType = type( paramVal )&lt;br /&gt;
                if &amp;#039;string&amp;#039; == info.t and &amp;#039;string&amp;#039; == paramType then&lt;br /&gt;
                    paramVal = mw.text.trim( paramVal )&lt;br /&gt;
                    if &amp;#039;&amp;#039; ~= paramVal then&lt;br /&gt;
                        insertValue()&lt;br /&gt;
                    end&lt;br /&gt;
                elseif &amp;#039;boolean&amp;#039; == info.t then&lt;br /&gt;
                    paramVal = tobool(paramVal)&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif &amp;#039;number&amp;#039; == info.t then&lt;br /&gt;
                    paramVal = tonumber(paramVal)&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif paramType == info.t then&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                elseif paramType == &amp;#039;nil&amp;#039; then&lt;br /&gt;
                    -- Do nothing&lt;br /&gt;
                elseif not laxtype and &amp;#039;string&amp;#039; == info.t and &amp;#039;table&amp;#039; == paramType then&lt;br /&gt;
                    -- Convert multilingual object into content language string&lt;br /&gt;
                    paramVal = paramVal[contentLangcode]&lt;br /&gt;
                    insertValue()&lt;br /&gt;
                else&lt;br /&gt;
                    if laxtype then&lt;br /&gt;
                        insertValue()&lt;br /&gt;
                    else&lt;br /&gt;
                        error( p .. &amp;#039;: Is of type &amp;#039; ..  paramType .. &amp;#039; but should be of type &amp;#039; .. (info.t or &amp;#039;unknown&amp;#039;), 1 )&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- Now, treat sets&lt;br /&gt;
        if sets then&lt;br /&gt;
            key1 = prefix .. &amp;#039;set-td&amp;#039;&lt;br /&gt;
            key2 = prefix .. &amp;#039;set&amp;#039;&lt;br /&gt;
            paramVal = pargs[key1] or pargs[key2]&lt;br /&gt;
            if paramVal then&lt;br /&gt;
                local found = false&lt;br /&gt;
                for i, s in ipairs( tdata.sets ) do&lt;br /&gt;
                    if s.label == paramVal then&lt;br /&gt;
                        table.insert( s.params, p )&lt;br /&gt;
                        found = true&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
                if not found then&lt;br /&gt;
                    table.insert( tdata.sets, {&lt;br /&gt;
                        label = paramVal, &lt;br /&gt;
                        params = { p }&lt;br /&gt;
                    } )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- First, analyse the structure of the provided arguments&lt;br /&gt;
    for a, v in pairs( pargs ) do&lt;br /&gt;
        if unstrip then&lt;br /&gt;
            v = mw.text.unstrip( v )&lt;br /&gt;
            pargs[a] = v&lt;br /&gt;
        end&lt;br /&gt;
        if type( a ) == &amp;#039;number&amp;#039; then&lt;br /&gt;
            table.insert( templateArgs, a )&lt;br /&gt;
        else&lt;br /&gt;
            local argSplit = mw.text.split( a, &amp;#039;-&amp;#039;, true )&lt;br /&gt;
            local argUnitl = {}&lt;br /&gt;
            local argAfter = {}&lt;br /&gt;
            local isTDArg = false&lt;br /&gt;
            local containsTD = a:find( &amp;#039;-td&amp;#039;, 1, true )&lt;br /&gt;
            for i, part in ipairs( argSplit ) do&lt;br /&gt;
                if isTDArg or (containsTD == nil and i &amp;gt; 1) then&lt;br /&gt;
                    -- This is likely a language version&lt;br /&gt;
                    table.insert( argAfter, part )&lt;br /&gt;
                else&lt;br /&gt;
                    table.insert( argUnitl, part )&lt;br /&gt;
                end&lt;br /&gt;
                if part == &amp;#039;td&amp;#039; then&lt;br /&gt;
                    isTDArg = true&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            if #argAfter &amp;gt; 0 then&lt;br /&gt;
                argUnitl = table.concat( argUnitl, &amp;#039;-&amp;#039; )&lt;br /&gt;
                argAfter = table.concat( argAfter, &amp;#039;-&amp;#039; )&lt;br /&gt;
                i18nTemplateArgs[argUnitl] = i18nTemplateArgs[argUnitl] or {}&lt;br /&gt;
                i18nTemplateArgs[argUnitl][argAfter] = v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Then, start building the actual template&lt;br /&gt;
    if processDesc then&lt;br /&gt;
        extractData( paraminfoTemplate )&lt;br /&gt;
    end&lt;br /&gt;
    if processParams then&lt;br /&gt;
        for i, number in pairs( templateArgs ) do&lt;br /&gt;
            extractData( paraminfoTLParams, number )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return tdata, #templateArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
------------ CUSTOM PARAMETER TABLE PART -------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- A custom key-pref-function&lt;br /&gt;
local customOnGetKey = function( prefix, alias, param )&lt;br /&gt;
    local key, key2, tdkey, tdkey2&lt;br /&gt;
    key = prefix .. (alias or param)&lt;br /&gt;
    key2 = prefix .. param&lt;br /&gt;
    tdkey = key .. &amp;#039;-td&amp;#039;&lt;br /&gt;
    tdkey2 = key2 .. &amp;#039;-td&amp;#039;&lt;br /&gt;
    return key2, key, tdkey2, tdkey&lt;br /&gt;
end&lt;br /&gt;
local toUserLanguage = function(input, frame)&lt;br /&gt;
    if type(input) == &amp;#039;table&amp;#039; then&lt;br /&gt;
        input = frame:expandTemplate{ title = &amp;#039;LangSwitch&amp;#039;, args = input }&lt;br /&gt;
    end&lt;br /&gt;
    return input&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.description(frame)&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local tdata, paramLen&lt;br /&gt;
    local monolingual = function(input)&lt;br /&gt;
        return toUserLanguage(input, frame)&lt;br /&gt;
    end&lt;br /&gt;
    tdata, paramLen = p.args2table(pargs, customOnGetKey, &amp;#039;description&amp;#039;)&lt;br /&gt;
    return monolingual(tdata.description)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.paramtable(frame)&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local tdata, paramLen&lt;br /&gt;
    &lt;br /&gt;
    if &amp;#039;only&amp;#039; == pargs.useTemplateData then&lt;br /&gt;
        return &amp;#039;param table - output suppressed&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Initialize the language-related stuff&lt;br /&gt;
    initLangModule()&lt;br /&gt;
    local monolingual = function(input)&lt;br /&gt;
        return toUserLanguage(input, frame)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    tdata, paramLen = p.args2table(pargs, customOnGetKey, &amp;#039;paramtable&amp;#039;)&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    if 0 == paramLen then&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local row, rows = &amp;#039;&amp;#039;, {}&lt;br /&gt;
    local renderCell = function(wikitext, colspan)&lt;br /&gt;
        local colspan, oTd = colspan or 1, &amp;#039;&amp;lt;td&amp;gt;&amp;#039;&lt;br /&gt;
        if colspan &amp;gt; 1 then&lt;br /&gt;
            oTd = &amp;#039;&amp;lt;td colspan=&amp;quot;&amp;#039; .. colspan .. &amp;#039;&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        row = table.concat({ row, oTd, wikitext, &amp;#039;&amp;lt;/td&amp;gt;&amp;#039; })&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Create the header&lt;br /&gt;
    for i, field in ipairs( tableLayout ) do&lt;br /&gt;
        local style = &amp;#039; style=&amp;quot;width:&amp;#039; .. field.width .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
        local colspan = &amp;#039;&amp;#039;&lt;br /&gt;
        if field.cols then&lt;br /&gt;
            colspan = &amp;#039; colspan=&amp;quot;&amp;#039; .. field.cols .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        local th = &amp;#039;&amp;lt;th&amp;#039; .. style .. colspan .. &amp;#039;&amp;gt;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
        row = row .. th .. msg(field.col) .. &amp;#039;&amp;lt;/th&amp;gt;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    table.insert(rows, row)&lt;br /&gt;
    &lt;br /&gt;
    -- Now transform the Lua-table into an HTML-table&lt;br /&gt;
    for i, item in ipairs( tdata.params ) do&lt;br /&gt;
        row = &amp;#039;&amp;#039;&lt;br /&gt;
        for i2, field in ipairs( tableLayout ) do&lt;br /&gt;
            field.extract(item, renderCell, monolingual)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(rows, row)&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;#039;&amp;lt;table class=&amp;quot;wikitable templatebox-table&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;#039; .. table.concat(rows, &amp;#039;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;#039;) .. &amp;#039;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
----------------- TEMPLATEDATA PART ------------------&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- A real parser/transformer would look differently but it would likely be much more complex&lt;br /&gt;
-- The TemplateData-portion for [[Template:TemplateBox]]&lt;br /&gt;
function p.templatedata(frame)&lt;br /&gt;
    local tdata&lt;br /&gt;
    local args = frame.args or {}&lt;br /&gt;
    local formatting = args.formatting&lt;br /&gt;
    local pargs = ( frame:getParent() or {} ).args or {}&lt;br /&gt;
    local useTemplateData = pargs.useTemplateData&lt;br /&gt;
&lt;br /&gt;
    if  (formatting == &amp;#039;pretty&amp;#039; and useTemplateData ~= &amp;#039;export&amp;#039;) or&lt;br /&gt;
        (not useTemplateData) or&lt;br /&gt;
        (useTemplateData == &amp;#039;export&amp;#039; and formatting ~= &amp;#039;pretty&amp;#039;) then&lt;br /&gt;
            local warning = &amp;quot;Warning: Module:TemplateBox - templatedata invoked but not requested by user (setting useTemplateData=1).&amp;quot;&lt;br /&gt;
            mw.log(warning)&lt;br /&gt;
            tdata = &amp;#039;{&amp;quot;description&amp;quot;:&amp;quot;&amp;#039; .. warning .. &amp;#039;&amp;quot;,&amp;quot;params&amp;quot;:{},&amp;quot;sets&amp;quot;:[]}&amp;#039;&lt;br /&gt;
            return tdata&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Load the JSON-Module which will convert LUA tables into valid JSON&lt;br /&gt;
    local JSON = require(&amp;#039;Module:JSON&amp;#039;)&lt;br /&gt;
    JSON.strictTypes = true&lt;br /&gt;
    -- Obtain the object containing info&lt;br /&gt;
    tdata = p.args2table(pargs, nil, &amp;#039;templatedata&amp;#039;)&lt;br /&gt;
    -- And finally return the result&lt;br /&gt;
    if formatting == &amp;#039;pretty&amp;#039; then&lt;br /&gt;
        return JSON:encode_pretty(tdata)&lt;br /&gt;
    else&lt;br /&gt;
        return JSON:encode(tdata)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>PhilmacFLy</name></author>
	</entry>
</feed>