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

(Difference between pages)
Page 1
Page 2
imported>Sdrqaz
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))
 
imported>Lemondoge
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
local foreignModule = function ( access, advanced, append, alt, alert )
-- Precondition:
    -- Fetch global module
-- access -- string, with name of base module
    -- Precondition:
-- advanced  -- true, for require(); else mw.loadData()
    --     access   -- string, with name of base module
-- append -- string, with subpage part, if any; or false
    --     advanced  -- true, for require(); else mw.loadData()
-- alt   -- number, of wikidata item of root; or false
    --     append   -- string, with subpage part, if any; or false
-- alert -- true, for throwing error on data problem
    --     alt       -- number, of wikidata item of root; or false
-- Postcondition:
    --     alert     -- true, for throwing error on data problem
-- Returns whatever, probably table
    -- Postcondition:
-- 2020-01-01
    --     Returns whatever, probably table
local storage = access
    -- 2020-01-01
local finer = function()
    local storage = access
if append then
    local finer = function ()
storage = string.format("%s/%s", storage, append)
                      if append then
end
                          storage = string.format( "%s/%s",
end
                                                  storage,
local fun, lucky, r, suited
                                                  append )
if advanced then
                      end
fun = require
                  end
else
    local fun, lucky, r, suited
fun = mw.loadData
    if advanced then
end
        fun = require
GlobalMod.globalModules = GlobalMod.globalModules or {}
    else
suited = GlobalMod.globalModules[access]
        fun = mw.loadData
if not suited then
    end
finer()
    GlobalMod.globalModules = GlobalMod.globalModules or { }
lucky, r = pcall(fun,  "Module:" .. storage)
    suited = GlobalMod.globalModules[ access ]
end
    if not suited then
if not lucky then
        finer()
if not suited and
        lucky, r = pcall( fun,  "Module:" .. storage )
  type(alt) == "number" and
    end
  alt > 0 then
    if not lucky then
suited = string.format("Q%d", alt)
        if not suited and
suited = mw.wikibase.getSitelink(suited)
          type( alt ) == "number" and
GlobalMod.globalModules[access] = suited or true
          alt > 0 then
end
            suited = string.format( "Q%d", alt )
if type(suited) == "string" then
            suited = mw.wikibase.getSitelink( suited )
storage = suited
            GlobalMod.globalModules[ access ] = suited or true
finer()
        end
lucky, r = pcall(fun, storage)
        if type( suited ) == "string" then
end
            storage = suited
if not lucky and alert then
            finer()
error("Missing or invalid page: " .. storage)
            lucky, r = pcall( fun, storage )
end
        end
end
        if not lucky and alert then
return r
            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
local fetchData = function ( access )
-- Precondition:
    -- Retrieve translated keyword from commons:Data:****.tab
-- access  -- string, with page identification on Commons
    -- Precondition:
-- Returns table, with data, or string, with error message
    --     access  -- string, with page identification on Commons
-- 2019-12-05
    --     Returns table, with data, or string, with error message
local storage = access
    -- 2019-12-05
local r
    local storage = access
if type(storage) == "string" then
    local r
local s
    if type( storage ) == "string" then
storage = mw.text.trim(storage)
        local s
s = storage:lower()
        storage = mw.text.trim( storage )
if s:sub(1, 2) == "c:" then
        s = storage:lower()
storage = mw.text.trim(storage:sub(3))
        if s:sub( 1, 2 ) == "c:" then
s = storage:lower()
            storage = mw.text.trim( storage:sub( 3 ) )
elseif s:sub(1, 8) == "commons:" then
            s       = storage:lower()
storage = mw.text.trim(storage:sub(9))
        elseif s:sub( 1, 8 ) == "commons:" then
s = storage:lower()
            storage = mw.text.trim( storage:sub( 9 ) )
end
            s       = storage:lower()
if s:sub(1, 5) == "data:" then
        end
storage = mw.text.trim(storage:sub(6))
        if s:sub( 1, 5 ) == "data:" then
s = storage:lower()
            storage = mw.text.trim( storage:sub( 6 ) )
end
            s       = storage:lower()
if s == "" or s == ".tab" then
        end
storage = false
        if s == "" or s == ".tab" then
elseif s:sub(-4) == ".tab" then
            storage = false
storage = storage:sub(1, -5) .. ".tab"
        elseif s:sub( -4 ) == ".tab" then
