Jump to content

Module:Multilingual and Module:Multilingual/sandbox: Difference between pages

(Difference between pages)
Page 1
Page 2
Content deleted Content added
m Protected "Module:Multilingual": High-risk Lua module: Requested by Pppery at RfPP. Used in Module:Format TemplateData, which is semi-protected and has 516 transclusions ([Edit=Require autoconfirmed or confirmed access] (indefinite))
 
Simplifications, and MASSIVE formatting improvements - especially removing excess whitespace and replacing quadruple spaces with tabs, in accordance to mw:Manual:Coding conventions/Lua
 
Line 1: Line 1:
local Multilingual = { suite = "Multilingual",
local Multilingual = { suite = "Multilingual",
serial = "2020-12-10",
serial = "2020-12-10",
item = 47541920,
item = 47541920,
globals = { ISO15924 = 71584769,
globals = { ISO15924 = 71584769,
WLink = 19363224 }
WLink = 19363224 }
}
}
--[=[
--[=[
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
Line 33: Line 33:
local GlobalMod = Multilingual
local GlobalMod = Multilingual
local GlobalData = Multilingual
local GlobalData = Multilingual
local User = { sniffer = "showpreview" }
local User = { sniffer = "showpreview" }
Multilingual.globals.Multilingual = Multilingual.item
Multilingual.globals.Multilingual = Multilingual.item


Line 39: Line 39:


Multilingual.exotic = { simple = true,
Multilingual.exotic = { simple = true,
no = true }
no = true }
Multilingual.prefer = { cs = true,
Multilingual.prefer = { cs = true,
de = true,
de = true,
en = true,
en = true,
es = true,
es = true,
fr = true,
fr = true,
it = true,
it = true,
nl = true,
nl = true,
pt = true,
pt = true,
ru = true,
ru = true,
sv = true }
sv = true }


local foreignModule = function(access, advanced, append, alt, alert)

-- Fetch global module

-- Precondition:
local foreignModule = function ( access, advanced, append, alt, alert )
-- Fetch global module
-- access -- string, with name of base module
-- advanced -- true, for require(); else mw.loadData()
-- Precondition:
-- access -- string, with name of base module
-- append -- string, with subpage part, if any; or false
-- alt -- number, of wikidata item of root; or false
-- advanced -- true, for require(); else mw.loadData()
-- alert -- true, for throwing error on data problem
-- append -- string, with subpage part, if any; or false
-- Postcondition:
-- alt -- number, of wikidata item of root; or false
-- Returns whatever, probably table
-- alert -- true, for throwing error on data problem
-- 2020-01-01
-- Postcondition:
local storage = access
-- Returns whatever, probably table
local finer = function()
-- 2020-01-01
if append then
local storage = access
storage = string.format("%s/%s", storage, append)
local finer = function ()
end
if append then
end
storage = string.format( "%s/%s",
local fun, lucky, r, suited
storage,
if advanced then
append )
fun = require
end
else
end
fun = mw.loadData
local fun, lucky, r, suited
end
if advanced then
GlobalMod.globalModules = GlobalMod.globalModules or {}
fun = require
suited = GlobalMod.globalModules[access]
else
if not suited then
fun = mw.loadData
finer()
end
lucky, r = pcall(fun, "Module:" .. storage)
GlobalMod.globalModules = GlobalMod.globalModules or { }
end
suited = GlobalMod.globalModules[ access ]
if not suited then
if not lucky then
if not suited and
finer()
type(alt) == "number" and
lucky, r = pcall( fun, "Module:" .. storage )
end
alt > 0 then
suited = string.format("Q%d", alt)
if not lucky then
suited = mw.wikibase.getSitelink(suited)
if not suited and
GlobalMod.globalModules[access] = suited or true
type( alt ) == "number" and
end
alt > 0 then
suited = string.format( "Q%d", alt )
if type(suited) == "string" then
storage = suited
suited = mw.wikibase.getSitelink( suited )
finer()
GlobalMod.globalModules[ access ] = suited or true
lucky, r = pcall(fun, storage)
end
end
if type( suited ) == "string" then
if not lucky and alert then
storage = suited
error("Missing or invalid page: " .. storage)
finer()
end
lucky, r = pcall( fun, storage )
end
end
return r
if not lucky and alert then
error( "Missing or invalid page: " .. storage )
end
end
return r
end -- foreignModule()
end -- foreignModule()


local fetchData = function(access)

-- Retrieve translated keyword from commons:Data:****.tab

-- Precondition:
local fetchData = function ( access )
-- access -- string, with page identification on Commons
-- Retrieve translated keyword from commons:Data:****.tab
-- Returns table, with data, or string, with error message
-- Precondition:
-- 2019-12-05
-- access -- string, with page identification on Commons
local storage = access
-- Returns table, with data, or string, with error message
local r
-- 2019-12-05
local storage = access
if type(storage) == "string" then
local r
local s
if type( storage ) == "string" then
storage = mw.text.trim(storage)
s = storage:lower()
local s
if s:sub(1, 2) == "c:" then
storage = mw.text.trim( storage )
s = storage:lower()
storage = mw.text.trim(storage:sub(3))
s = storage:lower()
if s:sub( 1, 2 ) == "c:" then
elseif s:sub(1, 8) == "commons:" then
storage = mw.text.trim( storage:sub( 3 ) )
s = storage:lower()
storage = mw.text.trim(storage:sub(9))
s = storage:lower()
elseif s:sub( 1, 8 ) == "commons:" then
end
storage = mw.text.trim( storage:sub( 9 ) )
if s:sub(1, 5) == "data:" then
s = storage:lower()
storage = mw.text.trim(storage:sub(6))
end
s = storage:lower()
if s:sub( 1, 5 ) == "data:" then
end
storage = mw.text.trim( storage:sub( 6 ) )
if s == "" or s == ".tab" then
s = storage:lower()
storage = false
end
if s == "" or s == ".tab" then
elseif s:sub(-4) == ".tab" then
storage = storage:sub(1, -5) .. ".tab"
storage = false
else
elseif s:sub( -4 ) == ".tab" then
storage = storage:sub( 1, -5 ) .. ".tab"
storage = storage .. ".tab"
end
else
end
storage = storage .. ".tab"
if type(storage) == "string" then
end
local data
end
if type( storage ) == "string" then
if type(GlobalData.TabDATA) ~= "table" then
GlobalData.TabDATA = {}
local data
end
if type( GlobalData.TabDATA ) ~= "table" then
GlobalData.TabDATA = { }
data = GlobalData.TabDATA[storage]
if data then
end
r = data
data = GlobalData.TabDATA[ storage ]
else
if data then
local lucky
r = data
lucky, data = pcall(mw.ext.data.get, storage, "_")
else
if type(data) == "table" then
local lucky
data = data.data
lucky, data = pcall( mw.ext.data.get, storage, "_" )
if type( data ) == "table" then
if type(data) == "table" then
GlobalData.TabDATA[storage] = data
data = data.data
else
if type( data ) == "table" then
r = string.format("%s [[%s%s]]",
GlobalData.TabDATA[ storage ] = data
"INVALID Data:*.tab",
else
"commons:Data:",
r = string.format( "%s [[%s%s]]",
storage)
"INVALID Data:*.tab",
end
"commons:Data:",
else
storage )
r = "BAD PAGE Data:*.tab – commons:" .. storage
end
end
else
if r then
r = "BAD PAGE Data:*.tab – commons:" .. storage
GlobalData.TabDATA[storage] = r
end
data = false
if r then
else
GlobalData.TabDATA[ storage ] = r
r = data
data = false
end
else
end
r = data
else
end
r = "BAD PAGE commons:Data:*.tab"
end
end
else
return r
r = "BAD PAGE commons:Data:*.tab"
end
return r
end -- fetchData()
end -- fetchData()


local favorites = function()

-- Provide fallback codes

-- Postcondition:
local favorites = function ()
-- Returns table with sequence of preferred languages
-- Provide fallback codes
-- * ahead elements
-- Postcondition:
-- * user (not yet accessible)
-- Returns table with sequence of preferred languages
-- * page content language (not yet accessible)
-- * ahead elements
-- * page name subpage
-- * user (not yet accessible)
-- * project
-- * page content language (not yet accessible)
-- * en
-- * page name subpage
local r = Multilingual.polyglott
-- * project
if not r then
-- * en
local self = mw.language.getContentLanguage():getCode():lower()
local r = Multilingual.polyglott
local sub = mw.title.getCurrentTitle().subpageText
if not r then
local f = function(add)
local self = mw.language.getContentLanguage():getCode():lower()
local s = add
local sub = mw.title.getCurrentTitle().subpageText
for i = 1, #r do
local f = function ( add )
if r[i] == s then
local s = add
s = false
for i = 1, #r do
break -- for i
if r[ i ] == s then
end
s = false
end -- for i
break -- for i
if s then
end
table.insert(r, s)
end -- for i
end
if s then
end
table.insert( r, s )
r = {}
end
if sub:find("/", 2, true) then
end
sub = sub:match("/(%l%l%l?)$")
r = { }
if sub:find( "/", 2, true ) then
if sub then
table.insert(r, sub)
sub = sub:match( "/(%l%l%l?)$" )
end
if sub then
elseif sub:find("^%l%l%l?%-?%a?%a?%a?%a?$") and
table.insert( r, sub )
mw.language.isSupportedLanguage(sub) then
end
table.insert(r, sub)
elseif sub:find( "^%l%l%l?%-?%a?%a?%a?%a?$" ) and
end
mw.language.isSupportedLanguage( sub ) then
f(self)
table.insert( r, sub )
f("en")
end
Multilingual.polyglott = r
f( self )
end
f( "en" )
return r
Multilingual.polyglott = r
end
return r
end -- favorites()
end -- favorites()


local feasible = function(ask, accept)

-- Is ask to be supported by application?

-- Precondition:
local feasible = function ( ask, accept )
-- ask -- lowercase code
-- Is ask to be supported by application?
-- accept -- sequence table, with offered lowercase codes
-- Precondition:
-- Postcondition:
-- ask -- lowercase code
-- nil, or true
-- accept -- sequence table, with offered lowercase codes
local r
-- Postcondition:
for i = 1, #accept do
-- nil, or true
if accept[i] == ask then
local r
r = true
for i = 1, #accept do
break -- for i
if accept[ i ] == ask then
end
r = true
break -- for i
end -- for i
return r
end
end -- for i
return r
end -- feasible()
end -- feasible()


local fetch = function(access, append)

-- Attach config or library module

-- Precondition:
local fetch = function ( access, append )
-- access -- module title
-- Attach config or library module
-- append -- string, with subpage part of this; or false
-- Precondition:
-- Postcondition:
-- access -- module title
-- append -- string, with subpage part of this; or false
-- Returns: table, with library, or false
local got, sign
-- Postcondition:
if append then
-- Returns: table, with library, or false
sign = string.format("%s/%s", access, append)
local got, sign
else
if append then
sign = string.format( "%s/%s", access, append )
sign = access
end
else
if type(Multilingual.ext) ~= "table" then
sign = access
Multilingual.ext = {}
end
end
if type( Multilingual.ext ) ~= "table" then
Multilingual.ext = { }
got = Multilingual.ext[sign]
end
if got == nil then
got = Multilingual.ext[ sign ]
local global = Multilingual.globals[access]
if not got and got ~= false then
local lib = (not append or append == "config")
got = foreignModule(access, lib, append, global)
local global = Multilingual.globals[ access ]
if type(got) == "table" then
local lib = ( not append or append == "config" )
if lib then
got = foreignModule( access, lib, append, global )
local startup = got[access]
if type( got ) == "table" then
if type(startup) == "function" then
if lib then
got = startup()
local startup = got[ access ]
end
if type( startup ) == "function" then
end
got = startup()
else
end
got = false
end
end
else
Multilingual.ext[sign] = got
got = false
end
end
return got
Multilingual.ext[ sign ] = got
end
return got
end -- fetch()
end -- fetch()


local fetchISO639 = function(access)

-- Retrieve table from commons:Data:ISO639/***.tab

-- Precondition:
local fetchISO639 = function ( access )
-- access -- string, with subpage identification
-- Retrieve table from commons:Data:ISO639/***.tab
-- Postcondition:
-- Precondition:
-- Returns table, with data, even empty
-- access -- string, with subpage identification
local r
-- Postcondition:
if type(Multilingual.iso639) ~= "table" then
-- Returns table, with data, even empty
Multilingual.iso639 = {}
local r
end
if type( Multilingual.iso639 ) ~= "table" then
Multilingual.iso639 = { }
r = Multilingual.iso639[access]
if type(r) == "nil" then
end
local raw = fetchData("ISO639/" .. access)
r = Multilingual.iso639[ access ]
if type( r ) == "nil" then
if type(raw) == "table" then
local t
local raw = fetchData( "ISO639/" .. access )
r = {}
if type( raw ) == "table" then
for i = 1, #raw do
local t
t = raw[i]
r = { }
if type(t) == "table" and
for i = 1, #raw do
type(t[1]) == "string" and
t = raw[ i ]
if type( t ) == "table" and
type(t[2]) == "string" then
r[t[1]] = t[2]
type( t[ 1 ] ) == "string" and
else
type( t[ 2 ] ) == "string" then
break -- for i
r[ t[ 1 ] ] = t[ 2 ]
end
else
break -- for i
end -- for i
else
end
r = false
end -- for i
end
else
Multilingual.iso639[access] = r
r = false
end
end
return r or {}
Multilingual.iso639[ access ] = r
end
return r or { }
end -- fetchISO639()
end -- fetchISO639()


local fill = function(access, alien, frame)

-- Expand language name template

-- Precondition:
local fill = function ( access, alien, frame )
-- access -- string, with language code
-- Expand language name template
-- alien -- language code for which to be generated
-- Precondition:
-- access -- string, with language code
-- frame -- frame, if available
-- Postcondition:
-- alien -- language code for which to be generated
-- Returns string
-- frame -- frame, if available
local template = Multilingual.tmplLang
-- Postcondition:
if type(template) ~= "table" then
-- Returns string
local template = Multilingual.tmplLang
local cnf = fetch("Multilingual", "config")
if cnf then
local r
if type( template ) ~= "table" then
template = cnf.tmplLang
end
local cnf = fetch( "Multilingual", "config" )
end
if cnf then
template = cnf.tmplLang
if type(template) == "table" then
local source = template.title
end
local f, lucky, s
end
Multilingual.tmplLang = template
if type( template ) == "table" then
local source = template.title
if type(source) ~= "string" and
type(template.namePat) == "string" and
local f, lucky, s
template.namePat:find("%s", 1, true) then
Multilingual.tmplLang = template
if type( source ) ~= "string" and
source = string.format(template.namePat, access)
end
type( template.namePat ) == "string" and
if type(source) == "string" then
template.namePat:find( "%s", 1, true ) then
if not Multilingual.frame then
source = string.format( template.namePat, access )
Multilingual.frame = frame or mw.getCurrentFrame()
end
end
if type( source ) == "string" then
f = function(a)
if not Multilingual.frame then
return Multilingual.frame:expandTemplate{ title = a }
if frame then
end
Multilingual.frame = frame
lucky, s = pcall(f, source)
else
if lucky then
Multilingual.frame = mw.getCurrentFrame()
return s
end
end
end
end
f = function ( a )
end
return Multilingual.frame:expandTemplate{ title = a }
return nil
end
lucky, s = pcall( f, source )
if lucky then
r = s
end
end
end
return r
end -- fill()
end -- fill()


local find = function(ask, alien)

-- Derive language code from name

-- Precondition:
local find = function ( ask, alien )
-- Derive language code from name
-- ask -- language name, downcased
-- alien -- language code of ask
-- Precondition:
-- Postcondition:
-- ask -- language name, downcased
-- nil, or string
-- alien -- language code of ask
local codes = mw.language.fetchLanguageNames(alien, "all")
-- Postcondition:
local r
-- nil, or string
for k, v in pairs(codes) do
local codes = mw.language.fetchLanguageNames( alien, "all" )
if mw.ustring.lower(v) == ask then
local r
r = k
for k, v in pairs( codes ) do
break -- for k, v
if mw.ustring.lower( v ) == ask then
end
r = k
break -- for k, v
end -- for k, v
if not r then
end
r = Multilingual.fair(ask)
end -- for k, v
end
if not r then
return r
r = Multilingual.fair( ask )
end
return r
end -- find()
end -- find()






local fold = function ( frame )
local fold = function(frame)
-- Merge template and #invoke arglist
-- Merge template and #invoke arglist
-- Precondition:
-- Precondition:
-- frame -- template frame
-- frame -- template frame
-- Postcondition:
-- Postcondition:
-- table, with combined arglist
-- table, with combined arglist
local r = { }
local r = {}
local f = function ( apply )
local f = function(apply)
if type( apply ) == "table" and
if type(apply) == "table" and
type( apply.args ) == "table" then
type(apply.args) == "table" then
for k, v in pairs( apply.args ) do
for k, v in pairs(apply.args) do
v = mw.text.trim( v )
v = mw.text.trim(v)
if v ~= "" then
if v ~= "" then
r[ tostring( k ) ] = v
r[tostring(k)] = v
end
end
end -- for k, v
end -- for k, v
end
end
end -- f()
end -- f()
f( frame:getParent() )
f(frame:getParent())
f( frame )
f(frame)
return r
return r
end -- fold()
end -- fold()


User.favorize = function(accept, frame)

-- Guess user language

-- Precondition:
User.favorize = function ( accept, frame )
-- accept -- sequence table, with offered ISO 639 etc. codes
-- Guess user language
-- frame -- frame, if available
-- Precondition:
-- Postcondition:
-- accept -- sequence table, with offered ISO 639 etc. codes
-- Returns string with best code, or nil
-- frame -- frame, if available
if not (User.self or User.langs) then
-- Postcondition:
if not User.trials then
-- Returns string with best code, or nil
if not ( User.self or User.langs ) then
User.tell = mw.message.new(User.sniffer)
if not User.trials then
if User.tell:exists() then
User.trials = {}
User.tell = mw.message.new( User.sniffer )
if not Multilingual.frame then
if User.tell:exists() then
if frame then
User.trials = { }
if not Multilingual.frame then
Multilingual.frame = frame
else
if frame then
Multilingual.frame = frame
Multilingual.frame = mw.getCurrentFrame()
end
else
end
Multilingual.frame = mw.getCurrentFrame()
User.sin = Multilingual.frame:callParserFunction("int",
end
User.sniffer)
end
else
User.sin = Multilingual.frame:callParserFunction( "int",
User.langs = true
User.sniffer )
end
else
end
User.langs = true
if User.sin then
end
local order = {}
end
local post = {}
if User.sin then
local order = { }
local three = {}
local post = { }
local unfold = {}
local three = { }
local s, sin
for i = 1, #accept do
local unfold = { }
s = accept[i]
local s, sin
if not User.trials[s] then
for i = 1, #accept do
if #s > 2 then
s = accept[ i ]
if s:find("-", 3, true) then
if not User.trials[ s ] then
table.insert(unfold, s)
if #s > 2 then
else
if s:find( "-", 3, true ) then
table.insert( unfold, s )
table.insert(three, s)
end
else
elseif Multilingual.prefer[s] then
table.insert( three, s )
table.insert(order, s)
end
else
else
table.insert(post, s)
if Multilingual.prefer[ s ] then
end
table.insert( order, s )
end
else
end -- for i
table.insert( post, s )
for i = 1, #post do
end
table.insert(order, post[i])
end
end -- for i
end
for i = 1, #three do
end -- for i
table.insert(order, three[i])
for i = 1, #post do
end -- for i
table.insert( order, post[ i ] )
for i = 1, #unfold do
end -- for i
table.insert(order, unfold[i])
for i = 1, #three do
end -- for i
table.insert( order, three[ i ] )
for i = 1, #order do
end -- for i
s = order[i]
for i = 1, #unfold do
sin = User.tell:inLanguage(s):plain()
table.insert( order, unfold[ i ] )
if sin == User.sin then
end -- for i
User.self = s
for i = 1, #order do
break -- for i
s = order[ i ]
else
sin = User.tell:inLanguage( s ):plain()
User.trials[s] = true
if sin == User.sin then
end
User.self = s
break -- for i
end -- for i
end
else
end
User.trials[ s ] = true
return User.self
end
end -- for i
end
end
return User.self
end -- User.favorize()
end -- User.favorize()


Multilingual.fair = function(ask)

-- Format language specification according to RFC 5646 etc.

-- Precondition:
Multilingual.fair = function ( ask )
-- ask -- string or table, as created by .getLang()
-- Format language specification according to RFC 5646 etc.
-- Postcondition:
-- Precondition:
-- ask -- string or table, as created by .getLang()
-- Returns string, or false
local s = type(ask)
-- Postcondition:
local q, r
-- Returns string, or false
local s = type( ask )
if s == "table" then
q = ask
local q, r
if s == "table" then
elseif s == "string" then
q = Multilingual.getLang(ask)
q = ask
end
elseif s == "string" then
if q and
q = Multilingual.getLang( ask )
end
q.legal and
mw.language.isKnownLanguageTag(q.base) then
if q and
r = q.base
q.legal and
if q.n > 1 then
mw.language.isKnownLanguageTag( q.base ) then
local order = { "extlang",
r = q.base
"script",
if q.n > 1 then
"region",
local order = { "extlang",
"other",
"script",
"extension" }
"region",
for i = 1, #order do
"other",
s = q[order[i]]
"extension" }
if s then
for i = 1, #order do
r = string.format("%s-%s", r, s)
s = q[ order[ i ] ]
end
if s then
end -- for i
r = string.format( "%s-%s", r, s )
end
end
end
end -- for i
return r or false
end
end
return r or false
end -- Multilingual.fair()
end -- Multilingual.fair()


Multilingual.fallback = function(able, another)

-- Is another language suitable as replacement?

-- Precondition:
Multilingual.fallback = function ( able, another )
-- able -- language version specifier to be supported
-- Is another language suitable as replacement?
-- another -- language specifier of a possible replacement,
-- Precondition:
-- or not to retrieve a fallback table
-- able -- language version specifier to be supported
-- Postcondition:
-- another -- language specifier of a possible replacement,
-- or not to retrieve a fallback table
-- Returns boolean, or table with fallback codes
local r
-- Postcondition:
if type(able) == "string" and #able > 0 then
-- Returns boolean, or table with fallback codes
if type(another) == "string" and #another > 0 then
local r
if type( able ) == "string" and #able > 0 then
if able == another then
r = true
if type( another ) == "string" and #another > 0 then
else
if able == another then
local s = Multilingual.getBase(able)
r = true
if s == another then
else
r = true
local s = Multilingual.getBase( able )
else
if s == another then
local others = mw.language.getFallbacksFor(s)
r = true
r = feasible(another, others)
else
end
local others = mw.language.getFallbacksFor( s )
end
r = feasible( another, others )
else
end
local s = Multilingual.getBase(able)
end
if s then
else
r = mw.language.getFallbacksFor(s)
local s = Multilingual.getBase( able )
if s then
if r[1] == "en" then
local d = fetchISO639("fallback")
r = mw.language.getFallbacksFor( s )
if r[ 1 ] == "en" then
if type(d) == "table" and
type(d[s]) == "string" then
local d = fetchISO639( "fallback" )
r = mw.text.split(d[s], "|")
if type( d ) == "table" and
table.insert(r, "en")
type( d[ s ] ) == "string" then
end
r = mw.text.split( d[ s ], "|" )
end
table.insert( r, "en" )
end
end
end
end
end
end
return r or false
end
end
return r or false
end -- Multilingual.fallback()
end -- Multilingual.fallback()


Multilingual.findCode = function(ask)

-- Retrieve code of local (current project or English) language name

-- Precondition:
Multilingual.findCode = function ( ask )
-- Retrieve code of local (current project or English) language name
-- ask -- string, with presumable language name
-- A code itself will be identified, too.
-- Precondition:
-- Postcondition:
-- ask -- string, with presumable language name
-- Returns string, or false
-- A code itself will be identified, too.
local seek = mw.text.trim(ask)
-- Postcondition:
local r = false
-- Returns string, or false
if #seek > 1 then
local seek = mw.text.trim( ask )
if seek:find("[", 1, true) then
local r = false
local wlink = fetch("WLink")
if #seek > 1 then
if wlink and
if seek:find( "[", 1, true ) then
local wlink = fetch( "WLink" )
type(wlink.getPlain) == "function" then
seek = wlink.getPlain(seek)
if wlink and
end
type( wlink.getPlain ) == "function" then
end
seek = wlink.getPlain( seek )
seek = mw.ustring.lower(seek)
end
if Multilingual.isLang(seek) then
end
seek = mw.ustring.lower( seek )
r = Multilingual.fair(seek)
else
if Multilingual.isLang( seek ) then
local collection = favorites()
r = Multilingual.fair( seek )
for i = 1, #collection do
else
local collection = favorites()
r = find(seek, collection[i])
if r then
for i = 1, #collection do
break -- for i
r = find( seek, collection[ i ] )
end
if r then
break -- for i
end -- for i
end
end
end
end -- for i
return r
end
end
return r
end -- Multilingual.findCode()
end -- Multilingual.findCode()


Multilingual.fix = function(attempt)

-- Fix frequently mistaken language code

-- Precondition:
Multilingual.fix = function ( attempt )
-- Fix frequently mistaken language code
-- attempt -- string, with presumable language code
-- Postcondition:
-- Precondition:
-- Returns string with correction, or false if no problem known
-- attempt -- string, with presumable language code
local r = fetchISO639("correction")[attempt:lower()]
-- Postcondition:
return r or false
-- Returns string with correction, or false if no problem known
local r = fetchISO639( "correction" )[ attempt:lower() ]
return r or false
end -- Multilingual.fix()
end -- Multilingual.fix()


Multilingual.format = function(apply, alien, alter, active, alert,

frame, assembly, adjacent, ahead)

-- Format one or more languages
Multilingual.format = function ( apply, alien, alter, active, alert,
-- Precondition:
frame, assembly, adjacent, ahead )
-- apply -- string with language list or item
-- Format one or more languages
-- alien -- language of the answer
-- Precondition:
-- -- nil, false, "*": native
-- apply -- string with language list or item
-- -- "!": current project
-- alien -- language of the answer
-- -- "#": code, downcased, space separated
-- -- nil, false, "*": native
-- -- "-": code, mixcase, space separated
-- -- "!": current project
-- -- any valid code
-- -- "#": code, downcased, space separated
-- alter -- capitalize, if "c"; downcase all, if "d"
-- -- "-": code, mixcase, space separated
-- capitalize first item only, if "f"
-- -- any valid code
-- downcase every first word only, if "m"
-- alter -- capitalize, if "c"; downcase all, if "d"
-- active -- link items, if true
-- capitalize first item only, if "f"
-- alert -- string with category title in case of error
-- downcase every first word only, if "m"
-- active -- link items, if true
-- frame -- if available
-- alert -- string with category title in case of error
-- assembly -- string with split pattern, if list expected
-- adjacent -- string with list separator, else assembly
-- frame -- if available
-- assembly -- string with split pattern, if list expected
-- ahead -- string to prepend first element, if any
-- Postcondition:
-- adjacent -- string with list separator, else assembly
-- ahead -- string to prepend first element, if any
-- Returns string, or false if apply empty
local r = false
-- Postcondition:
if apply then
-- Returns string, or false if apply empty
local r = false
local slang
if apply then
if assembly then
local bucket = mw.text.split(apply, assembly)
local slang
local shift = alter
if assembly then
local separator
local bucket = mw.text.split( apply, assembly )
if adjacent then
local shift = alter
separator = adjacent
local separator
if adjacent then
elseif alien == "#" or alien == "-" then
separator = adjacent
separator = " "
else
elseif alien == "#" or alien == "-" then
separator = " "
separator = assembly
end
else
for k, v in pairs(bucket) do
separator = assembly
slang = Multilingual.format(v, alien, shift, active,
end
alert)
for k, v in pairs( bucket ) do
if slang then
slang = Multilingual.format( v, alien, shift, active,
if r then
alert )
r = string.format("%s%s%s",
if slang then
r, separator, slang)
if r then
else
r = string.format( "%s%s%s",
r = slang
r, separator, slang )
if shift == "f" then
else
shift = "d"
r = slang
end
if shift == "f" then
end
shift = "d"
end
end
end -- for k, v
end
if r and ahead then
end
r = ahead .. r
end -- for k, v
end
if r and ahead then
else
r = ahead .. r
local single = mw.text.trim(apply)
end
if single == "" then
else
r = false
local single = mw.text.trim( apply )
else
if single == "" then
local lapsus, slot
r = false
slang = Multilingual.findCode(single)
else
if slang then
local lapsus, slot
if alien == "-" then
slang = Multilingual.findCode( single )
r = slang
if slang then
if alien == "-" then
elseif alien == "#" then
r = slang
r = slang:lower()
else
elseif alien == "#" then
r = Multilingual.getName(slang, alien)
r = slang:lower()
if active then
else
slot = fill(slang, false, frame)
r = Multilingual.getName( slang, alien )
if active then
if slot then
local wlink = fetch("WLink")
slot = fill( slang, false, frame )
if wlink and
if slot then
type(wlink.getTarget) == "function" then
local wlink = fetch( "WLink" )
slot = wlink.getTarget(slot)
if wlink and
end
type( wlink.getTarget )
else
== "function" then
lapsus = alert
slot = wlink.getTarget( slot )
end
end
end
else
end
lapsus = alert
else
end
r = single
end
if active then
end
local title = mw.title.makeTitle(0, single)
else
if title.exists then
r = single
slot = single
if active then
end
local title = mw.title.makeTitle( 0, single )
end
if title.exists then
lapsus = alert
slot = single
end
end
if not r then
end
r = single
lapsus = alert
elseif alter == "c" or alter == "f" then
end
r = mw.ustring.upper(mw.ustring.sub(r, 1, 1))
if not r then
.. mw.ustring.sub(r, 2)
r = single
elseif alter == "c" or alter == "f" then
elseif alter == "d" then
if Multilingual.isMinusculable(slang, r) then
r = mw.ustring.upper( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
r = mw.ustring.lower(r)
end
elseif alter == "d" then
elseif alter == "m" then
if Multilingual.isMinusculable( slang, r ) then
if Multilingual.isMinusculable(slang, r) then
r = mw.ustring.lower( r )
r = mw.ustring.lower(mw.ustring.sub(r, 1, 1))
end
.. mw.ustring.sub(r, 2)
elseif alter == "m" then
end
if Multilingual.isMinusculable( slang, r ) then
end
r = mw.ustring.lower( mw.ustring.sub( r, 1, 1 ) )
if slot then
.. mw.ustring.sub( r, 2 )
if r == slot then
end
r = string.format("[[%s]]", r)
end
else
if slot then
r = string.format("[[%s|%s]]", slot, r)
if r == slot then
end
r = string.format( "[[%s]]", r )
end
else
if lapsus and alert then
r = string.format( "[[%s|%s]]", slot, r )
r = string.format("%s[[Category:%s]]", r, alert)
end
end
end
end
if lapsus and alert then
end
r = string.format( "%s[[Category:%s]]", r, alert )
end
end
return r
end
end
end
return r
end -- Multilingual.format()
end -- Multilingual.format()


Multilingual.getBase = function(ask)

-- Retrieve base language from possibly combined ISO language code

-- Precondition:
Multilingual.getBase = function ( ask )
-- Retrieve base language from possibly combined ISO language code
-- ask -- language code
-- Postcondition:
-- Precondition:
-- Returns string, or false
-- ask -- language code
local r
-- Postcondition:
if ask then
-- Returns string, or false
local slang = ask:match("^%s*(%a%a%a?)-?%a*%s*$")
local r
if ask then
if slang then
r = slang:lower()
local slang = ask:match( "^%s*(%a%a%a?)-?%a*%s*$" )
else
if slang then
r = false
r = slang:lower()
end
else
else
r = false
r = false
end
end
else
return r
r = false
end
return r
end -- Multilingual.getBase()
end -- Multilingual.getBase()


Multilingual.getLang = function(ask)

-- Retrieve components of a RFC 5646 language code

-- Precondition:
Multilingual.getLang = function ( ask )
-- ask -- language code with subtags
-- Retrieve components of a RFC 5646 language code
-- Postcondition:
-- Precondition:
-- ask -- language code with subtags
-- Returns table with formatted subtags
-- .base
-- Postcondition:
-- .region
-- Returns table with formatted subtags
-- .script
-- .base
-- .suggest
-- .region
-- .year
-- .script
-- .extension
-- .suggest
-- .other
-- .year
-- .n
-- .extension
local tags = mw.text.split(ask, "-")
-- .other
local s = tags[1]
-- .n
local r
local tags = mw.text.split( ask, "-" )
if s:match("^%a%a%a?$") then
local s = tags[ 1 ]
r = { base = s:lower(),
local r
legal = true,
if s:match( "^%a%a%a?$" ) then
n = #tags }
r = { base = s:lower(),
for i = 2, r.n do
legal = true,
n = #tags }
s = tags[i]
if #s == 2 then
for i = 2, r.n do
if r.region or not s:match("%a%a") then
s = tags[ i ]
r.legal = false
if #s == 2 then
else
if r.region or not s:match( "%a%a" ) then
r.region = s:upper()
r.legal = false
end
else
elseif #s == 4 then
r.region = s:upper()
if s:match("%a%a%a%a") then
end
r.legal = (not r.script)
elseif #s == 4 then
r.script = s:sub(1, 1):upper() ..
if s:match( "%a%a%a%a" ) then
s:sub(2):lower()
r.legal = ( not r.script )
elseif s:match("20%d%d") or
r.script = s:sub( 1, 1 ):upper() ..
s:match("1%d%d%d") then
s:sub( 2 ):lower()
r.legal = (not r.year)
elseif s:match( "20%d%d" ) or
r.year = s
s:match( "1%d%d%d" ) then
else
r.legal = ( not r.year )
r.legal = false
r.year = s
end
else
elseif #s == 3 then
r.legal = false
if r.extlang or not s:match("%a%a%a") then
end
r.legal = false
elseif #s == 3 then
else
if r.extlang or not s:match( "%a%a%a" ) then
r.extlang = s:lower()
r.legal = false
end
else
elseif #s == 1 then
r.extlang = s:lower()
s = s:lower()
end
if s:match("[tux]") then
elseif #s == 1 then
r.extension = s
s = s:lower()
for k = i + 1, r.n do
if s:match( "[tux]" ) then
s = tags[k]
r.extension = s
if s:match("^%w+$") then
for k = i + 1, r.n do
r.extension = string.format("%s-%s",
s = tags[ k ]
r.extension, s)
if s:match( "^%w+$" ) then
else
r.extension = string.format( "%s-%s",
r.legal = false
r.extension, s )
end
else
end -- for k
r.legal = false
else
end
r.legal = false
end -- for k
end
else
break -- for i
r.legal = false
else
end
r.legal = (not r.other) and
break -- for i
s:match("%a%a%a")
else
r.other = s:lower()
r.legal = ( not r.other ) and
end
s:match( "%a%a%a" )
if not r.legal then
r.other = s:lower()
break -- for i
end
end
if not r.legal then
break -- for i
end -- for i
if r.legal then
end
r.suggest = Multilingual.fix(r.base)
end -- for i
if r.legal then
if r.suggest then
r.legal = false
r.suggest = Multilingual.fix( r.base )
end
if r.suggest then
end
r.legal = false
else
end
end
r = { legal = false }
end
else
r = { legal = false }
if not r.legal then
local cnf = fetch("Multilingual", "config")
end
if not r.legal then
if cnf and type(cnf.scream) == "string" then
r.scream = cnf.scream
local cnf = fetch( "Multilingual", "config" )
end
if cnf and type( cnf.scream ) == "string" then
end
r.scream = cnf.scream
return r
end
end
return r
end -- Multilingual.getLang()
end -- Multilingual.getLang()


Multilingual.getName = function(ask, alien)

-- Which name is assigned to this language code?

-- Precondition:
Multilingual.getName = function ( ask, alien )
-- Which name is assigned to this language code?
-- ask -- language code
-- alien -- language of the answer
-- Precondition:
-- -- nil, false, "*": native
-- ask -- language code
-- -- "!": current project
-- alien -- language of the answer
-- -- nil, false, "*": native
-- -- any valid code
-- Postcondition:
-- -- "!": current project
-- Returns string, or false
-- -- any valid code
local r
-- Postcondition:
if ask then
-- Returns string, or false
local slang = alien
local r
local tLang
if ask then
local slang = alien
if slang then
if slang == "*" then
local tLang
slang = Multilingual.fair(ask)
if slang then
if slang == "*" then
elseif slang == "!" then
slang = favorites()[1]
slang = Multilingual.fair( ask )
else
elseif slang == "!" then
slang = Multilingual.fair(slang)
slang = favorites()[ 1 ]
end
else
else
slang = Multilingual.fair( slang )
slang = Multilingual.fair(ask)
end
end
else
if not slang then
slang = Multilingual.fair( ask )
slang = ask or "?????"
end
end
if not slang then
slang = ask or "?????"
slang = slang:lower()
tLang = fetch("Multilingual", "names")
end
if tLang then
slang = slang:lower()
tLang = tLang[slang]
tLang = fetch( "Multilingual", "names" )
if tLang then
if tLang then
tLang = tLang[ slang ]
r = tLang[ask]
end
if tLang then
end
r = tLang[ ask ]
if not r then
end
if not Multilingual.ext.tMW then
end
Multilingual.ext.tMW = {}
if not r then
end
if not Multilingual.ext.tMW then
Multilingual.ext.tMW = { }
tLang = Multilingual.ext.tMW[slang]
if tLang == nil then
end
tLang = Multilingual.ext.tMW[ slang ]
tLang = mw.language.fetchLanguageNames(slang)
if tLang == nil then
if tLang then
Multilingual.ext.tMW[slang] = tLang
tLang = mw.language.fetchLanguageNames( slang )
else
if tLang then
Multilingual.ext.tMW[ slang ] = tLang
Multilingual.ext.tMW[slang] = false
end
else
end
Multilingual.ext.tMW[ slang ] = false
if tLang then
end
r = tLang[ask]
end
end
if tLang then
end
r = tLang[ ask ]
if not r then
end
r = mw.language.fetchLanguageName(ask:lower(), slang)
end
if not r then
if r == "" then
r = false
r = mw.language.fetchLanguageName( ask:lower(), slang )
end
if r == "" then
end
r = false
else
end
r = false
end
end
else
return r
r = false
end
return r
end -- Multilingual.getName()
end -- Multilingual.getName()


Multilingual.i18n = function(available, alt, frame)

-- Select translatable message

-- Precondition:
Multilingual.i18n = function ( available, alt, frame )
-- available -- table, with mapping language code ./. text
-- Select translatable message
-- alt -- string|nil|false, with fallback text
-- Precondition:
-- frame -- frame, if available
-- available -- table, with mapping language code ./. text
-- Returns
-- alt -- string|nil|false, with fallback text
-- 1. string|nil|false, with selected message
-- frame -- frame, if available
-- 2. string|nil|false, with language code
-- Returns
local r1, r2
-- 1. string|nil|false, with selected message
if type(available) == "table" then
-- 2. string|nil|false, with language code
local codes = {}
local r1, r2
local trsl = {}
if type( available ) == "table" then
local codes = { }
local slang
for k, v in pairs(available) do
local trsl = { }
if type(k) == "string" and
local slang
type(v) == "string" then
for k, v in pairs( available ) do
slang = mw.text.trim(k:lower())
if type( k ) == "string" and
table.insert(codes, slang)
type( v ) == "string" then
trsl[slang] = v
slang = mw.text.trim( k:lower() )
end
table.insert( codes, slang )
end -- for k, v
trsl[ slang ] = v
slang = Multilingual.userLang(codes, frame)
end
if slang and trsl[slang] then
end -- for k, v
r1 = mw.text.trim(trsl[slang])
slang = Multilingual.userLang( codes, frame )
if slang and trsl[ slang ] then
if r1 == "" then
r1 = false
r1 = mw.text.trim( trsl[ slang ] )
else
if r1 == "" then
r2 = slang
r1 = false
end
else
end
r2 = slang
end
end
if not r1 and type(alt) == "string" then
end
r1 = mw.text.trim(alt)
end
if not r1 and type( alt ) == "string" then
if r1 == "" then
r1 = false
r1 = mw.text.trim( alt )
end
if r1 == "" then
end
r1 = false
return r1, r2
end
end
return r1, r2
end -- Multilingual.i18n()
end -- Multilingual.i18n()


Multilingual.int = function(access, alien, apply)

-- Translated system message

-- Precondition:
Multilingual.int = function ( access, alien, apply )
-- Translated system message
-- access -- message ID
-- Precondition:
-- alien -- language code
-- access -- message ID
-- apply -- nil, or sequence table with parameters $1, $2, ...
-- Postcondition:
-- alien -- language code
-- Returns string, or false
-- apply -- nil, or sequence table with parameters $1, $2, ...
local o = mw.message.new(access)
-- Postcondition:
local r
-- Returns string, or false
if o:exists() then
local o = mw.message.new( access )
if type(alien) == "string" then
local r
o:inLanguage(alien:lower())
if o:exists() then
end
if type( alien ) == "string" then
if type(apply) == "table" then
o:inLanguage( alien:lower() )
o:params(apply)
end
end
if type( apply ) == "table" then
r = o:plain()
o:params( apply )
end
end
return r or false
r = o:plain()
end
return r or false
end -- Multilingual.int()
end -- Multilingual.int()


Multilingual.isLang = function(ask, additional)

-- Could this be an ISO language code?

-- Precondition:
Multilingual.isLang = function ( ask, additional )
-- Could this be an ISO language code?
-- ask -- language code
-- additional -- true, if Wiki codes like "simple" permitted
-- Precondition:
-- Postcondition:
-- ask -- language code
-- Returns boolean
-- additional -- true, if Wiki codes like "simple" permitted
local r, s
-- Postcondition:
if additional then
-- Returns boolean
s = ask
local r, s
else
if additional then
s = Multilingual.getBase(ask)
s = ask
end
else
if s then
s = Multilingual.getBase( ask )
r = mw.language.isKnownLanguageTag(s)
end
if s then
if r then
r = not Multilingual.fix(s)
r = mw.language.isKnownLanguageTag( s )
if r then
elseif additional then
r = not Multilingual.fix( s )
r = Multilingual.exotic[s] or false
end
elseif additional then
else
r = Multilingual.exotic[ s ] or false
r = false
end
end
else
return r
r = false
end
return r
end -- Multilingual.isLang()
end -- Multilingual.isLang()


Multilingual.isLangWiki = function(ask)

-- Could this be a Wiki language version?

-- Precondition:
Multilingual.isLangWiki = function ( ask )
-- Could this be a Wiki language version?
-- ask -- language version specifier
-- Postcondition:
-- Precondition:
-- Returns boolean
-- ask -- language version specifier
local r
-- Postcondition:
local s = Multilingual.getBase(ask)
-- Returns boolean
if s then
local r
r = mw.language.isSupportedLanguage(s) or
local s = Multilingual.getBase( ask )
Multilingual.exotic[ask]
if s then
else
r = mw.language.isSupportedLanguage( s ) or
r = false
Multilingual.exotic[ ask ]
end
else
return r
r = false
end
return r
end -- Multilingual.isLangWiki()
end -- Multilingual.isLangWiki()


Multilingual.isMinusculable = function(ask, assigned)

-- Could this language name become downcased?

-- Precondition:
Multilingual.isMinusculable = function ( ask, assigned )
-- Could this language name become downcased?
-- ask -- language code, or nil
-- assigned -- language name, or nil
-- Precondition:
-- Postcondition:
-- ask -- language code, or nil
-- Returns boolean
-- assigned -- language name, or nil
local r = true
-- Postcondition:
if ask then
-- Returns boolean
local cnf = fetch("Multilingual", "config")
local r = true
if ask then
if cnf then
local cnf = fetch( "Multilingual", "config" )
local s = string.format(" %s ", ask:lower())
if type(cnf.stopMinusculization) == "string"
if cnf then
and cnf.stopMinusculization:find(s, 1, true) then
local s = string.format( " %s ", ask:lower() )
r = false
if type( cnf.stopMinusculization ) == "string"
end
and cnf.stopMinusculization:find( s, 1, true ) then
if r and assigned
r = false
and type(cnf.seekMinusculization) == "string"
end
and cnf.seekMinusculization:find(s, 1, true)
if r and assigned
and type( cnf.seekMinusculization ) == "string"
and type(cnf.scanMinusculization) == "string" then
local scan = assigned:gsub("[%(%)]", " ") .. " "
and cnf.seekMinusculization:find( s, 1, true )
and type( cnf.scanMinusculization ) == "string" then
if not scan:find(cnf.scanMinusculization) then
r = false
local scan = assigned:gsub( "[%(%)]", " " ) .. " "
end
if not scan:find( cnf.scanMinusculization ) then
end
r = false
end
end
end
end
return r
end
end
return r
end -- Multilingual.isMinusculable()
end -- Multilingual.isMinusculable()


Multilingual.isRTL = function(ask)

-- Check whether language is written right-to-left

-- Precondition:
Multilingual.isRTL = function ( ask )
-- Check whether language is written right-to-left
-- ask -- string, with language (or script) code
-- Returns true, if right-to-left
-- Precondition:
local r
-- ask -- string, with language (or script) code
Multilingual.rtl = Multilingual.rtl or {}
-- Returns true, if right-to-left
r = Multilingual.rtl[ask]
local r
if type(r) ~= "boolean" then
Multilingual.rtl = Multilingual.rtl or { }
local bib = fetch("ISO15924")
r = Multilingual.rtl[ ask ]
if type( r ) ~= "boolean" then
if type(bib) == "table" and
local bib = fetch( "ISO15924" )
type(bib.isRTL) == "function" then
r = bib.isRTL(ask)
if type( bib ) == "table" and
else
type( bib.isRTL ) == "function" then
r = bib.isRTL( ask )
r = mw.language.new(ask):isRTL()
end
else
Multilingual.rtl[ask] = r
r = mw.language.new( ask ):isRTL()
end
end
return r
Multilingual.rtl[ ask ] = r
end
return r
end -- Multilingual.isRTL()
end -- Multilingual.isRTL()


Multilingual.message = function(arglist, frame)

-- Show text in best match of user language like system message

-- Precondition:
Multilingual.message = function ( arglist, frame )
-- arglist -- template arguments
-- Show text in best match of user language like system message
-- frame -- frame, if available
-- Precondition:
-- Postcondition:
-- arglist -- template arguments
-- Returns string with appropriate text
-- frame -- frame, if available
local r
-- Postcondition:
if type(arglist) == "table" then
-- Returns string with appropriate text
local t = {}
local r
local m, p, save
if type( arglist ) == "table" then
for k, v in pairs(arglist) do
local t = { }
if type(k) == "string" and
local m, p, save
type(v) == "string" then
for k, v in pairs( arglist ) do
v = mw.text.trim(v)
if type( k ) == "string" and
type( v ) == "string" then
if v ~= "" then
if k:match("^%l%l") then
v = mw.text.trim( v )
t[k] = v
if v ~= "" then
if k:match( "^%l%l" ) then
elseif k:match("^%$%d$") and k ~= "$0" then
p = p or {}
t[ k ] = v
elseif k:match( "^%$%d$" ) and k ~= "$0" then
k = tonumber(k:match("^%$(%d)$"))
p[k] = v
p = p or { }
if not m or k > m then
k = tonumber( k:match( "^%$(%d)$" ) )
m = k
p[ k ] = v
end
if not m or k > m then
end
m = k
end
end
end
end
end -- for k, v
end
if type(arglist["-"]) == "string" then
end
save = arglist[arglist["-"]]
end -- for k, v
end
if type( arglist[ "-" ] ) == "string" then
r = Multilingual.i18n(t, save, frame)
save = arglist[ arglist[ "-" ] ]
if p and r and r:find("$", 1, true) then
end
t = {}
r = Multilingual.i18n( t, save, frame )
for i = 1, m do
if p and r and r:find( "$", 1, true ) then
t[i] = p[i] or ""
t = { }
for i = 1, m do
end -- for i
r = mw.message.newRawMessage(r, t):plain()
t[ i ] = p[ i ] or ""
end
end -- for i
end
r = mw.message.newRawMessage( r, t ):plain()
return r or ""
end
end
return r or ""
end -- Multilingual.message()
end -- Multilingual.message()


Multilingual.sitelink = function(all, frame)

-- Make link at local or other site with optimal linktext translation

-- Precondition:
Multilingual.sitelink = function ( all, frame )
-- all -- string or table or number, item ID or entity
-- Make link at local or other site with optimal linktext translation
-- frame -- frame, if available
-- Precondition:
-- Postcondition:
-- all -- string or table or number, item ID or entity
-- Returns string with any helpful internal link, or plain text
-- frame -- frame, if available
local s = type(all)
-- Postcondition:
local object, r
-- Returns string with any helpful internal link, or plain text
local s = type( all )
if s == "table" then
object = all
local object, r
if s == "table" then
elseif s == "string" then
object = all
object = mw.wikibase.getEntity(all)
elseif s == "string" then
elseif s == "number" then
object = mw.wikibase.getEntity( all )
object = mw.wikibase.getEntity(string.format("Q%d", all))
end
elseif s == "number" then
if type(object) == "table" then
object = mw.wikibase.getEntity( string.format( "Q%d", all ) )
local collection = object.sitelinks
end
local entry
if type( object ) == "table" then
s = false
local collection = object.sitelinks
if type(collection) == "table" then
local entry
Multilingual.site = Multilingual.site or
s = false
mw.wikibase.getGlobalSiteId()
if type( collection ) == "table" then
Multilingual.site = Multilingual.site or
entry = collection[Multilingual.site]
if entry then
mw.wikibase.getGlobalSiteId()
s = ":" .. entry.title
entry = collection[ Multilingual.site ]
elseif collection.enwiki then
if entry then
s = ":" .. entry.title
s = "w:en:" .. collection.enwiki.title
end
elseif collection.enwiki then
end
s = "w:en:" .. collection.enwiki.title
r = Multilingual.wikibase(object, "labels", frame)
end
if s then
end
if s == ":" .. r then
r = Multilingual.wikibase( object, "labels", frame )
r = string.format("[[%s]]", s)
if s then
else
if s == ":" .. r then
r = string.format( "[[%s]]", s )
r = string.format("[[%s|%s]]", s, r)
end
else
end
r = string.format( "[[%s|%s]]", s, r )
end
end
return r or ""
end
end
return r or ""
end -- Multilingual.sitelink()
end -- Multilingual.sitelink()


Multilingual.tabData = function(access, at, alt, frame)

-- Retrieve translated keyword from commons:Data:****.tab

-- Precondition:
Multilingual.tabData = function ( access, at, alt, frame )
-- access -- string, with page identification on Commons
-- Retrieve translated keyword from commons:Data:****.tab
-- at -- string, with keyword
-- Precondition:
-- access -- string, with page identification on Commons
-- alt -- string|nil|false, with fallback text
-- at -- string, with keyword
-- frame -- frame, if available
-- Returns
-- alt -- string|nil|false, with fallback text
-- 1. string|nil|false, with selected message
-- frame -- frame, if available
-- 2. language code, or "error"
-- Returns
local data = fetchData(access)
-- 1. string|nil|false, with selected message
local r1, r2
-- 2. language code, or "error"
local data = fetchData( access )
if type(data) == "table" then
if type(at) == "string" then
local r1, r2
local seek = mw.text.trim(at)
if type( data ) == "table" then
if type( at ) == "string" then
if seek == "" then
r1 = "EMPTY Multilingual.tabData key"
local seek = mw.text.trim( at )
else
if seek == "" then
local e, poly
r1 = "EMPTY Multilingual.tabData key"
for i = 1, #data do
else
e = data[i]
local e, poly
if type(e) == "table" then
for i = 1, #data do
if e[1] == seek then
e = data[ i ]
if type( e ) == "table" then
if type(e[2]) == "table" then
poly = e[2]
if e[ 1 ] == seek then
else
if type( e[ 2 ] ) == "table" then
r1 = "INVALID Multilingual.tabData bad #"
poly = e[ 2 ]
.. tostring(i)
else
end
r1 = "INVALID Multilingual.tabData bad #"
break -- for i
.. tostring( i )
end
end
else
break -- for i
break -- for i
end
end
else
break -- for i
end -- for i
if poly then
end
data = poly
end -- for i
else
if poly then
r1 = "UNKNOWN Multilingual.tabData key: " .. seek
data = poly
end
else
end
r1 = "UNKNOWN Multilingual.tabData key: " .. seek
else
end
r1 = "INVALID Multilingual.tabData key"
end
end
else
else
r1 = "INVALID Multilingual.tabData key"
r1 = data
end
end
else
r1 = data
if r1 then
r2 = "error"
end
if r1 then
elseif data then
r1, r2 = Multilingual.i18n(data, alt, frame)
r2 = "error"
r2 = r2 or "error"
elseif data then
end
r1, r2 = Multilingual.i18n( data, alt, frame )
return r1, r2
r2 = r2 or "error"
end
return r1, r2
end -- Multilingual.tabData()
end -- Multilingual.tabData()


Multilingual.userLang = function(accept, frame)

-- Try to support user language by application

-- Precondition:
Multilingual.userLang = function ( accept, frame )
-- accept -- string or table
-- Try to support user language by application
-- space separated list of available ISO 639 codes
-- Precondition:
-- Default: project language, or English
-- accept -- string or table
-- space separated list of available ISO 639 codes
-- frame -- frame, if available
-- Postcondition:
-- Default: project language, or English
-- Returns string with appropriate code
-- frame -- frame, if available
local s = type(accept)
-- Postcondition:
local codes, r, slang
-- Returns string with appropriate code
if s == "string" then
local s = type( accept )
codes = mw.text.split(accept:lower(), "%s+")
local codes, r, slang
if s == "string" then
elseif s == "table" then
codes = {}
codes = mw.text.split( accept:lower(), "%s+" )
for i = 1, #accept do
elseif s == "table" then
s = accept[i]
codes = { }
if type(s) == "string" and
for i = 1, #accept do
s = accept[ i ]
s ~= "" then
table.insert(codes, s:lower())
if type( s ) == "string" and
end
s ~= "" then
end -- for i
table.insert( codes, s:lower() )
end
end
slang = User.favorize(codes, frame)
end -- for i
if slang then
end
slang = User.favorize( codes, frame )
if feasible(slang, codes) then
if slang then
r = slang
if feasible( slang, codes ) then
elseif slang:find("-", 1, true) then
slang = Multilingual.getBase(slang)
r = slang
elseif slang:find( "-", 1, true ) then
if feasible(slang, codes) then
r = slang
slang = Multilingual.getBase( slang )
end
if feasible( slang, codes ) then
end
r = slang
if not r then
end
local others = mw.language.getFallbacksFor(slang)
end
for i = 1, #others do
if not r then
slang = others[i]
local others = mw.language.getFallbacksFor( slang )
if feasible(slang, codes) then
for i = 1, #others do
r = slang
slang = others[ i ]
break -- for i
if feasible( slang, codes ) then
end
r = slang
break -- for i
end -- for i
end
end
end
end -- for i
if not r then
end
local back = favorites()
end
for i = 1, #back do
if not r then
slang = back[i]
local back = favorites()
if feasible(slang, codes) then
for i = 1, #back do
slang = back[ i ]
r = slang
break -- for i
if feasible( slang, codes ) then
end
r = slang
break -- for i
end -- for i
if not r and codes[1] then
end
r = codes[1]
end -- for i
end
if not r and codes[ 1 ] then
end
r = codes[ 1 ]
return r or favorites()[1]
end
end
return r or favorites()[ 1 ]
end -- Multilingual.userLang()
end -- Multilingual.userLang()


Multilingual.userLangCode = function()

-- Guess a user language code

-- Postcondition:
Multilingual.userLangCode = function ()
-- Returns code of current best guess
-- Guess a user language code
return User.self or favorites()[1]
-- Postcondition:
-- Returns code of current best guess
return User.self or favorites()[ 1 ]
end -- Multilingual.userLangCode()
end -- Multilingual.userLangCode()


Multilingual.wikibase = function(all, about, attempt, frame)

-- Optimal translation of wikibase component

-- Precondition:
Multilingual.wikibase = function ( all, about, attempt, frame )
-- all -- string or table, object ID or entity
-- Optimal translation of wikibase component
-- about -- boolean, true "descriptions" or false "labels"
-- Precondition:
-- all -- string or table, object ID or entity
-- attempt -- string or not, code of preferred language
-- frame -- frame, if available
-- about -- boolean, true "descriptions" or false "labels"
-- Postcondition:
-- attempt -- string or not, code of preferred language
-- Returns
-- frame -- frame, if available
-- 1. string, with selected message
-- Postcondition:
-- 2. string, with language code, or not
-- Returns
local s = type(all)
-- 1. string, with selected message
local object, r, r2
-- 2. string, with language code, or not
local s = type( all )
if s == "table" then
local object, r, r2
object = all
if s == "table" then
elseif s == "string" then
object = all
object = mw.wikibase.getEntity(all)
end
elseif s == "string" then
object = mw.wikibase.getEntity( all )
if type(object) == "table" then
if about and about ~= "labels" then
end
s = "descriptions"
if type( object ) == "table" then
else
if about and about ~= "labels" then
s = "labels"
s = "descriptions"
end
else
object = object[s]
s = "labels"
if type(object) == "table" then
end
object = object[ s ]
if object[attempt] then
r = object[attempt].value
if type( object ) == "table" then
if object[ attempt ] then
r2 = attempt
else
r = object[ attempt ].value
local poly
r2 = attempt
for k, v in pairs(object) do
else
poly = poly or {}
local poly
poly[k] = v.value
for k, v in pairs( object ) do
end -- for k, v
poly = poly or { }
if poly then
poly[ k ] = v.value
r, r2 = Multilingual.i18n(poly, nil, frame)
end -- for k, v
end
if poly then
end
r, r2 = Multilingual.i18n( poly, nil, frame )
end
end
end
end
end
return r or "", r2
end
return r or "", r2
end -- Multilingual.wikibase()
end -- Multilingual.wikibase()


Failsafe.failsafe = function(atleast)

-- Retrieve versioning and check for compliance

-- Precondition:
Failsafe.failsafe = function ( atleast )
-- atleast -- string, with required version
-- Retrieve versioning and check for compliance
-- or wikidata|item|~|@ or false
-- Precondition:
-- Postcondition:
-- atleast -- string, with required version
-- Returns string -- with queried version/item, also if problem
-- or wikidata|item|~|@ or false
-- Postcondition:
-- false -- if appropriate
-- 2020-08-17
-- Returns string -- with queried version/item, also if problem
local since = atleast
-- false -- if appropriate
local last = (since == "~")
-- 2020-08-17
local since = atleast
local linked = (since == "@")
local last = ( since == "~" )
local link = (since == "item")
local r
local linked = ( since == "@" )
local link = ( since == "item" )
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
local r
since = false
if last or link or linked or since == "wikidata" then
if type(item) == "number" and item > 0 then
local item = Failsafe.item
local suited = string.format("Q%d", item)
since = false
if link then
if type( item ) == "number" and item > 0 then
r = suited
local suited = string.format( "Q%d", item )
else
if link then
local entity = mw.wikibase.getEntity(suited)
r = suited
if type(entity) == "table" then
else
local seek = Failsafe.serialProperty or "P348"
local entity = mw.wikibase.getEntity( suited )
local vsn = entity:formatPropertyValues(seek)
if type( entity ) == "table" then
if type(vsn) == "table" and
local seek = Failsafe.serialProperty or "P348"
type(vsn.value) == "string" and
local vsn = entity:formatPropertyValues( seek )
vsn.value ~= "" then
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
if last and vsn.value == Failsafe.serial then
r = false
vsn.value ~= "" then
elseif linked then
if last and vsn.value == Failsafe.serial then
if mw.title.getCurrentTitle().prefixedText
r = false
== mw.wikibase.getSitelink(suited) then
elseif linked then
r = false
if mw.title.getCurrentTitle().prefixedText
else
== mw.wikibase.getSitelink( suited ) then
r = suited
r = false
end
else
else
r = suited
r = vsn.value
end
end
else
end
r = vsn.value
end
end
end
end
end
end
end
end
if type(r) == "nil" then
end
if not since or since <= Failsafe.serial then
end
r = Failsafe.serial
if type( r ) == "nil" then
else
if not since or since <= Failsafe.serial then
r = false
r = Failsafe.serial
end
else
end
r = false
return r
end
end
return r
end -- Failsafe.failsafe()
end -- Failsafe.failsafe()




-- Export
-- Export
local p = { }
local p = {}


p.fair = function(frame)

-- Format language code

-- 1 -- language code
p.fair = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Format language code
return Multilingual.fair(s) or ""
-- 1 -- language code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.fair( s ) or ""
end -- p.fair
end -- p.fair


p.fallback = function(frame)

-- Is another language suitable as replacement?

-- 1 -- language version specifier to be supported
p.fallback = function ( frame )
-- Is another language suitable as replacement?
-- 2 -- language specifier of a possible replacement
local s1 = mw.text.trim(frame.args[1] or "")
-- 1 -- language version specifier to be supported
local s2 = mw.text.trim(frame.args[2] or "")
-- 2 -- language specifier of a possible replacement
local r = Multilingual.fallback(s1, s2)
local s1 = mw.text.trim( frame.args[ 1 ] or "" )
if type(r) == "table" then
local s2 = mw.text.trim( frame.args[ 2 ] or "" )
r = r[1]
local r = Multilingual.fallback( s1, s2 )
else
if type( r ) == "table" then
r = r[ 1 ]
r = r and "1" or ""
end
else
return r
r = r and "1" or ""
end
return r
end -- p.fallback
end -- p.fallback


p.findCode = function(frame)

-- Retrieve language code from language name

-- 1 -- name in current project language
p.findCode = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Retrieve language code from language name
return Multilingual.findCode(s) or ""
-- 1 -- name in current project language
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.findCode( s ) or ""
end -- p.findCode
end -- p.findCode


p.fix = function(frame)

local r = frame.args[1]

if r then
p.fix = function ( frame )
r = Multilingual.fix(mw.text.trim(r))
local r = frame.args[ 1 ]
end
if r then
return r or ""
r = Multilingual.fix( mw.text.trim( r ) )
end
return r or ""
end -- p.fix
end -- p.fix


p.format = function(frame)

-- Format one or more languages

-- 1 -- language list or item
p.format = function ( frame )
-- slang -- language of the answer, if not native
-- Format one or more languages
-- * -- native
-- 1 -- language list or item
-- ! -- current project
-- slang -- language of the answer, if not native
-- any valid code
-- * -- native
-- shift -- capitalize, if "c"; downcase, if "d"
-- ! -- current project
-- capitalize first item only, if "f"
-- any valid code
-- link -- 1 -- link items
-- shift -- capitalize, if "c"; downcase, if "d"
-- scream -- category title in case of error
-- capitalize first item only, if "f"
-- split -- split pattern, if list expected
-- link -- 1 -- link items
-- separator -- list separator, else split
-- scream -- category title in case of error
-- split -- split pattern, if list expected
-- start -- prepend first element, if any
local r
-- separator -- list separator, else split
local link
-- start -- prepend first element, if any
if frame.args.link == "1" then
local r
link = true
local link
end
if frame.args.link == "1" then
r = Multilingual.format(frame.args[1],
link = true
frame.args.slang,
end
r = Multilingual.format( frame.args[ 1 ],
frame.args.shift,
link,
frame.args.slang,
frame.args.shift,
frame.args.scream,
frame,
link,
frame.args.scream,
frame.args.split,
frame.args.separator,
frame,
frame.args.split,
frame.args.start)
return r or ""
frame.args.separator,
frame.args.start )
return r or ""
end -- p.format
end -- p.format


p.getBase = function(frame)

-- Retrieve base language from possibly combined ISO language code

-- 1 -- code
p.getBase = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Retrieve base language from possibly combined ISO language code
return Multilingual.getBase(s) or ""
-- 1 -- code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.getBase( s ) or ""
end -- p.getBase
end -- p.getBase


p.getName = function(frame)

-- Retrieve language name from ISO language code

-- 1 -- code
p.getName = function ( frame )
-- Retrieve language name from ISO language code
-- 2 -- language to be used for the answer, if not native
-- 1 -- code
-- ! -- current project
-- 2 -- language to be used for the answer, if not native
-- * -- native
-- any valid code
-- ! -- current project
local s = mw.text.trim(frame.args[1] or "")
-- * -- native
local slang = frame.args[2]
-- any valid code
local r
local s = mw.text.trim( frame.args[ 1 ] or "" )
local slang = frame.args[ 2 ]
Multilingual.frame = frame
if slang then
local r
slang = mw.text.trim(slang)
Multilingual.frame = frame
end
if slang then
slang = mw.text.trim( slang )
r = Multilingual.getName(s, slang)
return r or ""
end
r = Multilingual.getName( s, slang )
return r or ""
end -- p.getName
end -- p.getName


p.int = function(frame)

-- Translated system message

-- 1 -- message ID
p.int = function ( frame )
-- lang -- language code
-- Translated system message
-- 1 -- message ID
-- $1, $2, ... -- parameters
local sysMsg = frame.args[1]
-- lang -- language code
local r
-- $1, $2, ... -- parameters
local sysMsg = frame.args[ 1 ]
if sysMsg then
sysMsg = mw.text.trim(sysMsg)
local r
if sysMsg then
if sysMsg ~= "" then
local n = 0
sysMsg = mw.text.trim( sysMsg )
local slang = frame.args.lang
if sysMsg ~= "" then
local n = 0
local i, params, s
if slang == "" then
local slang = frame.args.lang
slang = false
local i, params, s
end
if slang == "" then
for k, v in pairs(frame.args) do
slang = false
if type(k) == "string" then
end
s = k:match("^%$(%d+)$")
for k, v in pairs( frame.args ) do
if s then
if type( k ) == "string" then
i = tonumber(s)
s = k:match( "^%$(%d+)$" )
if s then
if i > n then
n = i
i = tonumber( s )
end
if i > n then
end
n = i
end
end
end -- for k, v
end
if n > 0 then
end
local s
end -- for k, v
params = {}
if n > 0 then
for i = 1, n do
local s
s = frame.args["$" .. tostring(i)] or ""
params = { }
table.insert(params, s)
for i = 1, n do
end -- for i
s = frame.args[ "$" .. tostring( i ) ] or ""
end
table.insert( params, s )
r = Multilingual.int(sysMsg, slang, params)
end -- for i
end
end
end
r = Multilingual.int( sysMsg, slang, params )
return r or ""
end
end
return r or ""
end -- p.int
end -- p.int


p.isLang = function(frame)

-- Could this be an ISO language code?

-- 1 -- code
p.isLang = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Could this be an ISO language code?
local lucky, r = pcall(Multilingual.isLang, s)
-- 1 -- code
return r and "1" or ""
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLang, s )
return r and "1" or ""
end -- p.isLang
end -- p.isLang


p.isLangWiki = function(frame)

-- Could this be a Wiki language version?

-- 1 -- code
p.isLangWiki = function ( frame )
-- Could this be a Wiki language version?
-- Returns non-empty, if possibly language version
local s = mw.text.trim(frame.args[1] or "")
-- 1 -- code
local lucky, r = pcall(Multilingual.isLangWiki, s)
-- Returns non-empty, if possibly language version
return r and "1" or ""
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLangWiki, s )
return r and "1" or ""
end -- p.isLangWiki
end -- p.isLangWiki


p.isRTL = function(frame)

-- Check whether language is written right-to-left

-- 1 -- string, with language code
p.isRTL = function ( frame )
-- Check whether language is written right-to-left
-- Returns non-empty, if right-to-left
local s = mw.text.trim(frame.args[1] or "")
-- 1 -- string, with language code
return Multilingual.isRTL(s) and "1" or ""
-- Returns non-empty, if right-to-left
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.isRTL( s ) and "1" or ""
end -- p.isRTL()
end -- p.isRTL()


p.message = function(frame)

-- Translation of text element

p.message = function ( frame )
return Multilingual.message(fold(frame), frame)
-- Translation of text element
return Multilingual.message( fold( frame ), frame )
end -- p.message
end -- p.message


p.sitelink = function(frame)

-- Make link at local or other site with optimal linktext translation

-- 1 -- item ID
p.sitelink = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Make link at local or other site with optimal linktext translation
local r
-- 1 -- item ID
if s:match("^%d+$") then
local s = mw.text.trim( frame.args[ 1 ] or "" )
r = tonumber(s)
local r
if s:match( "^%d+$") then
elseif s:match("^Q%d+$") then
r = s
r = tonumber( s )
end
elseif s:match( "^Q%d+$") then
r = s
if r then
r = Multilingual.sitelink(r, frame)
end
end
if r then
return r or s
r = Multilingual.sitelink( r, frame )
end
return r or s
end -- p.sitelink
end -- p.sitelink


p.tabData = function(frame)

-- Retrieve best message text from Commons Data

-- 1 -- page identification on Commons
p.tabData = function ( frame )
-- 2 -- keyword
-- Retrieve best message text from Commons Data
-- alt -- fallback text
-- 1 -- page identification on Commons
local suite = frame.args[1]
-- 2 -- keyword
local seek = frame.args[2]
-- alt -- fallback text
local suite = frame.args[ 1 ]
local salt = frame.args.alt
local seek = frame.args[ 2 ]
local r = Multilingual.tabData(suite, seek, salt, frame)
return r
local salt = frame.args.alt
local r = Multilingual.tabData( suite, seek, salt, frame )
return r
end -- p.tabData
end -- p.tabData


p.userLang = function(frame)

-- Which language does the current user prefer?

-- 1 -- space separated list of available ISO 639 codes
p.userLang = function ( frame )
local s = mw.text.trim(frame.args[1] or "")
-- Which language does the current user prefer?
return Multilingual.userLang(s, frame)
-- 1 -- space separated list of available ISO 639 codes
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.userLang( s, frame )
end -- p.userLang
end -- p.userLang


p.wikibase = function(frame)

-- Optimal translation of wikibase component

-- 1 -- object ID
p.wikibase = function ( frame )
-- 2 -- 1 for "descriptions", 0 for "labels".
-- Optimal translation of wikibase component
-- or either "descriptions" or "labels"
-- 1 -- object ID
local r
-- 2 -- 1 for "descriptions", 0 for "labels".
local s = mw.text.trim(frame.args[1] or "")
-- or either "descriptions" or "labels"
local r
if s ~= "" then
local s = mw.text.trim( frame.args[ 1 ] or "" )
local s2 = mw.text.trim(frame.args[2] or "0")
local slang = mw.text.trim(frame.args.lang or "")
if s ~= "" then
local s2 = mw.text.trim( frame.args[ 2 ] or "0" )
local large = (s2 ~= "" and s2 ~= "0")
if slang == "" then
local slang = mw.text.trim( frame.args.lang or "" )
slang = false
local large = ( s2 ~= "" and s2 ~= "0" )
end
if slang == "" then
r = Multilingual.wikibase(s, large, slang, frame)
slang = false
end
end
return r or ""
r = Multilingual.wikibase( s, large, slang, frame )
end
return r or ""
end -- p.wikibase
end -- p.wikibase


p.failsafe = function(frame)

-- Versioning interface

p.failsafe = function ( frame )
local s = type(frame)
local since
-- Versioning interface
if s == "table" then
local s = type( frame )
since = frame.args[1]
local since
if s == "table" then
elseif s == "string" then
since = frame.args[ 1 ]
since = frame
end
elseif s == "string" then
since = frame
if since then
since = mw.text.trim(since)
end
if since then
if since == "" then
since = mw.text.trim( since )
since = false
end
if since == "" then
end
since = false
return Failsafe.failsafe(since) or ""
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
end -- p.failsafe()


p.Multilingual = function()

return Multilingual

p.Multilingual = function ()
return Multilingual
end -- p.Multilingual
end -- p.Multilingual