K (1 Version importiert: deWP/Vorl.) |
Im>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 unterstützen |
+ | Vorlage:lang und Sprachnamenvorlagen usw. unterstützen |
]=] |
]=] |
||
+ | local Failsafe = Export |
||
+ | local GlobalMod = Export |
||
local Config = { |
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 = "Parameter unbekannt:" }, |
||
− | + | de = "'%s' * vermutlich ist '%s' gemeint" }, |
|
− | + | errUnkown = { en = "Unkown parameter:", |
|
− | + | de = "Parameter unbekannt:" }, |
|
− | + | ipa = "IPA", |
|
− | + | keyBase = 100, |
|
+ | keyProject = 200, |
||
− | hi = true, |
||
+ | keyAncient = 300, |
||
− | kn = true, |
||
+ | keyTranslate = 400, |
||
− | kok = true, |
||
− | + | params = { "Text1", |
|
− | + | "Audio", |
|
− | + | "IPA", |
|
− | + | "class", |
|
− | + | "lenient", |
|
− | + | "script", |
|
− | + | "style", |
|
− | + | "nachgestellt", |
|
− | + | "demo", |
|
− | + | "demo2", |
|
− | + | "demo3", |
|
− | + | "demo4", |
|
− | + | "NoCat" }, |
|
+ | percents = false, |
||
− | support = "International Alphabet of Sanskrit Transliteration" }, |
||
− | + | 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 } |
|
− | en = 9 }, |
||
− | otherLangTmpl = { dewiki = { namePat = "%sS", |
||
− | textpar = 1 }, |
||
− | enwiki = { namePat = "lang-%s", |
||
− | textpar = 1 } }, |
||
− | owns = { de = "‚%s‘" }, |
||
− | transcriptions = |
||
− | { Arab = { en = "[[Arabic alphabet|arabic]]", |
||
− | de = "[[Arabisches Alphabet|arabisch]]" }, |
||
− | Cyrl = { en = "[[Cyrillic alphabets|cyrillic]]", |
||
− | de = "[[Kyrillisches Alphabet|kyrillisch]]" } |
||
− | } |
||
} |
} |
||
+ | |||
− | local Multilingual = false |
||
+ | |||
+ | |||
+ | 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() |
||
Zeile 103: | 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 |
||
− | entry = Config[ apply ] |
||
if entry then |
if entry then |
||
r = entry[ facility() ] |
r = entry[ facility() ] |
||
Zeile 111: | 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 127: | 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 135: | 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() |
||
local function family() |
local function family() |
||
− | -- |
+ | -- attempt to load local config |
+ | if not Config.data then |
||
− | -- Returns string |
||
+ | local sub = string.format( "%s/config", Frame():getTitle() ) |
||
− | if not Config.site then |
||
+ | local lucky |
||
− | local s = mw.site.server:gsub( "%.beta%.wmflabs%.org", ".org" ) |
||
− | + | lucky, Config.data = pcall( mw.loadData, sub ) |
|
− | if |
+ | 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 |
end |
||
− | return Config.site or "" |
||
end -- family() |
end -- family() |
||
− | 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 -- string, with message key |
+ | -- alert -- string, with message key |
− | -- about -- string, with explanation |
+ | -- 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 |
+ | local env = Frame():getParent() |
+ | local err = mw.html.create( "span" ) |
||
− | if Config.self then |
||
+ | local r |
||
− | story = string.format( "%s * %s", Config.self, story ) |
||
+ | err:addClass( Config.errClass ) |
||
+ | :css( { ["margin-left"] = "1em", |
||
+ | ["margin-right"] = "1em" } ) |
||
+ | family() |
||
+ | if env then |
||
+ | story = string.format( "[[%s]] – %s", |
||
+ | env:getTitle(), story ) |
||
end |
end |
||
− | if |
+ | if about then |
+ | story = string.format( "%s %s", story, about ) |
||
− | Config.frame = mw.getCurrentFrame() |
||
− | end |
||
− | if Config.frame:preprocess( "{{REVISIONID}}" ) == "" then |
||
− | Config.errCat = false |
||
− | Config.errHide = false |
||
− | scope = string.format( "%s error", Config.errClass ) |
||
− | else |
||
− | scope = Config.errClass |
||
− | end |
||
− | if Config.errHide then |
||
− | style = "style='display:none'" |
||
− | else |
||
− | style = "" |
||
end |
end |
||
if Config.errClasses then |
if Config.errClasses then |
||
− | + | err:addClass( Config.errClasses ) |
|
− | scope, Config.errClasses ) |
||
end |
end |
||
+ | err:wikitext( story ) |
||
− | r = string.format( "<span class=\"%s\" %s>%s</span>", |
||
+ | r = Fetch( "TemplUtl" ) |
||
− | scope, style, story ) |
||
− | if |
+ | if Config.TemplUtl then |
− | r = |
+ | r = Config.TemplUtl.failure( tostring( err ), |
+ | not Config.errHide, |
||
+ | false, |
||
+ | Frame() ) |
||
end |
end |
||
− | if Config.errCat 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 215: | Zeile 353: | ||
− | local function |
+ | local function features( apply, assign ) |
+ | -- Equip element with script attributes |
||
− | -- Fetch Multilingual module |
||
− | -- |
+ | -- apply -- mw.html element |
− | -- |
+ | -- assign -- string, with script code |
+ | if type( Config.percents ) == "table" then |
||
− | local r = auxilary |
||
+ | local more = Config.percents[ assign ] |
||
− | if not Multilingual then |
||
− | if |
+ | if more then |
+ | apply:css( "font-size", string.format( "%d%%", more ) ) |
||
− | local lucky |
||
+ | end |
||
− | lucky, r = pcall( require, "Module:Multilingual" ) |
||
+ | end |
||
− | if type( r ) == "table" then |
||
+ | end -- features() |
||
− | r = r.Multilingual() |
||
+ | |||
− | else |
||
+ | |||
− | r = string.format( "<span class=\"error\">%s</span>", r ) |
||
+ | |||
+ | 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 |
end |
||
− | Multilingual = r |
||
end |
end |
||
return r |
return r |
||
− | end -- |
+ | end -- fill() |
− | local function |
+ | local function first( assign, apply ) |
− | -- |
+ | -- Equip element with TemplateStyles |
− | -- |
+ | -- assign -- string, with script code |
+ | -- apply -- mw.html element, or false |
||
− | -- Returns string |
||
+ | -- 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 |
+ | 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 |
− | + | -- 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 |
||
− | else |
||
− | + | 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 p = { ["font-weight"] = "normal" } |
||
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 281: | Zeile 573: | ||
r = tostring( e ) |
r = tostring( e ) |
||
else |
else |
||
+ | p["font-style"] = "normal" |
||
− | r = frame():expandTemplate{ title = advanced, |
||
− | + | r = Export.fold( { css = p, |
|
+ | SCRIPTING = script }, |
||
+ | { [ 1 ] = acquire, |
||
+ | [ 2 ] = apply, |
||
+ | lang = advanced } ) |
||
end |
end |
||
return r |
return r |
||
Zeile 289: | 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 |
||
+ | -- alone -- boolean, no other elements in collection yet |
||
− | -- Returns string, starting with comma |
||
+ | -- Returns string, starting with separator (comma) |
||
− | local r = "" |
||
local pars = { } |
local pars = { } |
||
− | local |
+ | local sep = ahead |
+ | local lone = alone |
||
+ | local r = "" |
||
+ | local k, lucky, s, t |
||
+ | family() |
||
facility() |
facility() |
||
− | + | Fetch( "Multilingual" ) |
|
for i = 1, #aliens do |
for i = 1, #aliens do |
||
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 313: | Zeile 618: | ||
return ( a1.n < a2.n ) |
return ( a1.n < a2.n ) |
||
end ) |
end ) |
||
− | if not Config.frame then |
||
− | Config.frame = mw.getCurrentFrame() |
||
− | end |
||
− | o = Config.otherLangTmpl[ family() ] |
||
for i = 1, #aliens do |
for i = 1, #aliens do |
||
t = aliens[ i ] |
t = aliens[ i ] |
||
− | if |
+ | if lone then |
− | s |
+ | s = "" |
− | + | sep = "" |
|
− | s = Config.frame:expandTemplate{ title = s, |
||
− | args = pars } |
||
else |
else |
||
− | s = |
+ | s = false |
− | if |
+ | 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 |
||
− | s = string.format( "%s %s", |
||
− | facet( s ), |
||
− | foreign( t.story, t.short, t.slang ) ) |
||
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 341: | Zeile 665: | ||
− | local function |
+ | local function friend( assigned, apply ) |
− | -- |
+ | -- Transcription unit |
+ | -- assigned -- string, transcription ID |
||
− | -- Returns frame |
||
+ | -- apply -- string, transcription text |
||
− | if not Config.frame then |
||
+ | -- Returns string |
||
− | Config.frame = mw.getCurrentFrame() |
||
+ | 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 |
end |
||
+ | e:css( { ["font-style"] = s } ) |
||
− | return Config.frame |
||
+ | if type( Config.transys ) == "table" and |
||
− | end -- frame() |
||
+ | 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() |
||
Zeile 354: | Zeile 715: | ||
local function frontend( action, argsF, argsT, about ) |
local function frontend( action, argsF, argsT, about ) |
||
-- Template service |
-- Template service |
||
− | -- action -- string, "flat" or "full" |
+ | -- action -- string, "flat" or "full" etc. |
-- argsF -- table, with #invoke parameters, or false |
-- argsF -- table, with #invoke parameters, or false |
||
-- argsT -- table, with template parameters |
-- argsT -- table, with template parameters |
||
Zeile 378: | Zeile 739: | ||
-- Template transclusion |
-- Template transclusion |
||
-- frame -- object |
-- frame -- object |
||
− | -- action -- string, "flat" or "full" |
+ | -- action -- string, "flat" or "full" etc. |
-- Returns appropriate string |
-- Returns appropriate string |
||
Config.frame = frame |
Config.frame = frame |
||
Zeile 390: | 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 396: | Zeile 757: | ||
if arglist.Text1 then |
if arglist.Text1 then |
||
local slang = Config.slang |
local slang = Config.slang |
||
− | local |
+ | 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 |
if slang == facility() then |
||
arglist.style = false |
arglist.style = false |
||
Zeile 403: | 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 421: | 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", |
|
− | + | 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 ) |
|
− | + | end -- for i |
|
− | + | lone = false |
|
− | r = r .. " " |
||
− | s = fiast( s ) |
||
− | end |
||
− | r = r .. mw.text.tag( "span", params, s ) |
||
end |
end |
||
if not Config.low then |
if not Config.low then |
||
if Config.scripting then |
if Config.scripting then |
||
− | s = |
+ | s = false |
− | if |
+ | if arglist[ Config.scripting ] and |
− | + | not arglist.Text2 then |
|
− | + | Fetch( "ISO15924" ) |
|
− | + | if Config.ISO15924 then |
|
− | s = |
+ | s = Config.ISO15924 |
− | + | .scriptName( Config.scripting ) |
|
− | + | end |
|
+ | end |
||
+ | if not s and Config.service then |
||
s = facet( Config.service ) |
s = facet( Config.service ) |
||
− | else |
||
− | s = "" |
||
end |
end |
||
+ | elseif Config.service then |
||
+ | s = Config.service |
||
else |
else |
||
− | s = |
+ | s = false |
end |
end |
||
− | if |
+ | 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 } |
+ | args = params } |
− | r = string.format( "%s [%s]", r, s ) |
+ | r = string.format( "%s [%s]", r, s ) |
− | + | sep = follow() |
|
− | + | lone = false |
|
− | r = string.format( "%s, %s", r, arglist.Text3 ) |
||
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 497: | 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 |
||
if argsF then |
if argsF then |
||
+ | if argsF.errHide ~= nil then |
||
+ | Config.errHide = faculty( argsF.errHide ) |
||
+ | end |
||
Config.errCat = argsF.errCat |
Config.errCat = argsF.errCat |
||
Config.errClasses = argsF.errClasses |
Config.errClasses = argsF.errClasses |
||
− | Config.errHide = faculty( argsF.errHide ) |
||
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 519: | 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 527: | Zeile 918: | ||
end |
end |
||
if k <= 2 then |
if k <= 2 then |
||
− | if |
+ | if v then |
− | k = |
+ | if k == 0 then |
− | + | k = false |
|
− | v = mw.text.trim( v ) |
||
− | if v == "" then |
||
− | v = false |
||
− | end |
||
− | if k == 1 then |
||
− | r.Text1 = v |
||
− | k = false |
||
− | elseif Config.scripting == "Latn" then |
||
− | k = "2" |
||
else |
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 |
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 |
end |
||
else |
else |
||
k = tostring( k ) |
k = tostring( k ) |
||
end |
end |
||
− | elseif |
+ | 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$" ) |
− | if |
+ | if v then |
− | + | script = k:match( "^%l%l%l?%-(%u%l%l%l)$" ) |
|
− | + | else |
|
− | if not r.trsl then |
||
− | r.trsl = { } |
||
− | end |
||
− | table.insert( r.trsl, |
||
− | { n = #r.trsl + 10, |
||
− | short = s, |
||
− | slang = k, |
||
− | story = v } ) |
||
k = false |
k = false |
||
end |
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 |
end |
||
k = false |
k = false |
||
end |
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 |
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 592: | Zeile 1.045: | ||
end -- for k, v |
end -- for k, v |
||
if r.demo or faculty( r.NoCat ) then |
if r.demo or faculty( r.NoCat ) then |
||
− | Config.errCat = |
+ | Config.errCat = 0 |
Config.errHide = false |
Config.errHide = false |
||
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 614: | Zeile 1.076: | ||
return r |
return r |
||
end -- furnish() |
end -- furnish() |
||
− | |||
− | |||
− | |||
− | Export.failsafe = function ( assert ) |
||
− | local r |
||
− | if not assert or assert <= Export.serial then |
||
− | r = Export.serial |
||
− | else |
||
− | r = false |
||
− | end |
||
− | return r |
||
− | end -- Export.failsafe() |
||
Zeile 635: | Zeile 1.085: | ||
-- auxilary -- Multilingual library, or false |
-- auxilary -- Multilingual library, or false |
||
-- Returns appropriate string |
-- Returns appropriate string |
||
− | local r |
+ | local r |
− | if |
+ | if type( auxilary ) == "table" then |
+ | Config.Multilingual = auxilary |
||
+ | else |
||
+ | r = Fetch( "Multilingual" ) |
||
+ | end |
||
+ | if Config.Multilingual then |
||
local slang = argsT[ 1 ] |
local slang = argsT[ 1 ] |
||
local show = argsT[ 2 ] |
local show = argsT[ 2 ] |
||
Zeile 646: | Zeile 1.101: | ||
end |
end |
||
if show then |
if show then |
||
− | show = |
+ | show = flatten( show ) |
− | if show == "" then |
||
− | show = false |
||
− | end |
||
end |
end |
||
if slang and show then |
if slang and show then |
||
− | local q = 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 663: | Zeile 1.116: | ||
:attr( "lang", slang ) |
:attr( "lang", slang ) |
||
:wikitext( show ) |
: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 |
end |
||
else |
else |
||
− | r = fault( "errMissing" ) |
+ | r = fault( "errMissing", false, true ) |
if show then |
if show then |
||
r = show .. r |
r = show .. r |
||
Zeile 674: | Zeile 1.139: | ||
return r |
return r |
||
end -- Export.flat() |
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() |
||
Zeile 685: | 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 r |
+ | 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 |
end |
||
− | + | slang = slang:lower() |
|
+ | if not script then |
||
− | params.class = alike |
||
+ | script = fit( slang ) |
||
end |
end |
||
+ | if script then |
||
− | r = mw.text.tag( "span", params, apply ) |
||
+ | local rtl = Friend().rtl |
||
− | if audio and Config.audio then |
||
− | + | if type( rtl ) == "table" then |
|
− | + | ltr = not rtl[ script ] |
|
+ | end |
||
− | r = frame():expandTemplate{ title = Config.audio, |
||
+ | 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 } |
args = params } |
||
end |
end |
||
− | return r |
+ | return r or "" |
end -- Export.format() |
end -- Export.format() |
||
Zeile 711: | Zeile 1.369: | ||
-- Returns appropriate string |
-- Returns appropriate string |
||
if argsF then |
if argsF then |
||
− | Config. |
+ | Config.lenient = faculty( argsF.lenient ) |
− | Config. |
+ | Config.long = faculty( argsF.LONG ) |
− | Config. |
+ | Config.scripting = argsF.SCRIPTING |
− | Config. |
+ | Config.service = argsF.SERVICE |
− | Config. |
+ | Config.slang = argsF.CODE |
− | + | Config.sole = argsF.SOLE |
|
+ | 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 724: | 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 729: | Zeile 1.432: | ||
-- Export |
-- Export |
||
local p = { } |
local p = { } |
||
− | |||
p.test = function ( action, argsF, argsT ) |
p.test = function ( action, argsF, argsT ) |
||
− | -- action -- string, "flat" or "full" |
+ | -- action -- string, "flat" or "full" etc. |
-- argsF -- table, with #invoke parameters, or false |
-- argsF -- table, with #invoke parameters, or false |
||
-- argsT -- table, with template parameters |
-- argsT -- table, with template parameters |
||
return frontend( action, argsF, argsT ) |
return frontend( action, argsF, argsT ) |
||
end -- p.test() |
end -- p.test() |
||
− | |||
− | |||
− | |||
− | p.feedIAST = function ( frame ) |
||
− | return Config.iast.lang[ frame.args[ 1 ] ] and "1" or "" |
||
− | end -- p.feedIAST() |
||
− | |||
Zeile 751: | Zeile 1.446: | ||
end -- p.flat() |
end -- p.flat() |
||
+ | |||
+ | p.fold = function ( frame ) |
||
+ | return frontier( frame, "fold" ) or "" |
||
+ | end -- p.fold() |
||
Zeile 760: | Zeile 1.459: | ||
p.failsafe = function ( frame ) |
p.failsafe = function ( frame ) |
||
+ | -- Versioning interface |
||
− | local since = frame.args[ 1 ] |
||
+ | local s = type( frame ) |
||
+ | local since |
||
+ | if s == "table" then |
||
+ | since = frame.args[ 1 ] |
||
+ | elseif s == "string" then |
||
+ | since = frame |
||
+ | end |
||
if since then |
if since then |
||
since = mw.text.trim( since ) |
since = mw.text.trim( since ) |
||
Zeile 767: | Zeile 1.473: | ||
end |
end |
||
end |
end |
||
− | return |
+ | return Failsafe.failsafe( since ) or "" |
− | end -- p.failsafe |
+ | end -- p.failsafe |
Version vom 19. November 2019, 20:34 Uhr
Modul:Vorlage:LuaModuleDoc:142: attempt to index field 'wikibase' (a nil value)
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