else
            storage = storage:sub( 1, -5 ) .. ".tab"
storage = storage .. ".tab"
        else
end
            storage = storage .. ".tab"
end
        end
if type(storage) == "string" then
    end
local data
    if type( storage ) == "string" then
if type(GlobalData.TabDATA) ~= "table" then
        local data
GlobalData.TabDATA = {}
        if type( GlobalData.TabDATA ) ~= "table" then
end
            GlobalData.TabDATA = { }
data = GlobalData.TabDATA[storage]
        end
if data then
        data = GlobalData.TabDATA[ storage ]
r = data
        if data then
else
            r = data
local lucky
        else
lucky, data = pcall(mw.ext.data.get, storage, "_")
            local lucky
if type(data) == "table" then
            lucky, data = pcall( mw.ext.data.get, storage, "_" )
data = data.data
            if type( data ) == "table" then
if type(data) == "table" then
                data = data.data
GlobalData.TabDATA[storage] = data
                if type( data ) == "table" then
else
                    GlobalData.TabDATA[ storage ] = data
r = string.format("%s [[%s%s]]",
                else
  "INVALID Data:*.tab",
                    r = string.format( "%s [[%s%s]]",
  "commons:Data:",
                                      "INVALID Data:*.tab",
  storage)
                                      "commons:Data:",
end
                                      storage )
else
                end
r = "BAD PAGE Data:*.tab – commons:" .. storage
            else
end
                r = "BAD PAGE Data:*.tab – commons:" .. storage
if r then
            end
GlobalData.TabDATA[storage] = r
            if r then
data = false
                GlobalData.TabDATA[ storage ] = r
else
                data = false
r = data
            else
end
                r = data
end
            end
else
        end
r = "BAD PAGE commons:Data:*.tab"
    else
end
        r = "BAD PAGE commons:Data:*.tab"
return r
    end
    return r
end -- fetchData()
end -- fetchData()


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


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


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


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


 
local fill = function(access, alien, frame)
 
-- Expand language name template
local fill = function ( access, alien, frame )
-- Precondition:
    -- Expand language name template
-- access  -- string, with language code
    -- Precondition:
-- alien  -- language code for which to be generated
    --     access  -- string, with language code
-- frame  -- frame, if available
    --     alien  -- language code for which to be generated
-- Postcondition:
    --     frame  -- frame, if available
-- Returns string
    -- Postcondition:
local template = Multilingual.tmplLang
    --     Returns string
if type(template) ~= "table" then
    local template = Multilingual.tmplLang
local cnf = fetch("Multilingual", "config")
    local r
if cnf then
    if type( template ) ~= "table" then
template = cnf.tmplLang
        local cnf = fetch( "Multilingual", "config" )
end
        if cnf then
end
            template = cnf.tmplLang
if type(template) == "table" then
        end
local source = template.title
    end
local f, lucky, s
    if type( template ) == "table" then
Multilingual.tmplLang = template
        local source = template.title
if type(source) ~= "string" and
        local f, lucky, s
  type(template.namePat) == "string" and
        Multilingual.tmplLang = template
  template.namePat:find("%s", 1, true) then
        if type( source ) ~= "string" and
source = string.format(template.namePat, access)
          type( template.namePat ) == "string" and
end
          template.namePat:find( "%s", 1, true ) then
if type(source) == "string" then
            source = string.format( template.namePat, access )
if not Multilingual.frame then
        end
Multilingual.frame = frame or mw.getCurrentFrame()
        if type( source ) == "string" then
end
            if not Multilingual.frame then
f = function(a)
                if frame then
return Multilingual.frame:expandTemplate{ title = a }
                    Multilingual.frame = frame
end
                else
lucky, s = pcall(f, source)
                    Multilingual.frame = mw.getCurrentFrame()
if lucky then
                end
return s
            end
end
            f = function ( a )
end
                    return Multilingual.frame:expandTemplate{ title = a }
end
                end
return nil
            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
local find = function ( ask, alien )
-- Precondition:
    -- Derive language code from name
-- ask -- language name, downcased
    -- Precondition:
-- alien  -- language code of ask
    --     ask   -- language name, downcased
-- Postcondition:
    --     alien  -- language code of ask
-- nil, or string
    -- Postcondition:
local codes = mw.language.fetchLanguageNames(alien, "all")
    --     nil, or string
local r
    local codes = mw.language.fetchLanguageNames( alien, "all" )
