Modul:TemplateData
Dieses Modul wurde von der deutschsprachigen Wikipedia importiert und leicht modifiziert. Es dient der erweiterten Darstellung der TemplateData zur Nutzung im VisualEditor.
Eine erweitere Dokumentation ist auf der deutschsprachigen Wikipedia verfügbar.
Versionsbezeichnung auf Wikidata: keine Version verfügbar.
Das Modul wird von der Vorlage {{TemplateData}} aufgerufen.
Benötigte weitere Module
Dieses Modul benötigt folgende weitere Module: Arguments • JSONutil • Multilingual • Namespace detect • TemplateData/config • Text • WLink • Yesno}}
local TemplateData = { suite = "TemplateData",
serial = "2017-01-01" }
--[=[
improve template:TemplateData
]=]
local Config = {
-- multiple #invoke option names mapped into unique internal fields
cat = "strange",
debug = false,
docpageCreate = "suffix",
docpageDetect = "subpage",
msgDescMiss = "solo",
loudly = false, -- show exported element, etc.
solo = false, -- complaint on missing description
strange = false, -- title of maintenance category
subpage = false, -- pattern to identify subpage
suffix = false -- subpage creation scheme
}
local Data = {
div = false, -- <div class="mw-templatedata-doc-wrap">
got = false, -- table, initial templatedata object
heirs = false, -- table, params that are inherited
less = false, -- main description missing
lasting = false, -- old syntax encountered
-- low = false, -- 1= mode
order = false, -- parameter sequence
params = false, -- table, exported parameters
scream = false, -- error messages
slang = false, -- project language code
slim = false, -- JSON reduced to plain
source = false, -- JSON input
strip = false, -- <templatedata> evaluation
tag = false, -- table, exported root element
title = false, -- page
tree = false -- table, rewritten templatedata object
}
local Permit = {
colors = { required = "EAF3FF",
suggested = "FFFFFF",
optional = "D0D0D0",
deprecated = "FFCBCB" },
params = { aliases = "table",
autovalue = "string",
default = "string table I18N",
deprecated = "boolean string",
description = "string table I18N",
example = "string table I18N",
label = "string table I18N",
inherits = "string",
required = "boolean",
suggested = "boolean",
type = "string" },
root = { description = "string table I18N",
format = "string",
maps = "table",
params = "table",
paramOrder = "table",
sets = "table" },
search = "[{,]%%s*(['\"])%s%%1%%s*:%%s*%%{",
types = { boolean = true,
content = true,
date = true,
line = true,
number = true,
string = true,
unknown = true,
url = true,
["wiki-file-name"] = true,
["wiki-page-name"] = true,
["wiki-template-name"] = true,
["wiki-user-name"] = true,
["unbalanced-wikitext"] = true,
["string/line"] = "line",
["string/wiki-page-name"] = "wiki-page-name",
["string/wiki-user-name"] = "wiki-user-name" }
}
local function Fault( alert )
-- Memorize error message
-- Parameter:
-- alert -- string, error message
if Data.scream then
string.format( "%s *** %s", Data.scream, alert )
else
Data.scream = alert
end
end -- Fault()
local function facet( ask, at )
-- Find physical position of parameter definition in JSON
-- Parameter:
-- ask -- string, parameter name
-- at -- number, physical position within definition
-- Returns number, or nil
local seek = string.format( Permit.search,
ask:gsub( "%%", "%%%%" )
:gsub( "%-", "%%%-" ) )
local i, k = Data.source:find( seek, at )
local r, slice, source
while i and not r do
source = Data.source:sub( k + 1 )
slice = source:match( "^%s*\"([^\"]+)\"s*:" )
if not slice then
slice = source:match( "^%s*'([^']+)'%s*:" )
end
if ( slice and Permit.params[ slice ] ) or
source:match( "^%s*%}" ) then
r = k
else
i, k = Data.source:find( seek, k )
end
end -- while i
return r
end -- facet()
local function facility( about )
-- Create description head
-- Parameter:
-- about -- table, supposed to contain description
-- Returns <block>, with head, or nil
local para = mw.html.create( "p" )
local plus, r
if about and about.description then
if type( about.description ) == "string" then
para:wikitext( about.description )
else
para:wikitext( about.description[ 1 ] )
plus = mw.html.create( "ul" )
:addClass( "templatedata-maintain" )
:css( "display", "none" )
for k, v in pairs( about.description[ 2 ] ) do
plus:node( mw.html.create( "li" )
:node( mw.html.create( "code" )
:wikitext( k ) )
:tag( "br" )
:wikitext( v:gsub( "</?noinclude>",
"" ) ) )
end -- for k, v
end
elseif Config.solo then
para:addClass( "error" )
:wikitext( Config.solo )
Data.less = true
else
para = false
end
if para then
if plus then
r = mw.html.create( "div" )
:wikitext( para, plus )
else
r = para
end
end
return r
end -- facility()
local function factory( adapt )
-- Retrieve localized text from system message
-- Parameter:
-- adapt -- string, message ID after "templatedata-"
-- Returns string, with localized text
return mw.message.new( "templatedata-" .. adapt ):plain()
end -- factory()
local function faculty( adjust )
-- Test template arg for boolean
-- adjust -- string or nil
-- Returns boolean
local s = type( adjust )
local r
if s == "string" then
r = mw.text.trim( adjust )
r = ( r ~= "" and r ~= "0" )
elseif s == "boolean" then
r = adjust
else
r = false
end
return r
end -- faculty()
local function failures()
-- Retrieve error collection and category
-- Returns string
local r
if Data.scream then
local e = mw.html.create( "span" )
:addClass( "error" )
:wikitext( Data.scream )
r = tostring( e )
mw.addWarning( "'''TemplateData'''<br />" .. Data.scream )
if Config.strange then
r = string.format( "%s[[category:%s]]",
r,
Config.strange )
end
else
r = ""
end
return r
end -- failures()
local function faraway( alternatives )
-- Retrieve project language version from multilingual text
-- Parameter:
-- alternatives -- table, to be evaluated
-- Returns
-- 1 -- string, with best match
-- 2 -- table of other versions, if any
local n = 0
local r1, r2
if not Data.slang then
Data.slang = mw.language.getContentLanguage():getCode()
end
for k, v in pairs( alternatives ) do
if type( v ) == "string" then
v = mw.text.trim( v )
if v == "" then
alternatives[ k ] = nil
else
n = n + 1
end
else
alternatives[ k ] = nil
end
end -- for k, v
if n > 0 then
for k, v in pairs( alternatives ) do
if v then
if n == 1 then
r1 = v
elseif k:lower() == Data.slang then
alternatives[ k ] = nil
r1 = v
r2 = alternatives
break -- for k, v
end
end
end -- for k, v
if not r1 then
local seek = string.format( "^%s-", Data.slang )
for k, v in pairs( alternatives ) do
if v and k:lower():match( seek ) then
alternatives[ k ] = nil
r1 = v
r2 = alternatives
break -- for k, v
end
end -- for k, v
if not r1 then
local others = mw.language.getFallbacksFor( slang )
table.insert( others, "en" )
for i = 1, #others do
seek = others[ i ]
if alternatives[ seek ] then
r1 = alternatives[ seek ]
alternatives[ seek ] = nil
r2 = alternatives
break -- for i
end
end -- i = 1, #others
end
if not r1 then
for k, v in pairs( alternatives ) do
if v then
alternatives[ k ] = nil
r1 = v
r2 = alternatives
break -- for k, v
end
end -- for k, v
end
end
if r2 then
local Multilingual = fetch( "Multilingual" )
for k, v in pairs( r2 ) do
if v and not Multilingual.isLang( k ) then
Fault( string.format( "Invalid <code>lang=%s</code>",
k ) )
end
end -- for k, v
end
end
return r1, r2
end -- faraway()
local function fathers()
-- Merge params with inherited values
local n = 0
local p = Data.params
local t = Data.tree.params
local p2, t2
for k, v in pairs( Data.heirs ) do
n = n + 1
end -- for k, v
for i = 1, n do
for k, v in pairs( Data.heirs ) do
if v and not Data.heirs[ v ] then
n = n - 1
t[ k ].inherits = nil
Data.heirs[ k ] = nil
p2 = { }
t2 = { }
for k2, v2 in pairs( p[ v ] ) do
p2[ k2 ] = v2
end -- for k2, v2
for k2, v2 in pairs( p[ k ] ) do
if type( v2 ) ~= "nil" then
p2[ k2 ] = v2
end
end -- for k2, v2
p[ k ] = p2
for k2, v2 in pairs( t[ v ] ) do
t2[ k2 ] = v2
end -- for k2, v2
for k2, v2 in pairs( t[ k ] ) do
if type( v2 ) ~= "nil" then
t2[ k2 ] = v2
end
end -- for k2, v2
t[ k ] = t2
end
end -- for k, v
end -- i = 1, n
if n > 0 then
local s
for k, v in pairs( Data.heirs ) do
if v then
if s then
s = string.format( "%s | %s", s, k )
else
s = "Circular inherits: " .. k
end
end
end -- for k, v
Fault( s )
end
end -- fathers()
local function feat()
-- Check and store parameter sequence
if Data.source then
local i = 0
local s
for k, v in pairs( Data.tree.params ) do
if i == 0 then
Data.order = { }
i = 1
s = k
else
i = 2
break -- for k, v
end
end -- for k, v
if i > 1 then
local pointers = { }
local points = { }
for k, v in pairs( Data.tree.params ) do
i = facet( k, 1 )
if i then
table.insert( points, i )
pointers[ i ] = k
i = facet( k, i )
if i then
s = "Parameter '%s' detected twice"
Fault( string.format( s, k ) )
end
else
s = "Parameter '%s' not detected"
Fault( string.format( s, k ) )
end
end -- for k, v
table.sort( points )
for i = 1, #points do
table.insert( Data.order, pointers[ points[ i ] ] )
end -- i = 1, #points
elseif s then
table.insert( Data.order, s )
end
end
end -- feat()
local function feature( access )
-- Create table row for parameter, check and display violations
-- Parameter:
-- access -- string, with name
-- Returns <tr>
local mode, s, status
local fine = function ( a )
s = mw.text.trim( a )
return a == s and
a ~= "" and
not a:find( "%|=\n" ) and
not a:find( "%s%s" )
end
local begin = mw.html.create( "td" )
local code = mw.html.create( "code" )
local desc = mw.html.create( "td" )
local legal = true
local param = Data.tree.params[ access ]
local ranking = { "required", "suggested", "optional", "deprecated" }
local r = mw.html.create( "tr" )
local sort = param.label or access
local typed = param.type
-- label
if sort:match( "^%d+$" ) then
begin:attr( "data-sort-value",
string.format( "%05d", tonumber( sort ) ) )
end
begin:css( "font-weight", "bold" )
:wikitext( sort )
-- name and aliases
code:wikitext( access )
if not fine( access ) then
code:addClass( "error" )
Fault( string.format( "Bad ID params.<code>%s</code>", access ) )
legal = false
begin:attr( "data-sort-value", " " .. sort )
end
code = mw.html.create( "td" )
:node( code )
if access:match( "^%d+$" ) then
code:attr( "data-sort-value",
string.format( "%05d", tonumber( access ) ) )
end
if type( param.aliases ) == "table" then
local lapsus
for k, v in pairs( param.aliases ) do
code:tag( "br" )
if type( v ) == "string" then
if not fine( v ) then
lapsus = true
code:node( mw.html.create( "span" )
:addClass( "error" )
:css( "font-style", "italic" )
:wikitext( "string" ) )
end
code:wikitext( s )
else
lapsus = true
code:node( mw.html.create( "code" )
:addClass( "error" )
:wikitext( type( v ) ) )
end
end -- for k, v
if lapsus then
s = string.format( "params.<code>%s</code>.aliases", access )
Fault( factory( "invalid-value" ):gsub( "$1", s ) )
legal = false
end
end
-- description etc.
s = facility( param )
if s then
desc:node( s )
end
if param.default or param.example or param.autovalue then
local details = { "default", "example", "autovalue" }
local dl = mw.html.create( "dl" )
local section, show
for i = 1, #details do
s = details[ i ]
show = param[ s ]
if show then
section = factory( "doc-param-" .. s )
dl:node( mw.html.create( "dt" )
:wikitext( section ) )
:node( mw.html.create( "dd" )
:wikitext( mw.text.nowiki( show ) ) )
end
end -- i = 1, #details
desc:node( dl )
end
-- type
if typed then
s = Permit.types[ typed ]
typed = mw.html.create( "td" )
if s then
if s == "string" then
Data.params[ access ].type = s
typed:wikitext( factory( "doc-param-type-" .. s ) )
:node( "br" )
:node( mw.html.create( "span" )
:addClass( "error" )
:wikitext( param.type ) )
Data.lasting = true
else
s = factory( "doc-param-type-" .. param.type )
typed:wikitext( s )
end
else
Data.params[ access ].type = "unknown"
typed:addClass( "error" )
:wikitext( "INVALID" )
s = string.format( "params.<code>%s</code>.type", access )
Fault( factory( "invalid-value" ):gsub( "$1", s ) )
legal = false
end
else
typed = mw.html.create( "td" )
:wikitext( factory( "doc-param-type-unknown" ) )
end
-- status
if param.required then
mode = 1
if param.deprecated then
Fault( string.format( "Required deprecated <code>%s</code>",
access ) )
legal = false
end
elseif param.deprecated then
mode = 4
elseif param.suggested then
mode = 2
else
mode = 3
end
status = ranking[ mode ]
ranking = factory( "doc-param-status-" .. status )
if mode == 1 or mode == 4 then
ranking = mw.html.create( "span" )
:css( "font-weight", "bold" )
:wikitext( ranking )
if type( param.deprecated ) == "string" then
ranking:tag( "br" )
:wikitext( param.deprecated )
end
end
-- <tr>
r:attr( "id", "templatedata:" .. mw.uri.anchorEncode( access ) )
:css( "background-color", "#" .. Permit.colors[ status ] )
:node( begin )
:node( code )
:node( desc )
:node( typed )
:node( mw.html.create( "td" )
:attr( "data-sort-value", tostring( mode ) )
:node( ranking ) )
:newline()
if not legal then
r:css( "border", "#FF0000 3px solid" )
end
return r
end -- feature()
local function features()
-- Create <table> for parameters
-- Returns <table>, or nil
local r
if Data.tree and Data.tree.params then
local tr = mw.html.create( "tr" )
feat()
tr:node( mw.html.create( "th" )
:attr( "colspan", "2" )
:wikitext( factory( "doc-param-name" ) ) )
:node( mw.html.create( "th" )
:wikitext( factory( "doc-param-desc" ) ) )
:node( mw.html.create( "th" )
:wikitext( factory( "doc-param-type" ) ) )
:node( mw.html.create( "th" )
:wikitext( factory( "doc-param-status" ) ) )
r = mw.html.create( "table" )
:addClass( "wikitable" )
if Data.order and #Data.order > 1 then
r:addClass( "sortable" )
end
r:newline()
-- :node( mw.html.create( "thead" )
:node( tr )
-- )
:newline()
if Data.order then
for i = 1, #Data.order do
r:node( feature( Data.order[ i ] ) )
end -- for i = 1, #Data.order
end
end
return r
end -- features()
local function fetch( ask )
-- Fetch module
-- Parameter:
-- ask -- string, with name
-- "Multilingual"
-- "Text"
-- "WLink"
-- Returns table of module
-- error: Module not available
local r
if TemplateData.extern then
r = TemplateData.extern[ ask ]
else
TemplateData.extern = { }
end
if not r then
local lucky, g = pcall( require, "Module:" .. ask )
if type( g ) == "table" then
r = g[ ask ]()
TemplateData.extern[ ask ] = r
else
error( string.format( "fetch(%s) %s", ask, g ) )
end
end
return r
end -- fetch()
local function finalize()
-- Wrap presentation into frame
-- Returns string
local r
if Data.div then
r = tostring( Data.div )
elseif Data.strip then
r = Data.strip
else
r = ""
end
return r .. failures()
end -- finalize()
local function find()
-- Find JSON data within page source (title)
-- Returns string, or nil
local s = Data.title:getContent()
local i, j = s:find( "<templatedata>", 1, true )
local r
if i then
local k = s:find( "</templatedata>", j, true )
if k then
r = mw.text.trim( s:sub( j + 1, k - 1 ) )
end
end
return r
end -- find()
local function flat( adjust )
-- Remove formatting from text string
-- Parameter:
-- arglist -- string, to be stripped, or nil
-- Returns string, or nil
local r
if adjust then
r = adjust
if r:find( "<noinclude>", 1, true ) then
r = r:gsub( "<noinclude>(.*)</noinclude>", "" )
end
if r:find( "''", 1, true ) or r:find( "<", 1, true ) then
local Text = fetch( "Text" )
r = Text.getPlain( r )
end
if r:find( "[", 1, true ) then
local WLink = fetch( "WLink" )
if WLink.isBracketedURL( r ) then
r = r:gsub( "%[([hf]tt?ps?://%S+) [^%]]+%]", "%1" )
end
r = WLink.getPlain( r )
end
if r:find( "&", 1, true ) then
r = mw.text.decode( r )
end
end
return r
end -- flat()
local function flush()
-- JSON encode narrowed input; obey unnamed (numerical) parameters -- Returns <templatedata> JSON string
local r
if Data.tag then
r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," )
else
r = "{"
end
r = r .. "\n\"params\":{"
if Data.order then
local sep = ""
local s
for i = 1, #Data.order do
s = Data.order[ i ]
r = string.format( "%s%s\n%s:%s",
r,
sep,
mw.text.jsonEncode( s ),
mw.text.jsonEncode( Data.params[ s ] ) )
sep = ",\n"
end -- for i = 1, #Data.order
end
r = r .. "\n}\n}"
return r
end -- flush()
local function focus( access )
-- Check components; focus multilingual description, build trees
-- Parameter:
-- access -- string, name of parameter, nil for root
local f = function ( a, at )
local r
if at then
r = string.format( "<code>params.%s</code>", at )
else
r = "''root''"
end
if a then
r = string.format( "%s<code>.%s</code>", r, a )
end
return r
end
local parent
if access then
parent = Data.got.params[ access ]
else
parent = Data.got
end
if type( parent ) == "table" then
local elem, got, permit, s, scope, slot, tag, target
if access then
permit = Permit.params
if type( access ) == "number" then
slot = tostring( access )
else
slot = access
end
else
permit = Permit.root
end
for k, v in pairs( parent ) do
scope = permit[ k ]
if scope then
s = type( v )
if s == "string" then
v = mw.text.trim( v )
if v == "" then
s = "empty"
end
end
if scope:find( s, 1, true ) then
if scope:find( "I18N", 1, true ) then
if s == "string" then
elem = v:gsub( "</?noinclude>", "" )
v = flat( v )
else
local translated
v, translated = faraway( v )
if translated and k == "description" then
elem = { [ 1 ] = v:gsub( "</?noinclude>",
"" ),
[ 2 ] = translated }
else
elem = v:gsub( "</?noinclude>", "" )
end
v = flat( v )
end
else
elem = v
if k == "params" and not access then
v = nil
elem = nil
elseif k == "inherits" then
if not Data.heirs then
Data.heirs = { }
end
Data.heirs[ slot ] = v
v = nil
end
end
if type( elem ) ~= "nil" then
if not target then
if access then
if not Data.tree.params then
Data.tree.params = { }
end
Data.tree.params[ slot ] = { }
target = Data.tree.params[ slot ]
else
Data.tree = { }
target = Data.tree
end
end
target[ k ] = elem
elem = false
end
if type( v ) ~= "nil" then
if not tag then
if access then
if not Data.params then
Data.params = { }
end
Data.params[ slot ] = { }
tag = Data.params[ slot ]
else
Data.tag = { }
tag = Data.tag
end
end
tag[ k ] = v
end
elseif s ~= "empty" then
s = string.format( "Type <code>%s</code> bad for %s",
scope, f( k, slot ) )
Fault( s )
end
else
Fault( "Unknown component " .. f( k, slot ) )
end
end -- for k, v
else
Fault( f() .. " needs to be of <code>object</code> type" )
end
end -- focus()
local function format()
-- Build presented documentation
-- Returns <div>
local r = mw.html.create( "div" )
local s = facility( Data.tree )
if s then
r:node( s )
end
s = features()
if s then
r:node( s )
end
if Data.tree and Data.tree.format then
local e, style
s = Data.tree.format:lower( Data.tree.format )
if s == "inline" or s == "block" then
style = "i"
else
style = "code"
end
r:node( mw.html.create( "p" )
:wikitext( "Format: " )
:node( mw.html.create( style )
:wikitext( s ) ) )
end
return r
end -- format()
local function free()
-- Remove JSON comment lines
Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([},\"'])",
"%1%3" )
end -- free()
local function full()
-- Build survey table from JSON data, append invisible <templatedata>
Data.div = mw.html.create( "div" )
:addClass( "mw-templatedata-doc-wrap" )
focus()
if Data.tag then
if type( Data.got.params ) == "table" then
for k, v in pairs( Data.got.params ) do
focus( k )
end -- for k, v
if Data.heirs then
fathers()
end
end
end
Data.div:node( format() )
Data.slim = flush()
if TemplateData.frame then
local div = mw.html.create( "div" )
local tdata = { [ 1 ] = "templatedata",
[ 2 ] = Data.slim }
Data.strip = TemplateData.frame:callParserFunction( "#tag",
tdata )
div:wikitext( Data.strip )
if not Config.loudly then
div:css( "display", "none" )
end
Data.div:node( div )
end
end -- full()
local function furnish( adapt, arglist )
-- Analyze transclusion
-- Parameter:
-- adapt -- table, #invoke parameters
-- arglist -- table, template parameters
-- Returns string
local source
for k, v in pairs( Config ) do
if adapt[ k ] and adapt[ k ] ~= "" then
Config[ v ] = adapt[ k ]
end
end -- for k, v
Config.loudly = faculty( arglist.debug or adapt.debug )
if mw.site.server:find( "//de.wikipedia.beta.wmflabs.org", 1, true ) then
Config.loudly = true
end
Config.strange = "Wikipedia:Vorlagenfehler/Vorlage:TemplateData"
Config.solo = "Beschreibung fehlt"
Config.subpage = "/Doku$"
Config.suffix = "%s/Doku"
if arglist.JSON then
source = arglist.JSON
elseif arglist[ 1 ] then
local s = mw.text.trim( arglist[ 1 ] )
local start = s:sub( 1, 1 )
if start == "<" then
Data.strip = s
elseif start == "{" then
source = s
elseif mw.ustring.sub( s, 1, 8 ) ==
mw.ustring.char( 127, 39, 34, 96, 85, 78, 73, 81 ) then
Data.strip = s
end
end
if not source then
Data.title = mw.title.getCurrentTitle()
source = find()
if not source and
Config.subpage and Config.suffix and
not Data.title.text:match( Config.subpage ) then
local s = string.format( Config.suffix,
Data.title.prefixedText )
Data.title = mw.title.new( s )
if Data.title.exists then
source = find()
end
end
end
TemplateData.getPlainJSON( source )
return finalize()
end -- furnish()
TemplateData.failsafe = function ( assert )
local r
if not assert or assert <= TemplateData.serial then
r = TemplateData.serial
else
r = false
end
return r
end -- TemplateData.failsafe()
TemplateData.getPlainJSON = function ( adapt )
-- Reduce enhanced JSON data to plain text localized JSON
-- Parameter:
-- adapt -- string, with enhanced JSON
-- Returns string, or not
if type( adapt ) == "string" then
Data.source = adapt
free()
Data.got = mw.text.jsonDecode( Data.source )
if Data.got then
full()
if Data.lasting then
Fault( "deprecated type syntax" )
end
if Data.less then
Fault( Config.solo )
end
elseif not Data.strip then
Fault( "fatal JSON error" )
end
end
return Data.slim
end -- TemplateData.getPlainJSON()
TemplateData.test = function ( adapt, arglist )
TemplateData.frame = mw.getCurrentFrame()
return furnish( adapt, arglist )
end -- TemplateData.test()
-- Export
local p = { }
p.f = function ( frame )
-- Template call
local lucky, r
TemplateData.frame = frame
lucky, r = pcall( furnish, frame.args, frame:getParent().args )
if not lucky then
Fault( "INTERNAL: " .. r )
r = failures()
end
return r
end -- p.f()
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return TemplateData.failsafe( since ) or ""
end -- p.failsafe()
p.TemplateData = function ()
-- Module interface
return TemplateData
end
return p
Kategorien:
- Modul benötigt das Modul Arguments
- Modul benötigt das Modul JSONutil
- Modul benötigt das Modul Multilingual
- Modul benötigt das Modul Namespace detect
- Modul benötigt das Modul TemplateData/config
- Modul benötigt das Modul Text
- Modul benötigt das Modul WLink
- Modul benötigt das Modul Yesno
- Vorlagen:Formatierungshilfe