imported>PerfektesChaos (2017-04-24) |
imported>PerfektesChaos (2019-10-19) |
||
Zeile 1: | Zeile 1: | ||
local Export = { serial = " | local Export = { serial = "2019-10-19", | ||
suite = "lang" } | suite = "lang", | ||
item = 26826825 } | |||
--[=[ | --[=[ | ||
Vorlage:lang und Sprachnamenvorlagen usw. unterstützen | Vorlage:lang und Sprachnamenvorlagen usw. unterstützen | ||
]=] | ]=] | ||
local Failsafe = Export | |||
local GlobalMod = Export | |||
local Config = { | local Config = { | ||
errCat | errCat = false, | ||
errClass | errClass = "error_lang", | ||
errClasses | errClasses = false, | ||
errHide | errHide = true, | ||
errNS | errNS = false, | ||
errDoubled | errDoubled = { en = "Doubled:", | ||
de = "Doppelangabe:" }, | |||
errInvalid | errEmpty = { en = "Empty parameter value", | ||
de = "Parameterwert fehlt" }, | |||
errMissing | errInvalid = { en = "Invalid:", | ||
de = "Ungültig:" }, | |||
errUnkown | errMissing = { en = "Missing parameter", | ||
de = "Parameter fehlt" }, | |||
errSuggest = { en = "'%s' * probably '%s' intended", | |||
de = "'%s' * vermutlich ist '%s' gemeint" }, | |||
errUnkown = { en = "Unkown parameter:", | |||
de = "Parameter unbekannt:" }, | |||
ipa = "IPA", | |||
keyBase = 100, | |||
keyProject = 200, | |||
keyAncient = 300, | |||
keyTranslate = 400, | |||
params = { "Text1", | |||
"Audio", | |||
"IPA", | |||
"class", | |||
"lenient", | |||
"script", | |||
"style", | |||
"nachgestellt", | |||
"demo", | |||
"demo2", | |||
"demo3", | |||
"demo4", | |||
"NoCat" }, | |||
percents = false, | |||
orderOther = { grc = 1, | |||
hbo = 2, | |||
la = 3, | |||
en = 9 }, | |||
owns = { de = "‚%s‘" }, | |||
sepComma = "Latn Armn Cyrl Grek Thai", | |||
site = "Latn", | |||
percents | tmplAudio = false, -- template for media player link | ||
tmplLang = false, -- template for language name link | |||
orderOther | tmplStyles = false, | ||
wikidata = { Multilingual = 47541920, | |||
ISO15924 = 71584769, | |||
["ISO15924/codes"] = 71840276, | |||
owns | TemplUtl = 52364930 } | ||
tmplAudio | |||
} | } | ||
local foreignModule = function ( access, advanced, append, alt, alert ) | |||
-- Fetch global module | |||
-- Precondition: | |||
-- access -- string, with name of base module | |||
-- advanced -- true, for require(); else mw.loadData() | |||
-- append -- string, with subpage part, if any; or false | |||
-- alt -- number, of wikidata item of root; or false | |||
-- alert -- true, for throwing error on data problem | |||
-- Postcondition: | |||
-- Returns whatever, probably table | |||
-- 2019-10-29 | |||
local storage = access | |||
local finer = function () | |||
if append then | |||
storage = string.format( "%s/%s", | |||
storage, | |||
append ) | |||
end | |||
end | |||
local fun, lucky, r, suited | |||
if advanced then | |||
fun = require | |||
else | |||
fun = mw.loadData | |||
end | |||
GlobalMod.globalModules = GlobalMod.globalModules or { } | |||
suited = GlobalMod.globalModules[ access ] | |||
if not suited then | |||
finer() | |||
lucky, r = pcall( fun, "Module:" .. storage ) | |||
end | |||
if not lucky then | |||
if not suited and | |||
type( alt ) == "number" and | |||
alt > 0 then | |||
suited = string.format( "Q%d", alt ) | |||
suited = mw.wikibase.getSitelink( suited ) | |||
GlobalMod.globalModules[ access ] = suited or true | |||
end | |||
if type( suited ) == "string" then | |||
storage = suited | |||
finer() | |||
lucky, r = pcall( fun, storage ) | |||
end | |||
if not lucky and alert then | |||
error( "Missing or invalid page: " .. storage, 0 ) | |||
end | |||
end | |||
return r | |||
end -- foreignModule() | |||
local function Fetch( ask ) | local function Fetch( ask ) | ||
-- Fetch module | -- Fetch module (require) | ||
-- Parameter: | -- Parameter: | ||
-- ask -- string, with name | -- ask -- string, with name | ||
-- "ISO15924" | |||
-- "Multilingual" | -- "Multilingual" | ||
-- "TemplUtl" | -- "TemplUtl" | ||
-- Returns string, with error message, if not available | -- Returns string, with error message, if not available | ||
local ext = Config[ ask ] | |||
local r | local r | ||
if | if not ext and ext ~= false then | ||
ext = foreignModule( ask, | |||
if type( | true, | ||
false, | |||
if type( | Config.wikidata[ ask ] ) | ||
Config[ ask ] = | if type( ext ) == "table" then | ||
Config[ ask ] = ext | |||
if type( ext[ ask ] ) == "function" then | |||
Config[ ask ] = ext[ ask ]() | |||
end | end | ||
end | end | ||
if type( Config[ ask ] ) ~= "table" then | if type( Config[ ask ] ) ~= "table" then | ||
if not | Config[ ask ] = false | ||
if not ext then | |||
ext = "Invalid library *** Module:" .. ask | |||
end | end | ||
ext = mw.html.create( "span" ) | |||
:attr( "class", "error" ) | |||
:wikitext( ext ) | |||
r = tostring( | r = tostring( ext ) | ||
end | end | ||
end | end | ||
Zeile 102: | Zeile 153: | ||
end -- Fetch() | end -- Fetch() | ||
local function Frame() | |||
-- Fetch current frame | |||
-- Returns frame | |||
if not Config.frame then | |||
Config.frame = mw.getCurrentFrame() | |||
end | |||
return Config.frame | |||
end -- Frame() | |||
local function Friend() | |||
-- Fetch Module:ISO15924/codes | |||
if not Config.codesISO15924 then | |||
Config.codesISO15924 = foreignModule( "ISO15924", | |||
false, | |||
"codes", | |||
Config.wikidata.ISO15924 ) | |||
if type( Config.codesISO15924 ) ~= "table" then | |||
Config.codesISO15924 = { } | |||
end | |||
end | |||
return Config.codesISO15924 | |||
end -- Friend() | |||
local function Fulfil( access, args ) | |||
-- Expand template | |||
-- apply -- string, with template name | |||
-- args -- table, with parameters | |||
-- Returns string | |||
-- Throws error, if template not existing | |||
return Frame():expandTemplate{ title = access, | |||
args = args } | |||
end -- Fulfil() | |||
Zeile 133: | Zeile 222: | ||
-- apply -- string, with message key | -- apply -- string, with message key | ||
-- Returns message text; at least english | -- Returns message text; at least english | ||
local entry = Config[ apply ] | |||
local r | local r | ||
if entry then | if entry then | ||
r = entry[ facility() ] | r = entry[ facility() ] | ||
Zeile 141: | Zeile 230: | ||
end | end | ||
else | else | ||
local e = mw.html.create( "span" ) | |||
:attr( "class", "error" ) | |||
:wikitext( string.format( "????.%s.????", | |||
apply ) ) | |||
r = tostring( e ) | |||
end | end | ||
return r | return r | ||
Zeile 157: | Zeile 249: | ||
if s == "string" then | if s == "string" then | ||
r = mw.text.trim( adjust ) | r = mw.text.trim( adjust ) | ||
r = ( r ~= "" and r ~= "0" ) | r = ( r ~= "" and r ~= "0" and r ~= "-" ) | ||
elseif s == "boolean" then | elseif s == "boolean" then | ||
r = adjust | r = adjust | ||
Zeile 165: | Zeile 257: | ||
return r | return r | ||
end -- faculty() | end -- faculty() | ||
local function familiar( ask, assign ) | |||
-- Check whether valid transcription for context | |||
-- ask -- string, with transcription code | |||
-- assign -- string or nil, with language or scripting key | |||
-- Returns boolean | |||
local r | |||
Fetch( "ISO15924" ) | |||
if Config.ISO15924 then | |||
r = Config.ISO15924.isTrans( ask, assign, Config.site ) | |||
end | |||
return r | |||
end -- familiar() | |||
Zeile 171: | Zeile 278: | ||
-- attempt to load local config | -- attempt to load local config | ||
if not Config.data then | if not Config.data then | ||
local | local sub = string.format( "%s/config", Frame():getTitle() ) | ||
local lucky | |||
lucky, Config.data = pcall( mw.loadData, sub ) | lucky, Config.data = pcall( mw.loadData, sub ) | ||
if type( Config.data ) == "table" then | if type( Config.data ) == "table" then | ||
Zeile 189: | Zeile 293: | ||
local function fault( alert, about ) | local function fault( alert, about, assign ) | ||
-- Format message with class="error" or similar | -- Format message with class="error" or similar | ||
-- alert | -- alert -- string, with message key | ||
-- about | -- about -- string, with explanation | ||
-- assign -- true, when standard category to be fired | |||
-- Returns message with markup | -- Returns message with markup | ||
local story = factory( alert ) | local story = factory( alert ) | ||
local env = Frame():getParent() | |||
local err = mw.html.create( "span" ) | local err = mw.html.create( "span" ) | ||
local r | local r | ||
Zeile 201: | Zeile 307: | ||
["margin-right"] = "1em" } ) | ["margin-right"] = "1em" } ) | ||
family() | family() | ||
if | if env then | ||
story = string.format( "[[%s]] – %s", | |||
env:getTitle(), story ) | |||
end | end | ||
if about then | if about then | ||
story = string.format( "%s %s", story, about ) | story = string.format( "%s %s", story, about ) | ||
Zeile 217: | Zeile 321: | ||
if Config.TemplUtl then | if Config.TemplUtl then | ||
r = Config.TemplUtl.failure( tostring( err ), | r = Config.TemplUtl.failure( tostring( err ), | ||
not Config.errHide ) | not Config.errHide, | ||
false, | |||
Frame() ) | |||
end | end | ||
if type( Config.errCat ) == "string" then | if assign and type( Config.errCat ) == "string" then | ||
if Config.errNS then | if Config.errNS then | ||
local ns = mw.title.getCurrentTitle().namespace | local ns = mw.title.getCurrentTitle().namespace | ||
Zeile 247: | Zeile 353: | ||
local function | local function features( apply, assign ) | ||
-- | -- Equip element with script attributes | ||
-- apply -- string, with text | -- apply -- mw.html element | ||
-- Returns string | -- assign -- string, with script code | ||
if type( Config.percents ) == "table" then | |||
local more = Config.percents[ assign ] | |||
if more then | |||
apply:css( "font-size", string.format( "%d%%", more ) ) | |||
end | |||
end | |||
end -- features() | |||
local function fill( apply ) | |||
-- Expand language name template | |||
-- apply -- string, with code | |||
-- Returns string, identical apply in case of error | |||
local r = apply | |||
local template | |||
family() | |||
template = Config.tmplLang | |||
if type( template ) == "table" then | |||
local source = template.title | |||
if type( source ) ~= "string" then | |||
if type( template.namePat ) == "string" and | |||
template.namePat:find( "%s", 1, true ) then | |||
source = string.format( template.namePat, apply ) | |||
end | |||
end | |||
if type( source ) == "string" then | |||
local lucky, s = pcall( Fulfil, source ) | |||
if lucky then | |||
r = s | |||
end | |||
end | |||
end | |||
return r | |||
end -- fill() | |||
local function first( assign, apply ) | |||
-- Equip element with TemplateStyles | |||
-- assign -- string, with script code | |||
-- apply -- mw.html element, or false | |||
-- Returns string, perhaps with tag | |||
local r | |||
if type( Config.tmplStyles ) == "table" then | |||
local source = Config.tmplStyles[ assign ] | |||
if source then | |||
r = Frame():extensionTag( "templatestyles", | |||
nil, | |||
{ src = source } ) | |||
if apply then | |||
apply:wikitext( r ) | |||
end | |||
end | |||
end | |||
return r or "" | |||
end -- first() | |||
local function fit( acquire ) | |||
-- Retrieve script code for language | |||
-- acquire -- string, with language code | |||
-- Returns string or false | |||
local r | |||
local iso639script = Friend().iso639script | |||
if type( iso639script ) == "table" then | |||
r = iso639script[ acquire ] | |||
if type( r ) == "table" then | |||
r = r[ 1 ] | |||
end | |||
end | |||
return r | |||
end -- fit() | |||
local function flag( already, apply ) | |||
-- Check whether space separated classes contain | |||
-- already -- string or false, with classes | |||
-- apply -- string or false, with single class | |||
-- Returns true, if apply is in already | |||
local r | |||
if already then | |||
if apply then | |||
local classes = mw.text.split( already, "%s+" ) | |||
local plus = mw.text.split( apply, "%s+" ) | |||
local single | |||
for i = 1, #plus do | |||
single = plus[ i ] | |||
for k = 1, #classes do | |||
if classes[ k ] == single then | |||
single = false | |||
break -- for k | |||
end | |||
end -- for k | |||
if single then | |||
table.insert( classes, single ) | |||
end | |||
end -- for i | |||
r = table.concat( classes, " " ) | |||
else | |||
r = already | |||
end | |||
else | |||
r = apply | |||
end | |||
return r | |||
end -- flag() | |||
local function flatten( apply ) | |||
-- Trim any whitespace, even HTML encoded | |||
-- apply -- string | |||
-- Returns string, or false if empty | |||
local r = apply | local r = apply | ||
if Config. | if r:find( "&" ) then | ||
r = | r = r:gsub( " ", " " ) | ||
:gsub( " ", " " ) | |||
:gsub( "‌", "‌" ) | |||
:gsub( "‍", "‍" ) | |||
:gsub( "‎", "‎" ) | |||
:gsub( "‏", "‏" ) | |||
if r:find( "&#" ) then | |||
local f = function ( ax, an ) | |||
local k | |||
if ax == "x" then | |||
k = 16 | |||
else | |||
k = 10 | |||
end | |||
return mw.ustring.char( tonumber( an, k ) ) | |||
end | |||
r = r:gsub( "&#(x?)(%x+);", f ) | |||
end | |||
end | |||
if not Config.patternWS then | |||
Config.patternWS = mw.ustring.char( 91, | |||
1, 45, 32, | |||
160, | |||
8194, 45, 8207, | |||
8239, | |||
93, | |||
43 ) | |||
end | |||
r = mw.ustring.gsub( r, "^" .. Config.patternWS, "" ) | |||
r = mw.ustring.gsub( r, Config.patternWS .. "$", "" ) | |||
if r == "" then | |||
r = false | |||
end | |||
return r | |||
end -- flatten() | |||
local function follow( affine ) | |||
-- Retrieve appropriate separator | |||
-- affine -- string or nil, with code of script | |||
-- Returns string, with separator (comma) or not | |||
local r | |||
if affine then | |||
if Config.sepComma:find( affine, 1, true ) then | |||
r = "," | |||
else | |||
r = "" | |||
end | |||
else | |||
r = "," | |||
end | end | ||
return r | return r | ||
end -- | end -- follow() | ||
local function foreign( apply, acquire, advanced ) | local function foreign( apply, acquire, advanced, affine ) | ||
-- Format text in some language | -- Format text in some language | ||
-- apply -- string, with text | -- apply -- string, with text | ||
-- acquire -- string, with basic code of language | -- acquire -- string, with basic code of language | ||
-- advanced -- string, with full code of language | -- advanced -- string, with full code of language | ||
-- | -- affine -- string or nil, with code of script | ||
local story = apply | -- Returns string | ||
local story = apply | |||
local script = affine | |||
local p = { ["font-weight"] = "normal" } | |||
local ltr, r | local ltr, r | ||
if advanced == acquire then | if advanced == acquire then | ||
ltr = not mw.language.new( acquire ):isRTL() | ltr = not mw.language.new( acquire ):isRTL() | ||
elseif not script and advanced:find( "-", 3, true ) then | |||
local parts = mw.text.split( advanced, "-", true ) | |||
if #parts > 1 and parts[ 2 ]:match( "^%u%l%l%l$" ) then | |||
script = parts[ 2 ] | |||
end | |||
end | |||
if script then | |||
local rtl = Friend().rtl | |||
if type( rtl ) == "table" then | |||
ltr = not rtl[ script ] | |||
end | |||
end | end | ||
if ltr then | if ltr then | ||
local e = mw.html.create( "span" ) | local e = mw.html.create( "span" ) | ||
:attr( "lang", advanced ) | :attr( "lang", advanced ) | ||
local s = "normal" | local s = "normal" | ||
if acquire == | if acquire == facility() | ||
and Config.owns[ acquire ] then | and Config.owns[ acquire ] then | ||
story = string.format( Config.owns[ acquire ], apply ) | story = string.format( Config.owns[ acquire ], apply ) | ||
elseif advanced == acquire or | elseif advanced == acquire and Config.site == "Latn" or | ||
advanced == acquire .. "-Latn" then | advanced == acquire .. "-Latn" then | ||
s = "italic" | s = "italic" | ||
Zeile 291: | Zeile 573: | ||
r = tostring( e ) | r = tostring( e ) | ||
else | else | ||
r = | p["font-style"] = "normal" | ||
r = Export.fold( { css = p, | |||
SCRIPTING = script }, | |||
{ [ 1 ] = acquire, | |||
[ 2 ] = apply, | |||
lang = advanced } ) | |||
end | end | ||
return r | return r | ||
Zeile 299: | Zeile 585: | ||
local function foreigns( aliens ) | local function foreigns( ahead, aliens, alone ) | ||
-- Create list of translations | -- Create list of translations | ||
-- ahead -- string, with leading separator | |||
-- aliens -- sequence table, with assignment tables | -- aliens -- sequence table, with assignment tables | ||
-- Returns string, starting with comma | -- alone -- boolean, no other elements in collection yet | ||
-- Returns string, starting with separator (comma) | |||
local pars = { } | local pars = { } | ||
local s, t | local sep = ahead | ||
local lone = alone | |||
local r = "" | |||
local k, lucky, s, t | |||
family() | family() | ||
facility() | facility() | ||
Zeile 312: | Zeile 602: | ||
t = aliens[ i ] | t = aliens[ i ] | ||
if t.short == Config.standard then | if t.short == Config.standard then | ||
t.m = Config.keyProject | |||
t.n = 0 | t.n = 0 | ||
else | else | ||
k = Config.orderOther[ t.short ] | |||
if | if k then | ||
t.n = | t.n = k | ||
t.m = Config.keyAncient | |||
end | end | ||
lone = false | |||
end | end | ||
t.n = t.m + t.n | |||
end -- for i | end -- for i | ||
table.sort( aliens, | table.sort( aliens, | ||
Zeile 324: | Zeile 618: | ||
return ( a1.n < a2.n ) | return ( a1.n < a2.n ) | ||
end ) | end ) | ||
for i = 1, #aliens do | for i = 1, #aliens do | ||
t = aliens[ i ] | t = aliens[ i ] | ||
if | if lone then | ||
s = | s = "" | ||
sep = "" | |||
else | else | ||
s = mw.language.fetchLanguageName( t.short, Config.standard ) | s = false | ||
if t.short == Config.slang and | |||
t.script and | |||
t.n > 0 then | |||
Fetch( "ISO15924" ) | |||
if Config.ISO15924 then | |||
s = Config.ISO15924.scriptName( t.script ) | |||
if s == t.script then | |||
s = false | |||
end | |||
end | |||
end | |||
if not s and t.n > Config.keyProject then | |||
s = fill( t.short ) | |||
end | |||
if not s then | |||
Fetch( "Multilingual" ) | |||
s = mw.language.fetchLanguageName( t.short, | |||
Config.standard ) | |||
if Config.Multilingual and | |||
Config.Multilingual.isMinusculable( s ) then | |||
s = mw.ustring.lower( mw.ustring.sub( s, 1, 1 ) ) | |||
.. mw.ustring.sub( s, 2 ) | |||
end | |||
end | end | ||
end | end | ||
r = string.format( "%s | r = string.format( "%s%s %s %s", | ||
r, | |||
sep, | |||
s, | |||
foreign( t.story, | |||
t.short, | |||
t.slang, | |||
t.script ) ) | |||
sep = follow( t.script ) | |||
end -- for i | end -- for i | ||
return r | return r | ||
Zeile 352: | Zeile 665: | ||
local function | local function friend( assigned, apply ) | ||
-- | -- Transcription unit | ||
-- Returns | -- assigned -- string, transcription ID | ||
if | -- apply -- string, transcription text | ||
Config. | -- Returns string | ||
local e = mw.html.create( "span" ) | |||
:addClass( Config.site ) | |||
:attr( "lang", | |||
string.format( "%s-%s", | |||
Config.slang, | |||
Config.site ) ) | |||
:css( { ["font-weight"] = "normal" } ) | |||
:wikitext( apply ) | |||
local r, s | |||
if Config.site == "Latn" then | |||
s = "italic" | |||
else | |||
s = "normal" | |||
end | |||
e:css( { ["font-style"] = s } ) | |||
if type( Config.transys ) == "table" and | |||
type( Config.transys[ assigned ] ) == "table" then | |||
local transys = Config.transys[ assigned ] | |||
if transys.class then | |||
e:addClass( transys.class ) | |||
end | |||
if transys.show then | |||
s = transys.show | |||
else | |||
s = assigned | |||
end | |||
if transys.support then | |||
if s == transys.support then | |||
s = string.format( "[[%s]]", s ) | |||
else | |||
s = string.format( "[[%s|%s]]", transys.support, s ) | |||
end | |||
end | |||
else | |||
s = assigned | |||
end | end | ||
r = string.format( "%s %s%s", | |||
end -- | s, first( Config.site ), tostring( e ) ) | ||
return r | |||
end -- friend() | |||
Zeile 401: | Zeile 751: | ||
local function full( arglist ) | local function full( arglist ) | ||
-- | -- Finalize invocation of template | ||
-- arglist -- table, with parameters | -- arglist -- table, with parameters | ||
-- Returns appropriate string | -- Returns appropriate string | ||
Zeile 407: | Zeile 757: | ||
if arglist.Text1 then | if arglist.Text1 then | ||
local slang = Config.slang | local slang = Config.slang | ||
local | local lone = true | ||
if Config.scripting == | local s, sep | ||
if not Config.scripting then | |||
Config.scripting = fit( Config.slang ) | |||
end | |||
sep = follow( Config.scripting ) | |||
if Config.scripting == Config.site then | |||
if slang == facility() then | if slang == facility() then | ||
arglist.style = false | arglist.style = false | ||
Zeile 414: | Zeile 769: | ||
arglist.style = "font-style:italic" | arglist.style = "font-style:italic" | ||
end | end | ||
sep = follow( Config.site ) | |||
if arglist.Text2 then | if arglist.Text2 then | ||
arglist.Text2 = fault( "errInvalid", " | arglist.Text2 = fault( "errInvalid", | ||
Config.site .. "+2=", | |||
true ) | |||
end | end | ||
elseif not Config.low and not arglist.style then | elseif not Config.low and not arglist.style then | ||
Zeile 432: | Zeile 790: | ||
arglist.class ) | arglist.class ) | ||
if arglist.Text2 then | if arglist.Text2 then | ||
local e = mw.html.create( "span" ) | |||
:addClass( Config.site ) | |||
:attr( "lang", | |||
string.format( "%s-%s", | |||
r = string.format( "%s %s", r, | Config.slang, | ||
Config.site ) ) | |||
:css( { ["font-weight"] = "normal" } ) | |||
:wikitext( arglist.Text2 ) | |||
if Config.site == "Latn" then | |||
s = "italic" | |||
else | |||
s = "normal" | |||
end | |||
e:css( { ["font-style"] = s } ) | |||
r = string.format( "%s %s%s", | |||
r, | |||
first( Config.site ), | |||
tostring( e ) ) | |||
sep = follow( Config.site ) | |||
lone = false | |||
end | end | ||
if arglist. | if arglist.trans then | ||
local e | |||
for i = 1, #arglist.trans do | |||
e = arglist.trans[ i ] | |||
r = string.format( "%s%s %s", | |||
r, | |||
sep, | |||
friend( e.system, e.story ) ) | |||
sep = follow( Config.site ) | |||
r = string.format( "%s | end -- for i | ||
lone = false | |||
end | |||
end | end | ||
if not Config.low then | if not Config.low then | ||
if Config.scripting then | if Config.scripting then | ||
s = arglist[ Config.scripting ] | s = false | ||
if arglist[ Config.scripting ] and | |||
not arglist.Text2 then | |||
not arglist.Text2 | Fetch( "ISO15924" ) | ||
if Config.ISO15924 then | |||
s = Config.ISO15924 | |||
s = Config. | .scriptName( Config.scripting ) | ||
end | |||
end | |||
if not s and Config.service then | |||
s = facet( Config.service ) | s = facet( Config.service ) | ||
end | end | ||
elseif Config.service then | |||
s = Config.service | |||
else | else | ||
s = | s = false | ||
end | end | ||
if arglist.later then | if s then | ||
if arglist.later then | |||
r = string.format( "%s (%s)", r, s ) | |||
lone = false | |||
else | |||
r = string.format( "%s %s", s, r ) | |||
end | |||
end | end | ||
end | end | ||
if arglist.IPA then | if arglist.IPA then | ||
params = { [1] = arglist.IPA } | local params = { [1] = arglist.IPA } | ||
s = | s = Frame():expandTemplate{ title = Config.ipa, | ||
args = params } | |||
r = string.format( "%s [%s]", r, s ) | r = string.format( "%s [%s]", r, s ) | ||
sep = follow() | |||
lone = false | |||
end | end | ||
if arglist.trsl then | if arglist.trsl then | ||
r = r .. foreigns( arglist.trsl ) | r = r .. foreigns( sep, arglist.trsl, lone ) | ||
end | end | ||
elseif arglist.Text2 then | elseif arglist.Text2 then | ||
r = fault( "errInvalid", "2=" ) | r = fault( "errInvalid", "|1=|2=", true ) | ||
else | else | ||
if Config.sole then | if Config.sole then | ||
Zeile 505: | Zeile 881: | ||
-- argsT -- table, with template parameters | -- argsT -- table, with template parameters | ||
-- Returns appropriate string | -- Returns appropriate string | ||
local parIgnore = { } | |||
local r = { } | local r = { } | ||
local s | local s | ||
Zeile 514: | Zeile 891: | ||
Config.errClasses = argsF.errClasses | Config.errClasses = argsF.errClasses | ||
Config.errNS = argsF.errNS | Config.errNS = argsF.errNS | ||
if argsF.ELEMENT and argsF.ELEMENT:match( "^%a+$" ) then | |||
Config.scope = argsF.ELEMENT:lower() | |||
end | |||
if argsF.SUITABLE then | if argsF.SUITABLE then | ||
local params = mw.text.split( argsF.SUITABLE, " ", true ) | local params = mw.text.split( argsF.SUITABLE, " ", true ) | ||
for k, v in pairs( params ) do | for k, v in pairs( params ) do | ||
parIgnore[ v ] = true | |||
end -- for k, v | end -- for k, v | ||
end | end | ||
Zeile 529: | Zeile 909: | ||
if type( argsT ) == "table" then | if type( argsT ) == "table" then | ||
local n = table.maxn( Config.params ) | local n = table.maxn( Config.params ) | ||
local unknown | local script, unknown | ||
for k, v in pairs( argsT ) do | for k, v in pairs( argsT ) do | ||
v = flatten( v ) | |||
s = type( k ) | s = type( k ) | ||
if s == "number" then | if s == "number" then | ||
Zeile 537: | Zeile 918: | ||
end | end | ||
if k <= 2 then | if k <= 2 then | ||
if k == 0 then | if v then | ||
k = false | if k == 0 then | ||
k = false | |||
else | |||
if k == 1 then | |||
r.Text1 = v | |||
k = false | |||
elseif Config.scripting == Config.site then | |||
k = "2" | |||
else | |||
r.Text2 = v | |||
k = false | |||
end | |||
end | |||
else | else | ||
if not Config.lenient then | |||
-- LEGACY | |||
k = string.format( "%s %s, |%d=", | |||
"Sprachvorlage:", | |||
factory( "errEmpty" ), | |||
k ) | |||
mw.addWarning( k ) | |||
end | end | ||
k = false | |||
end | end | ||
else | else | ||
k = tostring( k ) | k = tostring( k ) | ||
end | end | ||
elseif k:match( "^%l%l%l?-?" ) then | elseif parIgnore[ k ] then | ||
k = false | |||
elseif k:match( "^%l%l%l?%-?" ) then | |||
s = k:match( "^(%l%l%l?)$" ) or | s = k:match( "^(%l%l%l?)$" ) or | ||
k:match( "^(%l%l%l?)-%u%u$" ) or | k:match( "^(%l%l%l?)%-%u%u$" ) or | ||
k:match( "^(%l%l%l?)-%u%l%l%l$" ) | k:match( "^(%l%l%l?)%-%u%l%l%l$" ) | ||
v = mw. | if v then | ||
script = k:match( "^%l%l%l?%-(%u%l%l%l)$" ) | |||
v = false | else | ||
k = false | |||
end | |||
if v and s and | |||
( s ~= Config.slang or | |||
script ~= Config.scripting ) then | |||
local legal = mw.language.isSupportedLanguage( s ) | |||
if not legal then | |||
legal = ( s ~= fill( s ) ) | |||
end | |||
if legal then | |||
local state = k:match( "^%l%l%l?%-(%u%u)$" ) | |||
local m | |||
if s == Config.slang then | |||
m = Config.keyBase | |||
else | |||
m = Config.keyTranslate | |||
end | |||
if not script then | |||
script = fit( s ) | |||
if script then | |||
k = string.format( "%s-%s", s, script ) | |||
end | |||
end | |||
if not r.trsl then | |||
r.trsl = { } | |||
end | |||
table.insert( r.trsl, | |||
{ m = m, | |||
n = #r.trsl + 1, | |||
script = script, | |||
short = s, | |||
slang = k, | |||
state = state, | |||
story = v } ) | |||
k = false | |||
end | |||
end | |||
elseif k:match( "^%u%u+%d*%.?%d*%-?%u*%d*$" ) then | |||
if familiar( k, Config.scripting ) or | |||
familiar( k, Config.slang ) then | |||
if v then | |||
if not r.trans then | |||
r.trans = { } | |||
end | |||
table.insert( r.trans, | |||
{ system = k, | |||
story = v } ) | |||
end | |||
k = false | |||
end | end | ||
if | elseif k:match( "^%u%l%l%l$" ) then | ||
if k == Config.scripting then | |||
if faculty( v ) then | |||
r[ k ] = true | |||
end | |||
else | |||
if not r.trsl then | if not r.trsl then | ||
r.trsl = { } | r.trsl = { } | ||
end | end | ||
table.insert( r.trsl, | table.insert( r.trsl, | ||
{ n | { m = 100, | ||
n = #r.trsl + 1, | |||
slang | script = k, | ||
short = Config.slang, | |||
slang = string.format( "%s-%s", | |||
Config.slang, | |||
k ), | |||
story = v } ) | |||
end | end | ||
k = false | |||
end | end | ||
if k then | if k then | ||
for i = 1, n do | for i = 1, n do | ||
if Config.params[ i ] == k then | if Config.params[ i ] == k then | ||
if v | if v then | ||
r[ k ] = v | r[ k ] = v | ||
end | end | ||
Zeile 610: | Zeile 1.049: | ||
end | end | ||
r.later = faculty( r.nachgestellt ) | r.later = faculty( r.nachgestellt ) | ||
if r.b and Config[ "OBSOLETING- | if r.b and Config[ "OBSOLETING-bwd" ] then | ||
if r.de then | if r.de then | ||
r = fault( "errDoubled", "'de=' und 'b='" ) | r = fault( "errDoubled", "'de=' und 'b='", true ) | ||
else | else | ||
r.de = r.b | r.de = r.b | ||
end | |||
end | |||
if r.w and Config[ "OBSOLETING-bwd" ] then | |||
if r.Text2 then | |||
r = fault( "errDoubled", "'2=' und 'w='", true ) | |||
else | |||
r.Text2 = r.w | |||
end | end | ||
end | end | ||
if unknown then | if unknown then | ||
local e = mw.html.create( "code" ) | |||
:wikitext( table.concat( unknown, " " ) ) | |||
r = fault( "errUnkown", | r = fault( "errUnkown", | ||
string.format( "'%s'", tostring( e ) ), | |||
true ) | |||
end | end | ||
end | end | ||
Zeile 628: | Zeile 1.076: | ||
return r | return r | ||
end -- furnish() | end -- furnish() | ||
Zeile 665: | Zeile 1.101: | ||
end | end | ||
if show then | if show then | ||
show = | show = flatten( show ) | ||
end | end | ||
if slang and show then | if slang and show then | ||
local q = Config.Multilingual.getLang( slang ) | local q = Config.Multilingual.getLang( slang ) | ||
if q then | if q and q.legal then | ||
Config.lenient = faculty( argsT.lenient ) | |||
Config.low = true | Config.low = true | ||
Config.slang = q.base | Config.slang = q.base | ||
Zeile 682: | Zeile 1.116: | ||
:attr( "lang", slang ) | :attr( "lang", slang ) | ||
:wikitext( show ) | :wikitext( show ) | ||
r = tostring( e ) | local list = ( q and q.scream ) | ||
local s | |||
if q and q.suggest then | |||
local say = factory( "errSuggest" ) | |||
s = string.format( say, slang, q.suggest ) | |||
else | |||
s = slang | |||
end | |||
r = tostring( e ) .. | |||
fault( "errInvalid", s, not list ) | |||
if list then | |||
r = string.format( "%s[[Category:%s]]", r, q.scream ) | |||
end | |||
end | end | ||
else | else | ||
r = fault( "errMissing" ) | r = fault( "errMissing", false, true ) | ||
if show then | if show then | ||
r = show .. r | r = show .. r | ||
Zeile 701: | Zeile 1.147: | ||
-- argsT -- table, with template parameters | -- argsT -- table, with template parameters | ||
-- Returns appropriate string, or nil | -- Returns appropriate string, or nil | ||
local params = { | local params = { } | ||
local r, s | local r, s, slang | ||
for | for k, v in pairs( argsT ) do | ||
if | if v then | ||
v = mw.text.trim( v ) | |||
if | if v ~= "" then | ||
params[ | params[ k ] = v | ||
end | end | ||
end | end | ||
end -- for | end -- for k, v | ||
if params[ 2 ] then | if params[ 2 ] then | ||
s = params[ 2 ]:gsub( mw.ustring.char( 8206 ), "‎" ) | s = params[ 2 ]:gsub( mw.ustring.char( 0x202A ), "" ) | ||
:gsub( mw.ustring.char( 0x202B ), "" ) | |||
:gsub( mw.ustring.char( 0x202C ), "" ) | |||
:gsub( mw.ustring.char( 0x202D ), "" ) | |||
:gsub( mw.ustring.char( 0x202E ), "" ) | |||
:gsub( mw.ustring.char( 0x2066 ), "" ) | |||
:gsub( mw.ustring.char( 0x2067 ), "" ) | |||
:gsub( mw.ustring.char( 0x2068 ), "" ) | |||
:gsub( mw.ustring.char( 0x2069 ), "" ) | |||
:gsub( mw.ustring.char( 8206 ), "‎" ) | |||
:gsub( "�*8206;", "‎" ) | :gsub( "�*8206;", "‎" ) | ||
:gsub( "�*200[Ee];", "‎" ) | :gsub( "�*200[Ee];", "‎" ) | ||
Zeile 731: | Zeile 1.186: | ||
end | end | ||
end | end | ||
end | |||
if s and | |||
s:sub( 1, 5 ) == "<bdo " and | |||
s:find( "^<bdo [^<>]+><bdi [^<>]+>[^<>]+</bdi></bdo>$" ) then | |||
r = s | |||
s = false | |||
end | end | ||
if s then | if s then | ||
local bdi = mw.html.create( "bdi" ) | local bdi = mw.html.create( "bdi" ) | ||
:attr( "dir", "rtl" ) | |||
:css( "unicode-bidi", "isolate" ) | |||
:wikitext( s ) | |||
local bdo = mw.html.create( "bdo" ) | |||
local bdo = mw.html.create( "bdo" ) | :attr( "dir", "ltr" ) | ||
local slang = params[ 1 ] | |||
local script = argsF.SCRIPTING | |||
if | local state = argsF.STATE | ||
bdi:addClass( | local selector | ||
family() | |||
if slang then | |||
if slang:find( "-", 3, true ) then | |||
local parts = mw.text.split( slang, "-", true ) | |||
slang = parts[ 1 ] | |||
for i = 2, #parts do | |||
if parts[ i ]:match( "^%u%u$" ) then | |||
state = parts[ i ] | |||
elseif parts[ i ]:match( "^%u%l%l%l$" ) then | |||
script = parts[ i ] | |||
end | |||
end -- for i | |||
end | |||
slang = slang:lower() | |||
else | |||
slang = "ar" | |||
end | |||
if script then | |||
first( script, bdo ) | |||
features( bdi, script ) | |||
selector = script | |||
if type( Config.classScript ) == "table" then | |||
selector = flag( selector, Config.classScript[ script ] ) | |||
end | |||
s = string.format( "%s-%s", slang, script ) | |||
else | |||
s = slang | |||
end | |||
if state then | |||
s = string.format( "%s-%s", s, state ) | |||
end | |||
bdi:attr( "lang", s ) | |||
selector = flag( selector, argsF.class ) | |||
selector = flag( selector, params.class ) | |||
if selector then | |||
bdi:addClass( selector ) | |||
end | |||
if argsF.css then | |||
bdi:css( argsF.css ) | |||
end | end | ||
if | if argsF.style then | ||
bdi:cssText( | bdi:cssText( argsF.style ) | ||
end | end | ||
if params.style then | |||
bdi:cssText( params.style ) | |||
end | |||
bdo:node( bdi ) | |||
r = tostring( bdo ) | r = tostring( bdo ) | ||
end | end | ||
Zeile 762: | Zeile 1.266: | ||
-- alike -- string, with additional class(es), or nil | -- alike -- string, with additional class(es), or nil | ||
-- Returns appropriate string with HTML tag | -- Returns appropriate string with HTML tag | ||
local | local ltr = true | ||
local | local r, script, selector, slang, state | ||
if appear then | family() | ||
if alien:find( "-", 3, true ) then | |||
local parts = mw.text.split( alien, "-", true ) | |||
slang = parts[ 1 ] | |||
for i = 2, #parts do | |||
if parts[ i ]:match( "^%u%u$" ) then | |||
state = parts[ i ] | |||
elseif parts[ i ]:match( "^%u%l%l%l$" ) then | |||
script = parts[ i ] | |||
end | |||
end -- for i | |||
else | |||
slang = alien | |||
end | |||
slang = slang:lower() | |||
if not script then | |||
script = fit( slang ) | |||
end | |||
if script then | |||
local rtl = Friend().rtl | |||
if type( rtl ) == "table" then | |||
ltr = not rtl[ script ] | |||
end | |||
if script ~= Config.site then | |||
selector = script | |||
if type( Config.classScript ) == "table" then | |||
selector = flag( selector, Config.classScript[ script ] ) | |||
end | |||
end | |||
end | |||
selector = flag( selector, alike ) | |||
if ltr then | |||
local scope = Config.scope or "span" | |||
local elem = mw.html.create( scope ) | |||
local story = apply | |||
local set | |||
if script then | |||
set = string.format( "%s-%s", slang, script ) | |||
features( elem, script ) | |||
else | |||
set = slang | |||
end | |||
if state then | |||
set = string.format( "%s-%s", set, state ) | |||
end | |||
elem:attr( "lang", set ) | |||
if selector then | |||
elem:addClass( selector ) | |||
end | |||
if appear then | |||
elem:cssText( appear ) | |||
end | |||
if scope == "span" then | |||
story = story:gsub( "\n", " " ) | |||
end | |||
elem:wikitext( story ) | |||
r = tostring( elem ) | |||
if script and script ~= Config.site then | |||
local lucky, x = pcall( require, | |||
"Module:Vorlage:lang/Zwiebelfisch" ) | |||
r = first( script ) .. r | |||
if type( x ) == "table" and | |||
type( x.finder ) == "function" then | |||
x = x.finder( apply, script ) | |||
if type( x ) == "string" then | |||
r = r .. x | |||
end | |||
end | |||
end | |||
else | |||
r = Export.fold( { SCRIPTING = script }, | |||
{ [ 1 ] = slang, | |||
[ 2 ] = apply, | |||
class = selector, | |||
style = appear } ) | |||
end | end | ||
if | if mw.text.unstrip( apply ):sub( 1, 1 ) == "<" then | ||
local seek = "^(<([sd][paniv]+) [^>]+>)%1(.+)(</%2>)%4$" | |||
local s, start, story, stop | |||
start, s, story, stop = mw.text.unstrip( r ):match( seek ) | |||
if story then | |||
r = Export.format( slang, story, appear, audio, alike ) | |||
end | |||
end | end | ||
if audio and Config.tmplAudio then | if audio and Config.tmplAudio then | ||
params = { [ Config.tmplAudio.filepar ] = audio, | local params = { [ Config.tmplAudio.filepar ] = audio, | ||
[ Config.tmplAudio.textpar ] = r } | |||
r = | r = Frame():expandTemplate{ title = Config.tmplAudio.title, | ||
args = params } | args = params } | ||
end | end | ||
return r | return r or "" | ||
end -- Export.format() | end -- Export.format() | ||
Zeile 789: | Zeile 1.369: | ||
-- Returns appropriate string | -- Returns appropriate string | ||
if argsF then | if argsF then | ||
Config.lenient = faculty( argsF.lenient ) | |||
Config.long = faculty( argsF.LONG ) | Config.long = faculty( argsF.LONG ) | ||
Config.scripting = argsF.SCRIPTING | Config.scripting = argsF.SCRIPTING | ||
Zeile 794: | Zeile 1.375: | ||
Config.slang = argsF.CODE | Config.slang = argsF.CODE | ||
Config.sole = argsF.SOLE | Config.sole = argsF.SOLE | ||
if | if argsF["OBSOLETING-bwd"] then | ||
table.insert( Config.params, "b" ) | table.insert( Config.params, "b" ) | ||
table.insert( Config.params, "d" ) | |||
table.insert( Config.params, "w" ) | table.insert( Config.params, "w" ) | ||
end | end | ||
Zeile 802: | Zeile 1.384: | ||
return furnish( argsF, argsT ) | return furnish( argsF, argsT ) | ||
end -- Export.full() | end -- Export.full() | ||
Failsafe.failsafe = function ( atleast ) | |||
-- Retrieve versioning and check for compliance | |||
-- Precondition: | |||
-- atleast -- string, with required version or "wikidata" or "~" | |||
-- or false | |||
-- Postcondition: | |||
-- Returns string -- with queried version, also if problem | |||
-- false -- if appropriate | |||
local last = ( atleast == "~" ) | |||
local since = atleast | |||
local r | |||
if last or since == "wikidata" then | |||
local item = Failsafe.item | |||
since = false | |||
if type( item ) == "number" and item > 0 then | |||
local entity = mw.wikibase.getEntity( string.format( "Q%d", | |||
item ) ) | |||
if type( entity ) == "table" then | |||
local vsn = entity:formatPropertyValues( "P348" ) | |||
if type( vsn ) == "table" and | |||
type( vsn.value ) == "string" and | |||
vsn.value ~= "" then | |||
if last and vsn.value == Failsafe.serial then | |||
r = false | |||
else | |||
r = vsn.value | |||
end | |||
end | |||
end | |||
end | |||
end | |||
if type( r ) == "nil" then | |||
if not since or since <= Failsafe.serial then | |||
r = Failsafe.serial | |||
else | |||
r = false | |||
end | |||
end | |||
return r | |||
end -- Failsafe.failsafe() | |||
Zeile 807: | Zeile 1.432: | ||
-- Export | -- Export | ||
local p = { } | local p = { } | ||
Zeile 816: | Zeile 1.440: | ||
return frontend( action, argsF, argsT ) | return frontend( action, argsF, argsT ) | ||
end -- p.test() | end -- p.test() | ||
Zeile 829: | Zeile 1.445: | ||
return frontier( frame, "flat" ) | return frontier( frame, "flat" ) | ||
end -- p.flat() | end -- p.flat() | ||
Zeile 835: | Zeile 1.450: | ||
return frontier( frame, "fold" ) or "" | return frontier( frame, "fold" ) or "" | ||
end -- p.fold() | end -- p.fold() | ||
Zeile 845: | Zeile 1.459: | ||
p.failsafe = function ( frame ) | p.failsafe = function ( frame ) | ||
-- Versioning interface | |||
local s = type( frame ) | local s = type( frame ) | ||
local since | local since | ||
Zeile 858: | Zeile 1.473: | ||
end | end | ||
end | end | ||
return | return Failsafe.failsafe( since ) or "" | ||
end -- p.failsafe | end -- p.failsafe | ||
Skriptfehler: Ein solches Modul „Vorlage:LuaModuleDoc“ ist nicht vorhanden.
local Export = { serial = "2019-10-19", suite = "lang", item = 26826825 } --[=[ Vorlage:lang und Sprachnamenvorlagen usw. unterstützen ]=] local Failsafe = Export local GlobalMod = Export local Config = { errCat = false, errClass = "error_lang", errClasses = false, errHide = true, errNS = false, errDoubled = { en = "Doubled:", de = "Doppelangabe:" }, errEmpty = { en = "Empty parameter value", de = "Parameterwert fehlt" }, errInvalid = { en = "Invalid:", de = "Ungültig:" }, errMissing = { en = "Missing parameter", de = "Parameter fehlt" }, errSuggest = { en = "'%s' * probably '%s' intended", de = "'%s' * vermutlich ist '%s' gemeint" }, errUnkown = { en = "Unkown parameter:", de = "Parameter unbekannt:" }, ipa = "IPA", keyBase = 100, keyProject = 200, keyAncient = 300, keyTranslate = 400, params = { "Text1", "Audio", "IPA", "class", "lenient", "script", "style", "nachgestellt", "demo", "demo2", "demo3", "demo4", "NoCat" }, percents = false, orderOther = { grc = 1, hbo = 2, la = 3, en = 9 }, owns = { de = "‚%s‘" }, sepComma = "Latn Armn Cyrl Grek Thai", site = "Latn", tmplAudio = false, -- template for media player link tmplLang = false, -- template for language name link tmplStyles = false, wikidata = { Multilingual = 47541920, ISO15924 = 71584769, ["ISO15924/codes"] = 71840276, TemplUtl = 52364930 } } local foreignModule = function ( access, advanced, append, alt, alert ) -- Fetch global module -- Precondition: -- access -- string, with name of base module -- advanced -- true, for require(); else mw.loadData() -- append -- string, with subpage part, if any; or false -- alt -- number, of wikidata item of root; or false -- alert -- true, for throwing error on data problem -- Postcondition: -- Returns whatever, probably table -- 2019-10-29 local storage = access local finer = function () if append then storage = string.format( "%s/%s", storage, append ) end end local fun, lucky, r, suited if advanced then fun = require else fun = mw.loadData end GlobalMod.globalModules = GlobalMod.globalModules or { } suited = GlobalMod.globalModules[ access ] if not suited then finer() lucky, r = pcall( fun, "Module:" .. storage ) end if not lucky then if not suited and type( alt ) == "number" and alt > 0 then suited = string.format( "Q%d", alt ) suited = mw.wikibase.getSitelink( suited ) GlobalMod.globalModules[ access ] = suited or true end if type( suited ) == "string" then storage = suited finer() lucky, r = pcall( fun, storage ) end if not lucky and alert then error( "Missing or invalid page: " .. storage, 0 ) end end return r end -- foreignModule() local function Fetch( ask ) -- Fetch module (require) -- Parameter: -- ask -- string, with name -- "ISO15924" -- "Multilingual" -- "TemplUtl" -- Returns string, with error message, if not available local ext = Config[ ask ] local r if not ext and ext ~= false then ext = foreignModule( ask, true, false, Config.wikidata[ ask ] ) if type( ext ) == "table" then Config[ ask ] = ext if type( ext[ ask ] ) == "function" then Config[ ask ] = ext[ ask ]() end end if type( Config[ ask ] ) ~= "table" then Config[ ask ] = false if not ext then ext = "Invalid library *** Module:" .. ask end ext = mw.html.create( "span" ) :attr( "class", "error" ) :wikitext( ext ) r = tostring( ext ) end end return r end -- Fetch() local function Frame() -- Fetch current frame -- Returns frame if not Config.frame then Config.frame = mw.getCurrentFrame() end return Config.frame end -- Frame() local function Friend() -- Fetch Module:ISO15924/codes if not Config.codesISO15924 then Config.codesISO15924 = foreignModule( "ISO15924", false, "codes", Config.wikidata.ISO15924 ) if type( Config.codesISO15924 ) ~= "table" then Config.codesISO15924 = { } end end return Config.codesISO15924 end -- Friend() local function Fulfil( access, args ) -- Expand template -- apply -- string, with template name -- args -- table, with parameters -- Returns string -- Throws error, if template not existing return Frame():expandTemplate{ title = access, args = args } end -- Fulfil() local function facet( assign ) -- Format language name -- apply -- string, with language name, might be linked -- Returns string local e = mw.html.create( "span" ) :css( { ["font-style"] = "normal", ["font-weight"] = "normal" } ) :wikitext( assign ) return tostring( e ) end -- facet() local function facility() -- Fetch current site language -- Returns language code if not Config.standard then Config.standard = mw.language.getContentLanguage():getCode() end return Config.standard end -- facility() local function factory( apply ) -- Localization of messages -- apply -- string, with message key -- Returns message text; at least english local entry = Config[ apply ] local r if entry then r = entry[ facility() ] if not r then r = entry.en end else local e = mw.html.create( "span" ) :attr( "class", "error" ) :wikitext( string.format( "????.%s.????", apply ) ) r = tostring( e ) end return r 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" and r ~= "-" ) elseif s == "boolean" then r = adjust else r = false end return r end -- faculty() local function familiar( ask, assign ) -- Check whether valid transcription for context -- ask -- string, with transcription code -- assign -- string or nil, with language or scripting key -- Returns boolean local r Fetch( "ISO15924" ) if Config.ISO15924 then r = Config.ISO15924.isTrans( ask, assign, Config.site ) end return r end -- familiar() local function family() -- attempt to load local config if not Config.data then local sub = string.format( "%s/config", Frame():getTitle() ) local lucky lucky, Config.data = pcall( mw.loadData, sub ) if type( Config.data ) == "table" then for k, v in pairs( Config.data ) do Config[ k ] = v end -- for k, v else Config.data = sub .. " not found" end end end -- family() local function fault( alert, about, assign ) -- Format message with class="error" or similar -- alert -- string, with message key -- about -- string, with explanation -- assign -- true, when standard category to be fired -- Returns message with markup local story = factory( alert ) local env = Frame():getParent() local err = mw.html.create( "span" ) local r err:addClass( Config.errClass ) :css( { ["margin-left"] = "1em", ["margin-right"] = "1em" } ) family() if env then story = string.format( "[[%s]] – %s", env:getTitle(), story ) end if about then story = string.format( "%s %s", story, about ) end if Config.errClasses then err:addClass( Config.errClasses ) end err:wikitext( story ) r = Fetch( "TemplUtl" ) if Config.TemplUtl then r = Config.TemplUtl.failure( tostring( err ), not Config.errHide, false, Frame() ) end if assign and type( Config.errCat ) == "string" then if Config.errNS then local ns = mw.title.getCurrentTitle().namespace local st = type( Config.errNS ) if st == "string" then local space = string.format( ".*%%s%d%%s.*", ns ) local spaces = string.format( " %s ", Config.errNS ) if spaces:match( space ) then Config.errNS = false end elseif st == "table" then for i = 1, #Config.errNS do if Config.errNS[ i ] == ns then Config.errNS = false break -- for i end end -- for i end end if not Config.errNS then r = string.format( "%s[[Category:%s]]", r, Config.errCat ) end end return r end -- fault() local function features( apply, assign ) -- Equip element with script attributes -- apply -- mw.html element -- assign -- string, with script code if type( Config.percents ) == "table" then local more = Config.percents[ assign ] if more then apply:css( "font-size", string.format( "%d%%", more ) ) end end end -- features() local function fill( apply ) -- Expand language name template -- apply -- string, with code -- Returns string, identical apply in case of error local r = apply local template family() template = Config.tmplLang if type( template ) == "table" then local source = template.title if type( source ) ~= "string" then if type( template.namePat ) == "string" and template.namePat:find( "%s", 1, true ) then source = string.format( template.namePat, apply ) end end if type( source ) == "string" then local lucky, s = pcall( Fulfil, source ) if lucky then r = s end end end return r end -- fill() local function first( assign, apply ) -- Equip element with TemplateStyles -- assign -- string, with script code -- apply -- mw.html element, or false -- Returns string, perhaps with tag local r if type( Config.tmplStyles ) == "table" then local source = Config.tmplStyles[ assign ] if source then r = Frame():extensionTag( "templatestyles", nil, { src = source } ) if apply then apply:wikitext( r ) end end end return r or "" end -- first() local function fit( acquire ) -- Retrieve script code for language -- acquire -- string, with language code -- Returns string or false local r local iso639script = Friend().iso639script if type( iso639script ) == "table" then r = iso639script[ acquire ] if type( r ) == "table" then r = r[ 1 ] end end return r end -- fit() local function flag( already, apply ) -- Check whether space separated classes contain -- already -- string or false, with classes -- apply -- string or false, with single class -- Returns true, if apply is in already local r if already then if apply then local classes = mw.text.split( already, "%s+" ) local plus = mw.text.split( apply, "%s+" ) local single for i = 1, #plus do single = plus[ i ] for k = 1, #classes do if classes[ k ] == single then single = false break -- for k end end -- for k if single then table.insert( classes, single ) end end -- for i r = table.concat( classes, " " ) else r = already end else r = apply end return r end -- flag() local function flatten( apply ) -- Trim any whitespace, even HTML encoded -- apply -- string -- Returns string, or false if empty local r = apply if r:find( "&" ) then r = r:gsub( " ", " " ) :gsub( " ", " " ) :gsub( "‌", "‌" ) :gsub( "‍", "‍" ) :gsub( "‎", "‎" ) :gsub( "‏", "‏" ) if r:find( "&#" ) then local f = function ( ax, an ) local k if ax == "x" then k = 16 else k = 10 end return mw.ustring.char( tonumber( an, k ) ) end r = r:gsub( "&#(x?)(%x+);", f ) end end if not Config.patternWS then Config.patternWS = mw.ustring.char( 91, 1, 45, 32, 160, 8194, 45, 8207, 8239, 93, 43 ) end r = mw.ustring.gsub( r, "^" .. Config.patternWS, "" ) r = mw.ustring.gsub( r, Config.patternWS .. "$", "" ) if r == "" then r = false end return r end -- flatten() local function follow( affine ) -- Retrieve appropriate separator -- affine -- string or nil, with code of script -- Returns string, with separator (comma) or not local r if affine then if Config.sepComma:find( affine, 1, true ) then r = "," else r = "" end else r = "," end return r end -- follow() local function foreign( apply, acquire, advanced, affine ) -- Format text in some language -- apply -- string, with text -- acquire -- string, with basic code of language -- advanced -- string, with full code of language -- affine -- string or nil, with code of script -- Returns string local story = apply local script = affine local p = { ["font-weight"] = "normal" } local ltr, r if advanced == acquire then ltr = not mw.language.new( acquire ):isRTL() elseif not script and advanced:find( "-", 3, true ) then local parts = mw.text.split( advanced, "-", true ) if #parts > 1 and parts[ 2 ]:match( "^%u%l%l%l$" ) then script = parts[ 2 ] end end if script then local rtl = Friend().rtl if type( rtl ) == "table" then ltr = not rtl[ script ] end end if ltr then local e = mw.html.create( "span" ) :attr( "lang", advanced ) local s = "normal" if acquire == facility() and Config.owns[ acquire ] then story = string.format( Config.owns[ acquire ], apply ) elseif advanced == acquire and Config.site == "Latn" or advanced == acquire .. "-Latn" then s = "italic" end p["font-style"] = s e:css( p ) :wikitext( story ) r = tostring( e ) else p["font-style"] = "normal" r = Export.fold( { css = p, SCRIPTING = script }, { [ 1 ] = acquire, [ 2 ] = apply, lang = advanced } ) end return r end -- foreign() local function foreigns( ahead, aliens, alone ) -- Create list of translations -- ahead -- string, with leading separator -- aliens -- sequence table, with assignment tables -- alone -- boolean, no other elements in collection yet -- Returns string, starting with separator (comma) local pars = { } local sep = ahead local lone = alone local r = "" local k, lucky, s, t family() facility() Fetch( "Multilingual" ) for i = 1, #aliens do t = aliens[ i ] if t.short == Config.standard then t.m = Config.keyProject t.n = 0 else k = Config.orderOther[ t.short ] if k then t.n = k t.m = Config.keyAncient end lone = false end t.n = t.m + t.n end -- for i table.sort( aliens, function ( a1, a2 ) return ( a1.n < a2.n ) end ) for i = 1, #aliens do t = aliens[ i ] if lone then s = "" sep = "" else s = false if t.short == Config.slang and t.script and t.n > 0 then Fetch( "ISO15924" ) if Config.ISO15924 then s = Config.ISO15924.scriptName( t.script ) if s == t.script then s = false end end end if not s and t.n > Config.keyProject then s = fill( t.short ) end if not s then Fetch( "Multilingual" ) s = mw.language.fetchLanguageName( t.short, Config.standard ) if Config.Multilingual and Config.Multilingual.isMinusculable( s ) then s = mw.ustring.lower( mw.ustring.sub( s, 1, 1 ) ) .. mw.ustring.sub( s, 2 ) end end end r = string.format( "%s%s %s %s", r, sep, s, foreign( t.story, t.short, t.slang, t.script ) ) sep = follow( t.script ) end -- for i return r end -- foreigns() local function friend( assigned, apply ) -- Transcription unit -- assigned -- string, transcription ID -- apply -- string, transcription text -- Returns string local e = mw.html.create( "span" ) :addClass( Config.site ) :attr( "lang", string.format( "%s-%s", Config.slang, Config.site ) ) :css( { ["font-weight"] = "normal" } ) :wikitext( apply ) local r, s if Config.site == "Latn" then s = "italic" else s = "normal" end e:css( { ["font-style"] = s } ) if type( Config.transys ) == "table" and type( Config.transys[ assigned ] ) == "table" then local transys = Config.transys[ assigned ] if transys.class then e:addClass( transys.class ) end if transys.show then s = transys.show else s = assigned end if transys.support then if s == transys.support then s = string.format( "[[%s]]", s ) else s = string.format( "[[%s|%s]]", transys.support, s ) end end else s = assigned end r = string.format( "%s %s%s", s, first( Config.site ), tostring( e ) ) return r end -- friend() local function frontend( action, argsF, argsT, about ) -- Template service -- action -- string, "flat" or "full" etc. -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters -- about -- string or nil, invocation name -- Returns frame local lucky, r lucky, r = pcall( Export[ action ], argsF, argsT ) if not lucky then local e = mw.html.create( "span" ) :attr( "class", "error" ) if about then r = string.format( "{{%s}} %s", about, r ) end e:wikitext( r ) r = tostring( e ) end return r end -- frontend() local function frontier( frame, action ) -- Template transclusion -- frame -- object -- action -- string, "flat" or "full" etc. -- Returns appropriate string Config.frame = frame return frontend( action, frame.args, frame:getParent().args, frame:getTitle() ) end -- frontier() local function full( arglist ) -- Finalize invocation of template -- arglist -- table, with parameters -- Returns appropriate string local r if arglist.Text1 then local slang = Config.slang local lone = true local s, sep if not Config.scripting then Config.scripting = fit( Config.slang ) end sep = follow( Config.scripting ) if Config.scripting == Config.site then if slang == facility() then arglist.style = false elseif not arglist.style then arglist.style = "font-style:italic" end sep = follow( Config.site ) if arglist.Text2 then arglist.Text2 = fault( "errInvalid", Config.site .. "+2=", true ) end elseif not Config.low and not arglist.style then arglist.style = "font-style:normal" end if Config.state then slang = string.format( "%s-%s", slang, Config.state ) end if Config.scripting then slang = string.format( "%s-%s", slang, Config.scripting ) end r = Export.format( slang, arglist.Text1, arglist.style, arglist.Audio, arglist.class ) if arglist.Text2 then local e = mw.html.create( "span" ) :addClass( Config.site ) :attr( "lang", string.format( "%s-%s", Config.slang, Config.site ) ) :css( { ["font-weight"] = "normal" } ) :wikitext( arglist.Text2 ) if Config.site == "Latn" then s = "italic" else s = "normal" end e:css( { ["font-style"] = s } ) r = string.format( "%s %s%s", r, first( Config.site ), tostring( e ) ) sep = follow( Config.site ) lone = false end if arglist.trans then local e for i = 1, #arglist.trans do e = arglist.trans[ i ] r = string.format( "%s%s %s", r, sep, friend( e.system, e.story ) ) sep = follow( Config.site ) end -- for i lone = false end if not Config.low then if Config.scripting then s = false if arglist[ Config.scripting ] and not arglist.Text2 then Fetch( "ISO15924" ) if Config.ISO15924 then s = Config.ISO15924 .scriptName( Config.scripting ) end end if not s and Config.service then s = facet( Config.service ) end elseif Config.service then s = Config.service else s = false end if s then if arglist.later then r = string.format( "%s (%s)", r, s ) lone = false else r = string.format( "%s %s", s, r ) end end end if arglist.IPA then local params = { [1] = arglist.IPA } s = Frame():expandTemplate{ title = Config.ipa, args = params } r = string.format( "%s [%s]", r, s ) sep = follow() lone = false end if arglist.trsl then r = r .. foreigns( sep, arglist.trsl, lone ) end elseif arglist.Text2 then r = fault( "errInvalid", "|1=|2=", true ) else if Config.sole then r = Config.sole else r = Config.service end end return r end -- full() local function furnish( argsF, argsT ) -- General entry point; basic argument consumption -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters -- Returns appropriate string local parIgnore = { } local r = { } local s if argsF then if argsF.errHide ~= nil then Config.errHide = faculty( argsF.errHide ) end Config.errCat = argsF.errCat Config.errClasses = argsF.errClasses Config.errNS = argsF.errNS if argsF.ELEMENT and argsF.ELEMENT:match( "^%a+$" ) then Config.scope = argsF.ELEMENT:lower() end if argsF.SUITABLE then local params = mw.text.split( argsF.SUITABLE, " ", true ) for k, v in pairs( params ) do parIgnore[ v ] = true end -- for k, v end end if Config.scripting == "" then Config.scripting = false end if Config.scripting then table.insert( Config.params, Config.scripting ) end if type( argsT ) == "table" then local n = table.maxn( Config.params ) local script, unknown for k, v in pairs( argsT ) do v = flatten( v ) s = type( k ) if s == "number" then if Config.low then k = k - 1 end if k <= 2 then if v then if k == 0 then k = false else if k == 1 then r.Text1 = v k = false elseif Config.scripting == Config.site then k = "2" else r.Text2 = v k = false end end else if not Config.lenient then -- LEGACY k = string.format( "%s %s, |%d=", "Sprachvorlage:", factory( "errEmpty" ), k ) mw.addWarning( k ) end k = false end else k = tostring( k ) end elseif parIgnore[ k ] then k = false elseif k:match( "^%l%l%l?%-?" ) then s = k:match( "^(%l%l%l?)$" ) or k:match( "^(%l%l%l?)%-%u%u$" ) or k:match( "^(%l%l%l?)%-%u%l%l%l$" ) if v then script = k:match( "^%l%l%l?%-(%u%l%l%l)$" ) else k = false end if v and s and ( s ~= Config.slang or script ~= Config.scripting ) then local legal = mw.language.isSupportedLanguage( s ) if not legal then legal = ( s ~= fill( s ) ) end if legal then local state = k:match( "^%l%l%l?%-(%u%u)$" ) local m if s == Config.slang then m = Config.keyBase else m = Config.keyTranslate end if not script then script = fit( s ) if script then k = string.format( "%s-%s", s, script ) end end if not r.trsl then r.trsl = { } end table.insert( r.trsl, { m = m, n = #r.trsl + 1, script = script, short = s, slang = k, state = state, story = v } ) k = false end end elseif k:match( "^%u%u+%d*%.?%d*%-?%u*%d*$" ) then if familiar( k, Config.scripting ) or familiar( k, Config.slang ) then if v then if not r.trans then r.trans = { } end table.insert( r.trans, { system = k, story = v } ) end k = false end elseif k:match( "^%u%l%l%l$" ) then if k == Config.scripting then if faculty( v ) then r[ k ] = true end else if not r.trsl then r.trsl = { } end table.insert( r.trsl, { m = 100, n = #r.trsl + 1, script = k, short = Config.slang, slang = string.format( "%s-%s", Config.slang, k ), story = v } ) end k = false end if k then for i = 1, n do if Config.params[ i ] == k then if v then r[ k ] = v end k = false break -- for i end end -- for i end if k then if not unknown then unknown = { } end table.insert( unknown, k ) end end -- for k, v if r.demo or faculty( r.NoCat ) then Config.errCat = 0 Config.errHide = false end r.later = faculty( r.nachgestellt ) if r.b and Config[ "OBSOLETING-bwd" ] then if r.de then r = fault( "errDoubled", "'de=' und 'b='", true ) else r.de = r.b end end if r.w and Config[ "OBSOLETING-bwd" ] then if r.Text2 then r = fault( "errDoubled", "'2=' und 'w='", true ) else r.Text2 = r.w end end if unknown then local e = mw.html.create( "code" ) :wikitext( table.concat( unknown, " " ) ) r = fault( "errUnkown", string.format( "'%s'", tostring( e ) ), true ) end end if type( r ) == "table" then r = full( r ) end return r end -- furnish() Export.flat = function ( argsF, argsT, auxilary ) -- Invocation of basic language template -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters -- auxilary -- Multilingual library, or false -- Returns appropriate string local r if type( auxilary ) == "table" then Config.Multilingual = auxilary else r = Fetch( "Multilingual" ) end if Config.Multilingual then local slang = argsT[ 1 ] local show = argsT[ 2 ] if slang then slang = mw.text.trim( slang ) if slang == "" then slang = false end end if show then show = flatten( show ) end if slang and show then local q = Config.Multilingual.getLang( slang ) if q and q.legal then Config.lenient = faculty( argsT.lenient ) Config.low = true Config.slang = q.base Config.state = q.region Config.scripting = q.script r = furnish( argsF, argsT ) else local e = mw.html.create( "span" ) :attr( "lang", slang ) :wikitext( show ) local list = ( q and q.scream ) local s if q and q.suggest then local say = factory( "errSuggest" ) s = string.format( say, slang, q.suggest ) else s = slang end r = tostring( e ) .. fault( "errInvalid", s, not list ) if list then r = string.format( "%s[[Category:%s]]", r, q.scream ) end end else r = fault( "errMissing", false, true ) if show then r = show .. r end end end return r end -- Export.flat() Export.fold = function ( argsF, argsT ) -- Invocation of RTL template -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters -- Returns appropriate string, or nil local params = { } local r, s, slang for k, v in pairs( argsT ) do if v then v = mw.text.trim( v ) if v ~= "" then params[ k ] = v end end end -- for k, v if params[ 2 ] then s = params[ 2 ]:gsub( mw.ustring.char( 0x202A ), "" ) :gsub( mw.ustring.char( 0x202B ), "" ) :gsub( mw.ustring.char( 0x202C ), "" ) :gsub( mw.ustring.char( 0x202D ), "" ) :gsub( mw.ustring.char( 0x202E ), "" ) :gsub( mw.ustring.char( 0x2066 ), "" ) :gsub( mw.ustring.char( 0x2067 ), "" ) :gsub( mw.ustring.char( 0x2068 ), "" ) :gsub( mw.ustring.char( 0x2069 ), "" ) :gsub( mw.ustring.char( 8206 ), "‎" ) :gsub( "�*8206;", "‎" ) :gsub( "�*200[Ee];", "‎" ) :gsub( mw.ustring.char( 8207 ), "‏" ) :gsub( "�*8207;", "‏" ) :gsub( "�*200[Ff];", "‏" ) if s:find( "&", 1, true ) then local shift = "^‏%s*" while s:match( shift ) do s = s:gsub( shift, "" ) end -- while shift = "%s*‎$" while s:match( shift ) do s = s:gsub( shift, "" ) end -- while if s == "" then s = false end end end if s and s:sub( 1, 5 ) == "<bdo " and s:find( "^<bdo [^<>]+><bdi [^<>]+>[^<>]+</bdi></bdo>$" ) then r = s s = false end if s then local bdi = mw.html.create( "bdi" ) :attr( "dir", "rtl" ) :css( "unicode-bidi", "isolate" ) :wikitext( s ) local bdo = mw.html.create( "bdo" ) :attr( "dir", "ltr" ) local slang = params[ 1 ] local script = argsF.SCRIPTING local state = argsF.STATE local selector family() if slang then if slang:find( "-", 3, true ) then local parts = mw.text.split( slang, "-", true ) slang = parts[ 1 ] for i = 2, #parts do if parts[ i ]:match( "^%u%u$" ) then state = parts[ i ] elseif parts[ i ]:match( "^%u%l%l%l$" ) then script = parts[ i ] end end -- for i end slang = slang:lower() else slang = "ar" end if script then first( script, bdo ) features( bdi, script ) selector = script if type( Config.classScript ) == "table" then selector = flag( selector, Config.classScript[ script ] ) end s = string.format( "%s-%s", slang, script ) else s = slang end if state then s = string.format( "%s-%s", s, state ) end bdi:attr( "lang", s ) selector = flag( selector, argsF.class ) selector = flag( selector, params.class ) if selector then bdi:addClass( selector ) end if argsF.css then bdi:css( argsF.css ) end if argsF.style then bdi:cssText( argsF.style ) end if params.style then bdi:cssText( params.style ) end bdo:node( bdi ) r = tostring( bdo ) end return r end -- Export.fold() Export.format = function ( alien, apply, appear, audio, alike ) -- Markup foreign language text -- alien -- string, with language code -- apply -- string, with text -- appear -- string, with additional CSS, or nil -- audio -- string, with title of an audio file, or nil -- alike -- string, with additional class(es), or nil -- Returns appropriate string with HTML tag local ltr = true local r, script, selector, slang, state family() if alien:find( "-", 3, true ) then local parts = mw.text.split( alien, "-", true ) slang = parts[ 1 ] for i = 2, #parts do if parts[ i ]:match( "^%u%u$" ) then state = parts[ i ] elseif parts[ i ]:match( "^%u%l%l%l$" ) then script = parts[ i ] end end -- for i else slang = alien end slang = slang:lower() if not script then script = fit( slang ) end if script then local rtl = Friend().rtl if type( rtl ) == "table" then ltr = not rtl[ script ] end if script ~= Config.site then selector = script if type( Config.classScript ) == "table" then selector = flag( selector, Config.classScript[ script ] ) end end end selector = flag( selector, alike ) if ltr then local scope = Config.scope or "span" local elem = mw.html.create( scope ) local story = apply local set if script then set = string.format( "%s-%s", slang, script ) features( elem, script ) else set = slang end if state then set = string.format( "%s-%s", set, state ) end elem:attr( "lang", set ) if selector then elem:addClass( selector ) end if appear then elem:cssText( appear ) end if scope == "span" then story = story:gsub( "\n", " " ) end elem:wikitext( story ) r = tostring( elem ) if script and script ~= Config.site then local lucky, x = pcall( require, "Module:Vorlage:lang/Zwiebelfisch" ) r = first( script ) .. r if type( x ) == "table" and type( x.finder ) == "function" then x = x.finder( apply, script ) if type( x ) == "string" then r = r .. x end end end else r = Export.fold( { SCRIPTING = script }, { [ 1 ] = slang, [ 2 ] = apply, class = selector, style = appear } ) end if mw.text.unstrip( apply ):sub( 1, 1 ) == "<" then local seek = "^(<([sd][paniv]+) [^>]+>)%1(.+)(</%2>)%4$" local s, start, story, stop start, s, story, stop = mw.text.unstrip( r ):match( seek ) if story then r = Export.format( slang, story, appear, audio, alike ) end end if audio and Config.tmplAudio then local params = { [ Config.tmplAudio.filepar ] = audio, [ Config.tmplAudio.textpar ] = r } r = Frame():expandTemplate{ title = Config.tmplAudio.title, args = params } end return r or "" end -- Export.format() Export.full = function ( argsF, argsT ) -- Invocation of language name template -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters -- Returns appropriate string if argsF then Config.lenient = faculty( argsF.lenient ) Config.long = faculty( argsF.LONG ) Config.scripting = argsF.SCRIPTING Config.service = argsF.SERVICE Config.slang = argsF.CODE Config.sole = argsF.SOLE if argsF["OBSOLETING-bwd"] then table.insert( Config.params, "b" ) table.insert( Config.params, "d" ) table.insert( Config.params, "w" ) end end Config.low = false return furnish( argsF, argsT ) end -- Export.full() Failsafe.failsafe = function ( atleast ) -- Retrieve versioning and check for compliance -- Precondition: -- atleast -- string, with required version or "wikidata" or "~" -- or false -- Postcondition: -- Returns string -- with queried version, also if problem -- false -- if appropriate local last = ( atleast == "~" ) local since = atleast local r if last or since == "wikidata" then local item = Failsafe.item since = false if type( item ) == "number" and item > 0 then local entity = mw.wikibase.getEntity( string.format( "Q%d", item ) ) if type( entity ) == "table" then local vsn = entity:formatPropertyValues( "P348" ) if type( vsn ) == "table" and type( vsn.value ) == "string" and vsn.value ~= "" then if last and vsn.value == Failsafe.serial then r = false else r = vsn.value end end end end end if type( r ) == "nil" then if not since or since <= Failsafe.serial then r = Failsafe.serial else r = false end end return r end -- Failsafe.failsafe() -- Export local p = { } p.test = function ( action, argsF, argsT ) -- action -- string, "flat" or "full" etc. -- argsF -- table, with #invoke parameters, or false -- argsT -- table, with template parameters return frontend( action, argsF, argsT ) end -- p.test() p.flat = function ( frame ) return frontier( frame, "flat" ) end -- p.flat() p.fold = function ( frame ) return frontier( frame, "fold" ) or "" end -- p.fold() p.full = function ( frame ) return frontier( frame, "full" ) end -- p.full() 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 Failsafe.failsafe( since ) or "" end -- p.failsafe p.lang = function () return Export end -- p.lang() return p