for k, v in pairs(codes) do
    local r
if mw.ustring.lower(v) == ask then
    for k, v in pairs( codes ) do
r = k
        if mw.ustring.lower( v ) == ask then
break -- for k, v
            r = k
end
            break -- for k, v
end -- for k, v
        end
if not r then
    end -- for k, v
r = Multilingual.fair(ask)
    if not r then
end
        r = Multilingual.fair( ask )
return r
    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
User.favorize = function ( accept, frame )
-- Precondition:
    -- Guess user language
-- accept  -- sequence table, with offered ISO 639 etc. codes
    -- Precondition:
-- frame  -- frame, if available
    --     accept  -- sequence table, with offered ISO 639 etc. codes
-- Postcondition:
    --     frame  -- frame, if available
-- Returns string with best code, or nil
    -- Postcondition:
if not (User.self or User.langs) then
    --     Returns string with best code, or nil
if not User.trials then
    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.tell = mw.message.new( User.sniffer )
User.trials = {}
            if User.tell:exists() then
if not Multilingual.frame then
                User.trials = { }
if frame then
                if not Multilingual.frame then
Multilingual.frame = frame
                    if frame then
else
                        Multilingual.frame = frame
Multilingual.frame = mw.getCurrentFrame()
                    else
end
                        Multilingual.frame = mw.getCurrentFrame()
end
                    end
User.sin = Multilingual.frame:callParserFunction("int",
                end
  User.sniffer)
                User.sin = Multilingual.frame:callParserFunction( "int",
else
                                                          User.sniffer )
User.langs = true
            else
end
                User.langs = true
end
            end
if User.sin then
        end
local order  = {}
        if User.sin then
local post  = {}
            local order  = { }
local three  = {}
            local post  = { }
local unfold = {}
            local three  = { }
local s, sin
            local unfold = { }
for i = 1, #accept do
            local s, sin
s = accept[i]
            for i = 1, #accept do
if not User.trials[s] then
                s = accept[ i ]
if #s > 2 then
                if not User.trials[ s ] then
if s:find("-", 3, true) then
                    if #s > 2 then
table.insert(unfold, s)
                        if s:find( "-", 3, true ) then
else
                            table.insert( unfold, s )
table.insert(three, s)
                        else
end
                            table.insert( three, s )
elseif Multilingual.prefer[s] then
                        end
table.insert(order, s)
                    else
else
                        if Multilingual.prefer[ s ] then
table.insert(post, s)
                            table.insert( order, s )
end
                        else
end
                            table.insert( post, s )
end -- for i
                        end
for i = 1, #post do
                    end
table.insert(order, post[i])
                end
end -- for i
            end -- for i
for i = 1, #three do
            for i = 1, #post do
table.insert(order, three[i])
                table.insert( order, post[ i ] )
end -- for i
            end -- for i
for i = 1, #unfold do
            for i = 1, #three do
table.insert(order, unfold[i])
                table.insert( order, three[ i ] )
end -- for i
            end -- for i
for i = 1, #order do
            for i = 1, #unfold do
s = order[i]
                table.insert( order, unfold[ i ] )
sin = User.tell:inLanguage(s):plain()
            end -- for i
if sin == User.sin then
            for i = 1, #order do
User.self = s
                s = order[ i ]
break -- for i
                sin = User.tell:inLanguage( s ):plain()
else
                if sin == User.sin then
User.trials[s] = true
                    User.self = s
end
                    break -- for i
end -- for i
                else
end
                    User.trials[ s ] = true
end
                end
return User.self
            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.
Multilingual.fair = function ( ask )
-- Precondition:
    -- Format language specification according to RFC 5646 etc.
-- ask  -- string or table, as created by .getLang()
    -- Precondition:
-- Postcondition:
    --     ask  -- string or table, as created by .getLang()
-- Returns string, or false
    -- Postcondition:
local s = type(ask)
    --     Returns string, or false
local q, r
    local s = type( ask )
if s == "table" then
    local q, r
q = ask
    if s == "table" then
elseif s == "string" then
        q = ask
q = Multilingual.getLang(ask)
    elseif s == "string" then
end
        q = Multilingual.getLang( ask )
if q and
    end
  q.legal and
    if q and
  mw.language.isKnownLanguageTag(q.base) then
      q.legal and
r = q.base
      mw.language.isKnownLanguageTag( q.base ) then
if q.n > 1 then
        r = q.base
local order = { "extlang",
        if q.n > 1 then
"script",
            local order = { "extlang",
"region",
                            "script",
"other",
                            "region",
"extension" }
                            "other",
for i = 1, #order do
                            "extension" }
s = q[order[i]]
            for i = 1, #order do
if s then
                s = q[ order[ i ] ]
r = string.format("%s-%s", r, s)
                if s then
end
                    r = string.format( "%s-%s", r, s )
end -- for i
                end
end
            end -- for i
end
        end
return r or false
    end
    return r or false
end -- Multilingual.fair()
end -- Multilingual.fair()


 
Multilingual.fallback = function(able, another)
 
-- Is another language suitable as replacement?
Multilingual.fallback = function ( able, another )
-- Precondition:
    -- Is another language suitable as replacement?
-- able -- language version specifier to be supported
    -- Precondition:
-- another  -- language specifier of a possible replacement,
    --     able     -- language version specifier to be supported
-- or not to retrieve a fallback table
    --     another  -- language specifier of a possible replacement,
-- Postcondition:
    --                 or not to retrieve a fallback table
-- Returns boolean, or table with fallback codes
    -- Postcondition:
local r
    --     Returns boolean, or table with fallback codes
if type(able) == "string" and #able > 0 then
    local r
if type(another) == "string" and #another > 0 then
    if type( able ) == "string" and #able > 0 then
if able == another then
        if type( another ) == "string" and #another > 0 then
r = true
            if able == another then
else
                r = true
local s = Multilingual.getBase(able)
            else
if s == another then
                local s = Multilingual.getBase( able )
r = true
                if s == another then
else
                    r = true
local others = mw.language.getFallbacksFor(s)
                else
r = feasible(another, others)
                    local others = mw.language.getFallbacksFor( s )
end
                    r = feasible( another, others )
end
                end
else
            end
local s = Multilingual.getBase(able)
        else
if s then
            local s = Multilingual.getBase( able )
r = mw.language.getFallbacksFor(s)
            if s then
if r[1] == "en" then
                r = mw.language.getFallbacksFor( s )
local d = fetchISO639("fallback")
                if r[ 1 ] == "en" then
if type(d) == "table" and
                    local d = fetchISO639( "fallback" )
  type(d[s]) == "string" then
                    if type( d ) == "table" and
r = mw.text.split(d[s], "|")
                      type( d[ s ] ) == "string" then
table.insert(r, "en")
                        r = mw.text.split( d[ s ], "|" )
end
                        table.insert( r, "en" )
end
                    end
end
                end
end
            end
end
        end
return r or false
    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
Multilingual.findCode = function ( ask )
-- Precondition:
    -- Retrieve code of local (current project or English) language name
-- ask  -- string, with presumable language name
    -- Precondition:
-- A code itself will be identified, too.
    --     ask  -- string, with presumable language name
-- Postcondition:
    --             A code itself will be identified, too.
-- Returns string, or false
    -- Postcondition:
local seek = mw.text.trim(ask)
    --     Returns string, or false
local r = false
    local seek = mw.text.trim( ask )
if #seek > 1 then
    local r = false
if seek:find("[", 1, true) then
    if #seek > 1 then
local wlink = fetch("WLink")
        if seek:find( "[", 1, true ) then
if wlink and
            local wlink = fetch( "WLink" )
  type(wlink.getPlain) == "function" then
            if wlink and
seek = wlink.getPlain(seek)
              type( wlink.getPlain ) == "function" then
end
                seek = wlink.getPlain( seek )
end
            end
seek = mw.ustring.lower(seek)
        end
if Multilingual.isLang(seek) then
        seek = mw.ustring.lower( seek )
r = Multilingual.fair(seek)
        if Multilingual.isLang( seek ) then
else
            r = Multilingual.fair( seek )
local collection = favorites()
        else
for i = 1, #collection do
            local collection = favorites()
r = find(seek, collection[i])
            for i = 1, #collection do
if r then
                r = find( seek, collection[ i ] )
break -- for i
                if r then
end
                    break -- for i
end -- for i
                end
end
            end -- for i
end
        end
return r
    end
    return r
end -- Multilingual.findCode()
end -- Multilingual.findCode()


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


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


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


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


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


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


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


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


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


 
Multilingual.isRTL = function(ask)
 
-- Check whether language is written right-to-left
Multilingual.isRTL = function ( ask )
-- Precondition:
    -- Check whether language is written right-to-left
-- ask  -- string, with language (or script) code
    -- Precondition:
-- Returns true, if right-to-left
    --     ask  -- string, with language (or script) code
local r
    -- Returns true, if right-to-left
Multilingual.rtl = Multilingual.rtl or {}
    local r
r = Multilingual.rtl[ask]
    Multilingual.rtl = Multilingual.rtl or { }
if type(r) ~= "boolean" then
    r = Multilingual.rtl[ ask ]
local bib = fetch("ISO15924")
    if type( r ) ~= "boolean" then
if type(bib) == "table" and
        local bib = fetch( "ISO15924" )
  type(bib.isRTL) == "function" then
        if type( bib ) == "table" and
r = bib.isRTL(ask)
          type( bib.isRTL ) == "function" then
else
            r = bib.isRTL( ask )
r = mw.language.new(ask):isRTL()
        else
end
            r = mw.language.new( ask ):isRTL()
Multilingual.rtl[ask] = r
        end
end
        Multilingual.rtl[ ask ] = r
return 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
Multilingual.message = function ( arglist, frame )
-- Precondition:
    -- Show text in best match of user language like system message
-- arglist  -- template arguments
    -- Precondition:
-- frame -- frame, if available
    --     arglist  -- template arguments
-- Postcondition:
    --     frame   -- frame, if available
-- Returns string with appropriate text
    -- Postcondition:
local r
    --     Returns string with appropriate text
if type(arglist) == "table" then
    local r
local t = {}
    if type( arglist ) == "table" then
local m, p, save
        local t = { }
for k, v in pairs(arglist) do
        local m, p, save
if type(k) == "string" and
        for k, v in pairs( arglist ) do
  type(v) == "string" then
            if type( k ) == "string" and
v = mw.text.trim(v)
              type( v ) == "string" then
if v ~= "" then
                v = mw.text.trim( v )
if k:match("^%l%l") then
                if v ~= "" then
t[k] = v
                    if k:match( "^%l%l" ) then
elseif k:match("^%$%d$") and k ~= "$0" then
                        t[ k ] = v
p = p or {}
                    elseif k:match( "^%$%d$" ) and k ~= "$0" then
k = tonumber(k:match("^%$(%d)$"))
                        p = p or { }
p[k] = v
                        k = tonumber( k:match( "^%$(%d)$" ) )
if not m or k > m then
                        p[ k ] = v
m = k
                        if not m or k > m then
end
                            m = k
end
                        end
end
                    end
end
                end
end -- for k, v
            end
if type(arglist["-"]) == "string" then
        end -- for k, v
save = arglist[arglist["-"]]
        if type( arglist[ "-" ] ) == "string" then
end
            save = arglist[ arglist[ "-" ] ]
r = Multilingual.i18n(t, save, frame)
        end
if p and r and r:find("$", 1, true) then
        r = Multilingual.i18n( t, save, frame )
t = {}
        if p and r and r:find( "$", 1, true ) then
for i = 1, m do
            t = { }
t[i] = p[i] or ""
            for i = 1, m do
end -- for i
                t[ i ] = p[ i ] or ""
r = mw.message.newRawMessage(r, t):plain()
            end -- for i
end
            r = mw.message.newRawMessage( r, t ):plain()
end
        end
return r or ""
    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
Multilingual.sitelink = function ( all, frame )
-- Precondition:
    -- Make link at local or other site with optimal linktext translation
-- all -- string or table or number, item ID or entity
    -- Precondition:
-- frame  -- frame, if available
    --     all   -- string or table or number, item ID or entity
-- Postcondition:
    --     frame  -- frame, if available
-- Returns string with any helpful internal link, or plain text
    -- Postcondition:
local s = type(all)
    --     Returns string with any helpful internal link, or plain text
local object, r
    local s = type( all )
if s == "table" then
    local object, r
object = all
    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))
    elseif s == "number" then
end
        object = mw.wikibase.getEntity( string.format( "Q%d", all ) )
if type(object) == "table" then
    end
local collection = object.sitelinks
    if type( object ) == "table" then
local entry
        local collection = object.sitelinks
s = false
        local entry
if type(collection) == "table" then
        s = false
Multilingual.site = Multilingual.site or
        if type( collection ) == "table" then
mw.wikibase.getGlobalSiteId()
            Multilingual.site = Multilingual.site or
entry = collection[Multilingual.site]
                                mw.wikibase.getGlobalSiteId()
if entry then
            entry = collection[ Multilingual.site ]
s = ":" .. entry.title
            if entry then
elseif collection.enwiki then
                s = ":" .. entry.title
s = "w:en:" .. collection.enwiki.title
            elseif collection.enwiki then
end
                s = "w:en:" .. collection.enwiki.title
end
            end
r = Multilingual.wikibase(object, "labels", frame)
        end
if s then
        r = Multilingual.wikibase( object, "labels", frame )
if s == ":" .. r then
        if s then
r = string.format("[[%s]]", s)
            if s == ":" .. r then
else
                r = string.format( "[[%s]]", s )
r = string.format("[[%s|%s]]", s, r)
            else
end
                r = string.format( "[[%s|%s]]", s, r )
end
            end
end
        end
return r or ""
    end
    return r or ""
end -- Multilingual.sitelink()
end -- Multilingual.sitelink()


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


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


 
Multilingual.userLangCode = function()
 
-- Guess a user language code
Multilingual.userLangCode = function ()
-- Postcondition:
    -- Guess a user language code
-- Returns code of current best guess
    -- Postcondition:
return User.self or favorites()[1]
    --     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
Multilingual.wikibase = function ( all, about, attempt, frame )
-- Precondition:
    -- Optimal translation of wikibase component
-- all   -- string or table, object ID or entity
    -- Precondition:
-- about -- boolean, true "descriptions" or false "labels"
    --     all     -- string or table, object ID or entity
-- attempt  -- string or not, code of preferred language
    --     about   -- boolean, true "descriptions" or false "labels"
-- frame -- frame, if available
    --     attempt  -- string or not, code of preferred language
-- Postcondition:
    --     frame   -- frame, if available
-- Returns
    -- Postcondition:
-- 1. string, with selected message
    --     Returns
-- 2. string, with language code, or not
    --         1. string, with selected message
local s = type(all)
    --         2. string, with language code, or not
local object, r, r2
    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)
    elseif s == "string" then
end
        object = mw.wikibase.getEntity( all )
if type(object) == "table" then
    end
if about and about ~= "labels" then
    if type( object ) == "table" then
s = "descriptions"
        if about and about ~= "labels" then
else
            s = "descriptions"
s = "labels"
        else
end
            s = "labels"
object = object[s]
        end
if type(object) == "table" then
        object = object[ s ]
if object[attempt] then
        if type( object ) == "table" then
r  = object[attempt].value
            if object[ attempt ] then
r2 = attempt
                r  = object[ attempt ].value
else
                r2 = attempt
local poly
            else
for k, v in pairs(object) do
                local poly
poly = poly or {}
                for k, v in pairs( object ) do
poly[k] = v.value
                    poly = poly or { }
end -- for k, v
                    poly[ k ] = v.value
if poly then
                end -- for k, v
r, r2 = Multilingual.i18n(poly, nil, frame)
                if poly then
end
                    r, r2 = Multilingual.i18n( poly, nil, frame )
end
                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
Failsafe.failsafe = function ( atleast )
-- Precondition:
    -- Retrieve versioning and check for compliance
-- atleast  -- string, with required version
    -- Precondition:
-- or wikidata|item|~|@ or false
    --     atleast  -- string, with required version
-- Postcondition:
    --                         or wikidata|item|~|@ or false
-- Returns  string  -- with queried version/item, also if problem
    -- Postcondition:
--   false  -- if appropriate
    --     Returns  string  -- with queried version/item, also if problem
-- 2020-08-17
    --             false  -- if appropriate
local since = atleast
    -- 2020-08-17
local last = (since == "~")
    local since = atleast
local linked  = (since == "@")
    local last   = ( since == "~" )
local link = (since == "item")
    local linked  = ( since == "@" )
local r
    local link   = ( since == "item" )
if last or link or linked or since == "wikidata" then
    local r
local item = Failsafe.item
    if last or link or linked or since == "wikidata" then
since = false
        local item = Failsafe.item
if type(item) == "number" and item > 0 then
        since = false
local suited = string.format("Q%d", item)
        if type( item ) == "number" and item > 0 then
if link then
            local suited = string.format( "Q%d", item )
r = suited
            if link then
else
                r = suited
local entity = mw.wikibase.getEntity(suited)
            else
if type(entity) == "table" then
                local entity = mw.wikibase.getEntity( suited )
local seek = Failsafe.serialProperty or "P348"
                if type( entity ) == "table" then
local vsn  = entity:formatPropertyValues(seek)
                    local seek = Failsafe.serialProperty or "P348"
if type(vsn) == "table" and
                    local vsn  = entity:formatPropertyValues( seek )
  type(vsn.value) == "string" and
                    if type( vsn ) == "table" and
  vsn.value ~= "" then
                      type( vsn.value ) == "string" and
if last and vsn.value == Failsafe.serial then
                      vsn.value ~= "" then
r = false
                        if last and vsn.value == Failsafe.serial then
elseif linked then
                            r = false
if mw.title.getCurrentTitle().prefixedText
                        elseif linked then
  ==  mw.wikibase.getSitelink(suited) then
                            if mw.title.getCurrentTitle().prefixedText
r = false
                              ==  mw.wikibase.getSitelink( suited ) then
else
                                r = false
r = suited
                            else
end
                                r = suited
else
                            end
r = vsn.value
                        else
end
                            r = vsn.value
end
                        end
end
                    end
end
                end
end
            end
end
        end
if type(r) == "nil" then
    end
if not since or since <= Failsafe.serial then
    if type( r ) == "nil" then
r = Failsafe.serial
        if not since or since <= Failsafe.serial then
else
            r = Failsafe.serial
r = false
        else
end
            r = false
end
        end
return r
    end
    return r
end -- Failsafe.failsafe()
end -- Failsafe.failsafe()


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


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


 
p.findCode = function(frame)
 
-- Retrieve language code from language name
p.findCode = function ( frame )
-- 1  -- name in current project language
    -- Retrieve language code from language name
local s = mw.text.trim(frame.args[1] or "")
    --     1  -- name in current project language
return Multilingual.findCode(s) or ""
    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]
p.fix = function ( frame )
if r then
    local r = frame.args[ 1 ]
r = Multilingual.fix(mw.text.trim(r))
    if r then
end
        r = Multilingual.fix( mw.text.trim( r ) )
return r or ""
    end
    return r or ""
end -- p.fix
end -- p.fix


 
p.format = function(frame)
 
-- Format one or more languages
p.format = function ( frame )
-- 1   -- language list or item
    -- Format one or more languages
-- slang   -- language of the answer, if not native
    --     1         -- language list or item
--   * -- native
    --     slang     -- language of the answer, if not native
--   ! -- current project
    --                   * -- native
--   any valid code
    --                   ! -- current project
-- shift   -- capitalize, if "c"; downcase, if "d"
    --                   any valid code
--   capitalize first item only, if "f"
    --     shift     -- capitalize, if "c"; downcase, if "d"
-- link   -- 1 -- link items
    --                   capitalize first item only, if "f"
-- scream -- category title in case of error
    --     link       -- 1 -- link items
-- split   -- split pattern, if list expected
    --     scream     -- category title in case of error
-- separator -- list separator, else split
    --     split     -- split pattern, if list expected
-- start   -- prepend first element, if any
    --     separator -- list separator, else split
local r
    --     start     -- prepend first element, if any
local link
    local r
if frame.args.link == "1" then
    local link
link = true
    if frame.args.link == "1" then
end
        link = true
r = Multilingual.format(frame.args[1],
    end
frame.args.slang,
    r = Multilingual.format( frame.args[ 1 ],
frame.args.shift,
                            frame.args.slang,
link,
                            frame.args.shift,
frame.args.scream,
                            link,
frame,
                            frame.args.scream,
frame.args.split,
                            frame,
frame.args.separator,
                            frame.args.split,
frame.args.start)
                            frame.args.separator,
return r or ""
                            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
p.getBase = function ( frame )
-- 1  -- code
    -- Retrieve base language from possibly combined ISO language code
local s = mw.text.trim(frame.args[1] or "")
    --     1  -- code
return Multilingual.getBase(s) or ""
    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
p.getName = function ( frame )
-- 1  -- code
    -- 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
    --           ! -- current project
--   any valid code
    --           * -- native
local s = mw.text.trim(frame.args[1] or "")
    --           any valid code
local slang = frame.args[2]
    local s     = mw.text.trim( frame.args[ 1 ] or "" )
local r
    local slang = frame.args[ 2 ]
Multilingual.frame = frame
    local r
if slang then
    Multilingual.frame = frame
slang = mw.text.trim(slang)
    if slang then
end
        slang = mw.text.trim( slang )
r = Multilingual.getName(s, slang)
    end
return r or ""
    r = Multilingual.getName( s, slang )
    return r or ""
end -- p.getName
end -- p.getName


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


 
p.isLang = function(frame)
 
-- Could this be an ISO language code?
p.isLang = function ( frame )
-- 1  -- code
    -- Could this be an ISO language code?
local s = mw.text.trim(frame.args[1] or "")
    --     1  -- code
local lucky, r = pcall(Multilingual.isLang, s)
    local s = mw.text.trim( frame.args[ 1 ] or "" )
return r and "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?
p.isLangWiki = function ( frame )
-- 1  -- code
    -- Could this be a Wiki language version?
-- Returns non-empty, if possibly language version
    --     1  -- code
local s = mw.text.trim(frame.args[1] or "")
    -- Returns non-empty, if possibly language version
local lucky, r = pcall(Multilingual.isLangWiki, s)
    local s = mw.text.trim( frame.args[ 1 ] or "" )
return r and "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
p.isRTL = function ( frame )
-- 1  -- string, with language code
    -- Check whether language is written right-to-left
-- Returns non-empty, if right-to-left
    --     1  -- string, with language code
local s = mw.text.trim(frame.args[1] or "")
    -- Returns non-empty, if right-to-left
return Multilingual.isRTL(s) and "1" or ""
    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
p.sitelink = function ( frame )
-- 1  -- item ID
    -- Make link at local or other site with optimal linktext translation
local s = mw.text.trim(frame.args[1] or "")
    --     1  -- item ID
local r
    local s = mw.text.trim( frame.args[ 1 ] or "" )
if s:match("^%d+$") then
    local r
r = tonumber(s)
    if s:match( "^%d+$") then
elseif s:match("^Q%d+$") then
        r = tonumber( s )
r = s
    elseif s:match( "^Q%d+$") then
end
        r = s
if r then
    end
r = Multilingual.sitelink(r, frame)
    if r then
end
        r = Multilingual.sitelink( r, frame )
return r or s
    end
    return r or s
end -- p.sitelink
end -- p.sitelink


 
p.tabData = function(frame)
 
-- Retrieve best message text from Commons Data
p.tabData = function ( frame )
-- 1 -- page identification on Commons
    -- Retrieve best message text from Commons Data
-- 2 -- keyword
    --     1   -- page identification on Commons
-- alt  -- fallback text
    --     2   -- keyword
local suite = frame.args[1]
    --     alt  -- fallback text
local seek  = frame.args[2]
    local suite = frame.args[ 1 ]
local salt  = frame.args.alt
    local seek  = frame.args[ 2 ]
local r = Multilingual.tabData(suite, seek, salt, frame)
    local salt  = frame.args.alt
return r
    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?
p.userLang = function ( frame )
-- 1  -- space separated list of available ISO 639 codes
    -- Which language does the current user prefer?
local s = mw.text.trim(frame.args[1] or "")
    --     1  -- space separated list of available ISO 639 codes
return Multilingual.userLang(s, frame)
    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
p.wikibase = function ( frame )
-- 1  -- object ID
    -- Optimal translation of wikibase component
-- 2  -- 1 for "descriptions", 0 for "labels".
    --     1  -- object ID
--   or either "descriptions" or "labels"
    --     2  -- 1 for "descriptions", 0 for "labels".
local r
    --           or either "descriptions" or "labels"
local s = mw.text.trim(frame.args[1] or "")
    local r
if s ~= "" then
    local s = mw.text.trim( frame.args[ 1 ] or "" )
local s2 = mw.text.trim(frame.args[2] or "0")
    if s ~= "" then
local slang = mw.text.trim(frame.args.lang or "")
        local s2   = mw.text.trim( frame.args[ 2 ] or "0" )
local large = (s2 ~= "" and s2 ~= "0")
        local slang = mw.text.trim( frame.args.lang or "" )
if slang == "" then
        local large = ( s2 ~= "" and s2 ~= "0" )
slang = false
        if slang == "" then
end
            slang = false
r = Multilingual.wikibase(s, large, slang, frame)
        end
end
        r = Multilingual.wikibase( s, large, slang, frame )
return r or ""
    end
    return r or ""
end -- p.wikibase
end -- p.wikibase


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


return p
return p