Difference between pages "Module:Multilingual" and "Card Tips:Mathmech Subtraction"

From Yugipedia
(Difference between pages)
Jump to: navigation, search
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=R...)
 
(Restoring varnish cache from 2022-04-06 12:24:00+00:00)
 
Line 1: Line 1:
local Multilingual = { suite  = "Multilingual",
+
{{Navigation}}
                      serial  = "2020-12-10",
 
                      item    = 47541920,
 
                      globals = { ISO15924 = 71584769,
 
                                  WLink    = 19363224 }
 
                    }
 
--[=[
 
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
 
* fair()
 
* fallback()
 
* findCode()
 
* fix()
 
* format()
 
* getBase()
 
* getLang()
 
* getName()
 
* i18n()
 
* int()
 
* isLang()
 
* isLangWiki()
 
* isMinusculable()
 
* isRTL()
 
* message()
 
* sitelink()
 
* tabData()
 
* userLang()
 
* userLangCode()
 
* wikibase()
 
* failsafe()
 
loadData: Multilingual/config Multilingual/names
 
]=]
 
local Failsafe  = Multilingual
 
local GlobalMod  = Multilingual
 
local GlobalData = Multilingual
 
local User      = { sniffer = "showpreview" }
 
Multilingual.globals.Multilingual = Multilingual.item
 
  
 
+
* This card can be [[Searcher|searched]] by "[[Mathmech Nabla]]", "[[Primathmech Alembertian]]", "[[Geomathmech Final Sigma]]", "[[Cynet Mining]]", "[[Cynet Backdoor]]", "[[Garbage Collector]]", "[[Armored Bitron]]", "[[Cyberse Reminder]]", "[[Micro Coder]]", "[[Code Generator]]", "[[Cynet Codec]]", "[[World Legacy Bestowal]]", "[[Cyberse Magician]]", "[[Cyberse Beacon]]", "[[ROM Cloudia]]", "[[Hiita the Fire Charmer, Ablaze]]", "[[UFO Turtle]]", "[[Summoner Monk]]", "[[Battle Royal Mode - Joining]]", "[[Vampire Dragon]]", "[[Resonator Engine]]", "[[Soul Rope]]", "[[Rescue Ferret]]", "[[Umbramirage the Elemental Lord]]", "[[Sangan]]", "[[Witch of the Black Forest]]", and other [[List of generic searchers#Monsters|generic searchers]].
 
 
Multilingual.exotic = { simple = true,
 
                        no    = true }
 
Multilingual.prefer = { cs = true,
 
                        de = true,
 
                        en = true,
 
                        es = true,
 
                        fr = true,
 
                        it = true,
 
                        nl = true,
 
                        pt = true,
 
                        ru = true,
 
                        sv = true }
 
 
 
 
 
 
 
local foreignModule = function ( access, advanced, append, alt, alert )
 
    -- Fetch global module
 
    -- Precondition:
 
    --    access    -- string, with name of base module
 
    --    advanced  -- true, for require(); else mw.loadData()
 
    --    append    -- string, with subpage part, if any; or false
 
    --    alt      -- number, of wikidata item of root; or false
 
    --    alert    -- true, for throwing error on data problem
 
    -- Postcondition:
 
    --    Returns whatever, probably table
 
    -- 2020-01-01
 
    local storage = access
 
    local finer = function ()
 
                      if append then
 
                          storage = string.format( "%s/%s",
 
                                                  storage,
 
                                                  append )
 
                      end
 
                  end
 
    local fun, lucky, r, suited
 
    if advanced then
 
        fun = require
 
    else
 
        fun = mw.loadData
 
    end
 
    GlobalMod.globalModules = GlobalMod.globalModules or { }
 
    suited = GlobalMod.globalModules[ access ]
 
    if not suited then
 
        finer()
 
        lucky, r = pcall( fun,  "Module:" .. storage )
 
    end
 
    if not lucky then
 
        if not suited  and
 
          type( alt ) == "number"  and
 
          alt > 0 then
 
            suited = string.format( "Q%d", alt )
 
            suited = mw.wikibase.getSitelink( suited )
 
            GlobalMod.globalModules[ access ] = suited or true
 
        end
 
        if type( suited ) == "string" then
 
            storage = suited
 
            finer()
 
            lucky, r = pcall( fun, storage )
 
        end
 
        if not lucky and alert then
 
            error( "Missing or invalid page: " .. storage )
 
        end
 
    end
 
    return r
 
end -- foreignModule()
 
 
 
 
 
 
 
local fetchData = function ( access )
 
    -- Retrieve translated keyword from commons:Data:****.tab
 
    -- Precondition:
 
    --    access  -- string, with page identification on Commons
 
    --    Returns table, with data, or string, with error message
 
    -- 2019-12-05
 
    local storage = access
 
    local r
 
    if type( storage ) == "string" then
 
        local s
 
        storage = mw.text.trim( storage )
 
        s = storage:lower()
 
        if s:sub( 1, 2 ) == "c:" then
 
            storage = mw.text.trim( storage:sub( 3 ) )
 
            s      = storage:lower()
 
        elseif s:sub( 1, 8 ) == "commons:" then
 
            storage = mw.text.trim( storage:sub( 9 ) )
 
            s      = storage:lower()
 
        end
 
        if s:sub( 1, 5 ) == "data:" then
 
            storage = mw.text.trim( storage:sub( 6 ) )
 
            s      = storage:lower()
 
        end
 
        if s == ""  or  s == ".tab" then
 
            storage = false
 
        elseif s:sub( -4 ) == ".tab" then
 
            storage = storage:sub( 1, -5 ) .. ".tab"
 
        else
 
            storage = storage .. ".tab"
 
        end
 
    end
 
    if type( storage ) == "string" then
 
        local data
 
        if type( GlobalData.TabDATA ) ~= "table" then
 
            GlobalData.TabDATA = { }
 
        end
 
        data = GlobalData.TabDATA[ storage ]
 
        if data then
 
            r = data
 
        else
 
            local lucky
 
            lucky, data = pcall( mw.ext.data.get, storage, "_" )
 
            if type( data ) == "table" then
 
                data = data.data
 
                if type( data ) == "table" then
 
                    GlobalData.TabDATA[ storage ] = data
 
                else
 
                    r = string.format( "%s [[%s%s]]",
 
                                      "INVALID Data:*.tab",
 
                                      "commons:Data:",
 
                                      storage )
 
                end
 
            else
 
                r = "BAD PAGE Data:*.tab – commons:" .. storage
 
            end
 
            if r then
 
                GlobalData.TabDATA[ storage ] = r
 
                data = false
 
            else
 
                r = data
 
            end
 
        end
 
    else
 
        r = "BAD PAGE commons:Data:*.tab"
 
    end
 
    return r
 
end -- fetchData()
 
 
 
 
 
 
 
local favorites = function ()
 
    -- Provide fallback codes
 
    -- Postcondition:
 
    --    Returns table with sequence of preferred languages
 
    --    * ahead elements
 
    --    * user (not yet accessible)
 
    --    * page content language (not yet accessible)
 
    --    * page name subpage
 
    --    * project
 
    --    * en
 
    local r = Multilingual.polyglott
 
    if not r then
 
        local self = mw.language.getContentLanguage():getCode():lower()
 
        local sub  = mw.title.getCurrentTitle().subpageText
 
        local f    = function ( add )
 
                        local s = add
 
                        for i = 1, #r do
 
                            if r[ i ] == s then
 
                                s = false
 
                                break -- for i
 
                            end
 
                        end -- for i
 
                        if s then
 
                            table.insert( r, s )
 
                        end
 
                    end
 
        r = { }
 
        if sub:find( "/", 2, true ) then
 
            sub = sub:match( "/(%l%l%l?)$" )
 
            if sub then
 
                table.insert( r, sub )
 
            end
 
        elseif sub:find( "^%l%l%l?%-?%a?%a?%a?%a?$" )  and
 
              mw.language.isSupportedLanguage( sub ) then
 
            table.insert( r, sub )
 
        end
 
        f( self )
 
        f( "en" )
 
        Multilingual.polyglott = r
 
    end
 
    return r
 
end -- favorites()
 
 
 
 
 
 
 
local feasible = function ( ask, accept )
 
    -- Is ask to be supported by application?
 
    -- Precondition:
 
    --    ask    -- lowercase code
 
    --    accept  -- sequence table, with offered lowercase codes
 
    -- Postcondition:
 
    --    nil, or true
 
    local r
 
    for i = 1, #accept do
 
        if accept[ i ] == ask then
 
            r = true
 
            break -- for i
 
        end
 
    end -- for i
 
    return r
 
end -- feasible()
 
 
 
 
 
 
 
local fetch = function ( access, append )
 
    -- Attach config or library module
 
    -- Precondition:
 
    --    access  -- module title
 
    --    append  -- string, with subpage part of this; or false
 
    -- Postcondition:
 
    --    Returns:  table, with library, or false
 
    local got, sign
 
    if append then
 
        sign = string.format( "%s/%s", access, append )
 
    else
 
        sign = access
 
    end
 
    if type( Multilingual.ext ) ~= "table" then
 
        Multilingual.ext = { }
 
    end
 
    got = Multilingual.ext[ sign ]
 
    if not got  and  got ~= false then
 
        local global = Multilingual.globals[ access ]
 
        local lib    = ( not append  or  append == "config" )
 
        got = foreignModule( access, lib, append, global )
 
        if type( got ) == "table" then
 
            if lib then
 
                local startup = got[ access ]
 
                if type( startup ) == "function" then
 
                    got = startup()
 
                end
 
            end
 
        else
 
            got = false
 
        end
 
        Multilingual.ext[ sign ] = got
 
    end
 
    return got
 
end -- fetch()
 
 
 
 
 
 
 
local fetchISO639 = function ( access )
 
    -- Retrieve table from commons:Data:ISO639/***.tab
 
    -- Precondition:
 
    --    access  -- string, with subpage identification
 
    -- Postcondition:
 
    --    Returns table, with data, even empty
 
    local r
 
    if type( Multilingual.iso639 ) ~= "table" then
 
        Multilingual.iso639 = { }
 
    end
 
    r = Multilingual.iso639[ access ]
 
    if type( r ) == "nil" then
 
        local raw = fetchData( "ISO639/" .. access )
 
        if type( raw ) == "table" then
 
            local t
 
            r = { }
 
            for i = 1, #raw do
 
                t = raw[ i ]
 
                if type( t ) == "table"  and
 
                  type( t[ 1 ] ) == "string"  and
 
                  type( t[ 2 ] ) == "string" then
 
                    r[ t[ 1 ] ] =  t[ 2 ]
 
                else
 
                    break -- for i
 
                end
 
            end -- for i
 
        else
 
            r = false
 
        end
 
        Multilingual.iso639[ access ] = r
 
    end
 
    return r or { }
 
end -- fetchISO639()
 
 
 
 
 
 
 
local fill = function ( access, alien, frame )
 
    -- Expand language name template
 
    -- Precondition:
 
    --    access  -- string, with language code
 
    --    alien  -- language code for which to be generated
 
    --    frame  -- frame, if available
 
    -- Postcondition:
 
    --    Returns string
 
    local template = Multilingual.tmplLang
 
    local r
 
    if type( template ) ~= "table" then
 
        local cnf = fetch( "Multilingual", "config" )
 
        if cnf then
 
            template = cnf.tmplLang
 
        end
 
    end
 
    if type( template ) == "table" then
 
        local source = template.title
 
        local f, lucky, s
 
        Multilingual.tmplLang = template
 
        if type( source ) ~= "string"  and
 
          type( template.namePat ) == "string"  and
 
          template.namePat:find( "%s", 1, true ) then
 
            source = string.format( template.namePat, access )
 
        end
 
        if type( source ) == "string" then
 
            if not Multilingual.frame then
 
                if frame then
 
                    Multilingual.frame = frame
 
                else
 
                    Multilingual.frame = mw.getCurrentFrame()
 
                end
 
            end
 
            f = function ( a )
 
                    return Multilingual.frame:expandTemplate{ title = a }
 
                end
 
            lucky, s = pcall( f, source )
 
            if lucky then
 
                r = s
 
            end
 
        end
 
    end
 
    return r
 
end -- fill()
 
 
 
 
 
 
 
local find = function ( ask, alien )
 
    -- Derive language code from name
 
    -- Precondition:
 
    --    ask    -- language name, downcased
 
    --    alien  -- language code of ask
 
    -- Postcondition:
 
    --    nil, or string
 
    local codes = mw.language.fetchLanguageNames( alien, "all" )
 
    local r
 
    for k, v in pairs( codes ) do
 
        if mw.ustring.lower( v ) == ask then
 
            r = k
 
            break -- for k, v
 
        end
 
    end -- for k, v
 
    if not r then
 
        r = Multilingual.fair( ask )
 
    end
 
    return r
 
end -- find()
 
 
 
 
 
 
 
local fold = function ( frame )
 
    -- Merge template and #invoke arglist
 
    -- Precondition:
 
    --    frame  -- template frame
 
    -- Postcondition:
 
    --    table, with combined arglist
 
    local r = { }
 
    local f = function ( apply )
 
                  if type( apply ) == "table"  and
 
                    type( apply.args ) == "table" then
 
                      for k, v in pairs( apply.args ) do
 
                          v = mw.text.trim( v )
 
                          if v ~= "" then
 
                              r[ tostring( k ) ] = v
 
                          end
 
                      end -- for k, v
 
                  end
 
              end -- f()
 
    f( frame:getParent() )
 
    f( frame )
 
    return r
 
end -- fold()
 
 
 
 
 
 
 
User.favorize = function ( accept, frame )
 
    -- Guess user language
 
    -- Precondition:
 
    --    accept  -- sequence table, with offered ISO 639 etc. codes
 
    --    frame  -- frame, if available
 
    -- Postcondition:
 
    --    Returns string with best code, or nil
 
    if not ( User.self or User.langs ) then
 
        if not User.trials then
 
            User.tell = mw.message.new( User.sniffer )
 
            if User.tell:exists() then
 
                User.trials = { }
 
                if not Multilingual.frame then
 
                    if frame then
 
                        Multilingual.frame = frame
 
                    else
 
                        Multilingual.frame = mw.getCurrentFrame()
 
                    end
 
                end
 
                User.sin = Multilingual.frame:callParserFunction( "int",
 
                                                          User.sniffer )
 
            else
 
                User.langs = true
 
            end
 
        end
 
        if User.sin then
 
            local order  = { }
 
            local post  = { }
 
            local three  = { }
 
            local unfold = { }
 
            local s, sin
 
            for i = 1, #accept do
 
                s = accept[ i ]
 
                if not User.trials[ s ] then
 
                    if #s > 2 then
 
                        if s:find( "-", 3, true ) then
 
                            table.insert( unfold, s )
 
                        else
 
                            table.insert( three, s )
 
                        end
 
                    else
 
                        if Multilingual.prefer[ s ] then
 
                            table.insert( order, s )
 
                        else
 
                            table.insert( post, s )
 
                        end
 
                    end
 
                end
 
            end -- for i
 
            for i = 1, #post do
 
                table.insert( order, post[ i ] )
 
            end -- for i
 
            for i = 1, #three do
 
                table.insert( order, three[ i ] )
 
            end -- for i
 
            for i = 1, #unfold do
 
                table.insert( order, unfold[ i ] )
 
            end -- for i
 
            for i = 1, #order do
 
                s = order[ i ]
 
                sin = User.tell:inLanguage( s ):plain()
 
                if sin == User.sin then
 
                    User.self = s
 
                    break -- for i
 
                else
 
                    User.trials[ s ] = true
 
                end
 
            end -- for i
 
        end
 
    end
 
    return User.self
 
end -- User.favorize()
 
 
 
 
 
 
 
Multilingual.fair = function ( ask )
 
    -- Format language specification according to RFC 5646 etc.
 
    -- Precondition:
 
    --    ask  -- string or table, as created by .getLang()
 
    -- Postcondition:
 
    --    Returns string, or false
 
    local s = type( ask )
 
    local q, r
 
    if s == "table" then
 
        q = ask
 
    elseif s == "string" then
 
        q = Multilingual.getLang( ask )
 
    end
 
    if q  and
 
      q.legal  and
 
      mw.language.isKnownLanguageTag( q.base ) then
 
        r = q.base
 
        if q.n > 1 then
 
            local order = { "extlang",
 
                            "script",
 
                            "region",
 
                            "other",
 
                            "extension" }
 
            for i = 1, #order do
 
                s = q[ order[ i ] ]
 
                if s then
 
                    r =  string.format( "%s-%s", r, s )
 
                end
 
            end -- for i
 
        end
 
    end
 
    return r or false
 
end -- Multilingual.fair()
 
 
 
 
 
 
 
Multilingual.fallback = function ( able, another )
 
    -- Is another language suitable as replacement?
 
    -- Precondition:
 
    --    able    -- language version specifier to be supported
 
    --    another  -- language specifier of a possible replacement,
 
    --                or not to retrieve a fallback table
 
    -- Postcondition:
 
    --    Returns boolean, or table with fallback codes
 
    local r
 
    if type( able ) == "string"  and  #able > 0 then
 
        if type( another ) == "string" and  #another > 0 then
 
            if able == another then
 
                r = true
 
            else
 
                local s = Multilingual.getBase( able )
 
                if s == another then
 
                    r = true
 
                else
 
                    local others = mw.language.getFallbacksFor( s )
 
                    r = feasible( another, others )
 
                end
 
            end
 
        else
 
            local s = Multilingual.getBase( able )
 
            if s then
 
                r = mw.language.getFallbacksFor( s )
 
                if r[ 1 ] == "en" then
 
                    local d = fetchISO639( "fallback" )
 
                    if type( d ) == "table"  and
 
                      type( d[ s ] ) == "string" then
 
                        r = mw.text.split( d[ s ], "|" )
 
                        table.insert( r, "en" )
 
                    end
 
                end
 
            end
 
        end
 
    end
 
    return r or false
 
end -- Multilingual.fallback()
 
 
 
 
 
 
 
Multilingual.findCode = function ( ask )
 
    -- Retrieve code of local (current project or English) language name
 
    -- Precondition:
 
    --    ask  -- string, with presumable language name
 
    --            A code itself will be identified, too.
 
    -- Postcondition:
 
    --    Returns string, or false
 
    local seek = mw.text.trim( ask )
 
    local r = false
 
    if #seek > 1 then
 
        if seek:find( "[", 1, true ) then
 
            local wlink = fetch( "WLink" )
 
            if wlink  and
 
              type( wlink.getPlain ) == "function" then
 
                seek = wlink.getPlain( seek )
 
            end
 
        end
 
        seek = mw.ustring.lower( seek )
 
        if Multilingual.isLang( seek ) then
 
            r = Multilingual.fair( seek )
 
        else
 
            local collection = favorites()
 
            for i = 1, #collection do
 
                r = find( seek, collection[ i ] )
 
                if r then
 
                    break -- for i
 
                end
 
            end -- for i
 
        end
 
    end
 
    return r
 
end -- Multilingual.findCode()
 
 
 
 
 
 
 
Multilingual.fix = function ( attempt )
 
    -- Fix frequently mistaken language code
 
    -- Precondition:
 
    --    attempt  -- string, with presumable language code
 
    -- Postcondition:
 
    --    Returns string with correction, or false if no problem known
 
    local r = fetchISO639( "correction" )[ attempt:lower() ]
 
    return r or false
 
end -- Multilingual.fix()
 
 
 
 
 
 
 
Multilingual.format = function ( apply, alien, alter, active, alert,
 
                                frame, assembly, adjacent, ahead )
 
    -- Format one or more languages
 
    -- Precondition:
 
    --    apply    -- string with language list or item
 
    --    alien    -- language of the answer
 
    --                  -- nil, false, "*": native
 
    --                  -- "!": current project
 
    --                  -- "#": code, downcased, space separated
 
    --                  -- "-": code, mixcase, space separated
 
    --                  -- any valid code
 
    --    alter    -- capitalize, if "c"; downcase all, if "d"
 
    --                  capitalize first item only, if "f"
 
    --                  downcase every first word only, if "m"
 
    --    active    -- link items, if true
 
    --    alert    -- string with category title in case of error
 
    --    frame    -- if available
 
    --    assembly  -- string with split pattern, if list expected
 
    --    adjacent  -- string with list separator, else assembly
 
    --    ahead    -- string to prepend first element, if any
 
    -- Postcondition:
 
    --    Returns string, or false if apply empty
 
    local r = false
 
    if apply then
 
        local slang
 
        if assembly then
 
            local bucket = mw.text.split( apply, assembly )
 
            local shift = alter
 
            local separator
 
            if adjacent then
 
                separator = adjacent
 
            elseif alien == "#"  or  alien == "-" then
 
                separator = " "
 
            else
 
                separator = assembly
 
            end
 
            for k, v in pairs( bucket ) do
 
                slang = Multilingual.format( v, alien, shift, active,
 
                                            alert )
 
                if slang then
 
                    if r then
 
                        r = string.format( "%s%s%s",
 
                                          r, separator, slang )
 
                    else
 
                        r = slang
 
                        if shift == "f" then
 
                            shift = "d"
 
                        end
 
                    end
 
                end
 
            end -- for k, v
 
            if r and ahead then
 
                r = ahead .. r
 
            end
 
        else
 
            local single = mw.text.trim( apply )
 
            if single == "" then
 
                r = false
 
            else
 
                local lapsus, slot
 
                slang = Multilingual.findCode( single )
 
                if slang then
 
                    if alien == "-" then
 
                        r = slang
 
                    elseif alien == "#" then
 
                        r = slang:lower()
 
                    else
 
                        r = Multilingual.getName( slang, alien )
 
                        if active then
 
                            slot = fill( slang, false, frame )
 
                            if slot then
 
                                local wlink = fetch( "WLink" )
 
                                if wlink  and
 
                                  type( wlink.getTarget )
 
                                                      == "function" then
 
                                    slot = wlink.getTarget( slot )
 
                                end
 
                            else
 
                                lapsus = alert
 
                            end
 
                        end
 
                    end
 
                else
 
                    r = single
 
                    if active then
 
                        local title = mw.title.makeTitle( 0, single )
 
                        if title.exists then
 
                            slot = single
 
                        end
 
                    end
 
                    lapsus = alert
 
                end
 
                if not r then
 
                    r = single
 
                elseif alter == "c" or alter == "f" then
 
                    r = mw.ustring.upper( mw.ustring.sub( r, 1, 1 ) )
 
                        .. mw.ustring.sub( r, 2 )
 
                elseif alter == "d" then
 
                    if Multilingual.isMinusculable( slang, r ) then
 
                        r = mw.ustring.lower( r )
 
                    end
 
                elseif alter == "m" then
 
                    if Multilingual.isMinusculable( slang, r ) then
 
                        r = mw.ustring.lower( mw.ustring.sub( r, 1, 1 ) )
 
                            .. mw.ustring.sub( r, 2 )
 
                    end
 
                end
 
                if slot then
 
                    if r == slot then
 
                        r = string.format( "[[%s]]", r )
 
                    else
 
                        r = string.format( "[[%s|%s]]", slot, r )
 
                    end
 
                end
 
                if lapsus and alert then
 
                    r = string.format( "%s[[Category:%s]]", r, alert )
 
                end
 
            end
 
        end
 
    end
 
    return r
 
end -- Multilingual.format()
 
 
 
 
 
 
 
Multilingual.getBase = function ( ask )
 
    -- Retrieve base language from possibly combined ISO language code
 
    -- Precondition:
 
    --    ask  -- language code
 
    -- Postcondition:
 
    --    Returns string, or false
 
    local r
 
    if ask then
 
        local slang = ask:match( "^%s*(%a%a%a?)-?%a*%s*$" )
 
        if slang then
 
            r = slang:lower()
 
        else
 
            r = false
 
        end
 
    else
 
        r = false
 
    end
 
    return r
 
end -- Multilingual.getBase()
 
 
 
 
 
 
 
Multilingual.getLang = function ( ask )
 
    -- Retrieve components of a RFC 5646 language code
 
    -- Precondition:
 
    --    ask  -- language code with subtags
 
    -- Postcondition:
 
    --    Returns table with formatted subtags
 
    --            .base
 
    --            .region
 
    --            .script
 
    --            .suggest
 
    --            .year
 
    --            .extension
 
    --            .other
 
    --            .n
 
    local tags = mw.text.split( ask, "-" )
 
    local s    = tags[ 1 ]
 
    local r
 
    if s:match( "^%a%a%a?$" ) then
 
        r = { base  = s:lower(),
 
              legal = true,
 
              n    = #tags }
 
        for i = 2, r.n do
 
            s = tags[ i ]
 
            if #s == 2 then
 
                if r.region  or  not s:match( "%a%a" ) then
 
                    r.legal = false
 
                else
 
                    r.region = s:upper()
 
                end
 
            elseif #s == 4 then
 
                if s:match( "%a%a%a%a" ) then
 
                    r.legal = ( not r.script )
 
                    r.script = s:sub( 1, 1 ):upper() ..
 
                              s:sub( 2 ):lower()
 
                elseif s:match( "20%d%d" )  or
 
                      s:match( "1%d%d%d" ) then
 
                    r.legal = ( not r.year )
 
                    r.year = s
 
                else
 
                    r.legal = false
 
                end
 
            elseif #s == 3 then
 
                if r.extlang  or  not s:match( "%a%a%a" ) then
 
                    r.legal = false
 
                else
 
                    r.extlang = s:lower()
 
                end
 
            elseif #s == 1 then
 
                s = s:lower()
 
                if s:match( "[tux]" ) then
 
                    r.extension = s
 
                    for k = i + 1, r.n do
 
                        s = tags[ k ]
 
                        if s:match( "^%w+$" ) then
 
                            r.extension = string.format( "%s-%s",
 
                                                        r.extension, s )
 
                        else
 
                            r.legal = false
 
                        end
 
                    end -- for k
 
                else
 
                    r.legal = false
 
                end
 
                break -- for i
 
            else
 
                r.legal = ( not r.other )  and
 
                          s:match( "%a%a%a" )
 
                r.other = s:lower()
 
            end
 
            if not r.legal then
 
                break -- for i
 
            end
 
        end -- for i
 
        if r.legal then
 
            r.suggest = Multilingual.fix( r.base )
 
            if r.suggest then
 
                r.legal = false
 
            end
 
        end
 
    else
 
        r = { legal = false }
 
    end
 
    if not r.legal then
 
        local cnf = fetch( "Multilingual", "config" )
 
        if cnf  and  type( cnf.scream ) == "string" then
 
            r.scream = cnf.scream
 
        end
 
    end
 
    return r
 
end -- Multilingual.getLang()
 
 
 
 
 
 
 
Multilingual.getName = function ( ask, alien )
 
    -- Which name is assigned to this language code?
 
    -- Precondition:
 
    --    ask    -- language code
 
    --    alien  -- language of the answer
 
    --              -- nil, false, "*": native
 
    --              -- "!": current project
 
    --              -- any valid code
 
    -- Postcondition:
 
    --    Returns string, or false
 
    local r
 
    if ask then
 
        local slang  = alien
 
        local tLang
 
        if slang then
 
            if slang == "*" then
 
                slang = Multilingual.fair( ask )
 
            elseif slang == "!" then
 
                slang = favorites()[ 1 ]
 
            else
 
                slang = Multilingual.fair( slang )
 
            end
 
        else
 
            slang = Multilingual.fair( ask )
 
        end
 
        if not slang then
 
            slang = ask or "?????"
 
        end
 
        slang = slang:lower()
 
        tLang = fetch( "Multilingual", "names" )
 
        if tLang then
 
            tLang = tLang[ slang ]
 
            if tLang then
 
                r = tLang[ ask ]
 
            end
 
        end
 
        if not r then
 
            if not Multilingual.ext.tMW then
 
                Multilingual.ext.tMW = { }
 
            end
 
            tLang = Multilingual.ext.tMW[ slang ]
 
            if tLang == nil then
 
                tLang = mw.language.fetchLanguageNames( slang )
 
                if tLang then
 
                    Multilingual.ext.tMW[ slang ] = tLang
 
                else
 
                    Multilingual.ext.tMW[ slang ] = false
 
                end
 
            end
 
            if tLang then
 
                r = tLang[ ask ]
 
            end
 
        end
 
        if not r then
 
            r = mw.language.fetchLanguageName( ask:lower(), slang )
 
            if r == "" then
 
                r = false
 
            end
 
        end
 
    else
 
        r = false
 
    end
 
    return r
 
end -- Multilingual.getName()
 
 
 
 
 
 
 
Multilingual.i18n = function ( available, alt, frame )
 
    -- Select translatable message
 
    -- Precondition:
 
    --    available  -- table, with mapping language code ./. text
 
    --    alt        -- string|nil|false, with fallback text
 
    --    frame      -- frame, if available
 
    --    Returns
 
    --        1. string|nil|false, with selected message
 
    --        2. string|nil|false, with language code
 
    local r1, r2
 
    if type( available ) == "table" then
 
        local codes = { }
 
        local trsl  = { }
 
        local slang
 
        for k, v in pairs( available ) do
 
            if type( k ) == "string"  and
 
              type( v ) == "string" then
 
                slang = mw.text.trim( k:lower() )
 
                table.insert( codes, slang )
 
                trsl[ slang ] = v
 
            end
 
        end -- for k, v
 
        slang = Multilingual.userLang( codes, frame )
 
        if slang  and  trsl[ slang ] then
 
            r1 = mw.text.trim( trsl[ slang ] )
 
            if r1 == "" then
 
                r1 = false
 
            else
 
                r2 = slang
 
            end
 
        end
 
    end
 
    if not r1  and  type( alt ) == "string" then
 
        r1 = mw.text.trim( alt )
 
        if r1 == "" then
 
            r1 = false
 
        end
 
    end
 
    return r1, r2
 
end -- Multilingual.i18n()
 
 
 
 
 
 
 
Multilingual.int = function ( access, alien, apply )
 
    -- Translated system message
 
    -- Precondition:
 
    --    access  -- message ID
 
    --    alien  -- language code
 
    --    apply  -- nil, or sequence table with parameters $1, $2, ...
 
    -- Postcondition:
 
    --    Returns string, or false
 
    local o = mw.message.new( access )
 
    local r
 
    if o:exists() then
 
        if type( alien ) == "string" then
 
            o:inLanguage( alien:lower() )
 
        end
 
        if type( apply ) == "table" then
 
            o:params( apply )
 
        end
 
        r = o:plain()
 
    end
 
    return r or false
 
end -- Multilingual.int()
 
 
 
 
 
 
 
Multilingual.isLang = function ( ask, additional )
 
    -- Could this be an ISO language code?
 
    -- Precondition:
 
    --    ask        -- language code
 
    --    additional  -- true, if Wiki codes like "simple" permitted
 
    -- Postcondition:
 
    --    Returns boolean
 
    local r, s
 
    if additional then
 
        s = ask
 
    else
 
        s = Multilingual.getBase( ask )
 
    end
 
    if s then
 
        r = mw.language.isKnownLanguageTag( s )
 
        if r then
 
            r = not Multilingual.fix( s )
 
        elseif additional then
 
            r = Multilingual.exotic[ s ] or false
 
        end
 
    else
 
        r = false
 
    end
 
    return r
 
end -- Multilingual.isLang()
 
 
 
 
 
 
 
Multilingual.isLangWiki = function ( ask )
 
    -- Could this be a Wiki language version?
 
    -- Precondition:
 
    --    ask  -- language version specifier
 
    -- Postcondition:
 
    --    Returns boolean
 
    local r
 
    local s = Multilingual.getBase( ask )
 
    if s then
 
        r = mw.language.isSupportedLanguage( s )  or
 
            Multilingual.exotic[ ask ]
 
    else
 
        r = false
 
    end
 
    return r
 
end -- Multilingual.isLangWiki()
 
 
 
 
 
 
 
Multilingual.isMinusculable = function ( ask, assigned )
 
    -- Could this language name become downcased?
 
    -- Precondition:
 
    --    ask      -- language code, or nil
 
    --    assigned  -- language name, or nil
 
    -- Postcondition:
 
    --    Returns boolean
 
    local r = true
 
    if ask then
 
        local cnf = fetch( "Multilingual", "config" )
 
        if cnf then
 
            local s = string.format( " %s ", ask:lower() )
 
            if type( cnf.stopMinusculization ) == "string"
 
              and  cnf.stopMinusculization:find( s, 1, true ) then
 
                r = false
 
            end
 
            if r  and  assigned
 
              and  type( cnf.seekMinusculization ) == "string"
 
              and  cnf.seekMinusculization:find( s, 1, true )
 
              and  type( cnf.scanMinusculization ) == "string" then
 
                local scan = assigned:gsub( "[%(%)]", " " ) .. " "
 
                if not scan:find( cnf.scanMinusculization ) then
 
                    r = false
 
                end
 
            end
 
        end
 
    end
 
    return r
 
end -- Multilingual.isMinusculable()
 
 
 
 
 
 
 
Multilingual.isRTL = function ( ask )
 
    -- Check whether language is written right-to-left
 
    -- Precondition:
 
    --    ask  -- string, with language (or script) code
 
    -- Returns true, if right-to-left
 
    local r
 
    Multilingual.rtl = Multilingual.rtl or { }
 
    r = Multilingual.rtl[ ask ]
 
    if type( r ) ~= "boolean" then
 
        local bib = fetch( "ISO15924" )
 
        if type( bib ) == "table"  and
 
          type( bib.isRTL ) == "function" then
 
            r = bib.isRTL( ask )
 
        else
 
            r = mw.language.new( ask ):isRTL()
 
        end
 
        Multilingual.rtl[ ask ] = r
 
    end
 
    return r
 
end -- Multilingual.isRTL()
 
 
 
 
 
 
 
Multilingual.message = function ( arglist, frame )
 
    -- Show text in best match of user language like system message
 
    -- Precondition:
 
    --    arglist  -- template arguments
 
    --    frame    -- frame, if available
 
    -- Postcondition:
 
    --    Returns string with appropriate text
 
    local r
 
    if type( arglist ) == "table" then
 
        local t = { }
 
        local m, p, save
 
        for k, v in pairs( arglist ) do
 
            if type( k ) == "string"  and
 
              type( v ) == "string" then
 
                v = mw.text.trim( v )
 
                if v ~= "" then
 
                    if k:match( "^%l%l" ) then
 
                        t[ k ] = v
 
                    elseif k:match( "^%$%d$" )  and  k ~= "$0" then
 
                        p = p or { }
 
                        k = tonumber( k:match( "^%$(%d)$" ) )
 
                        p[ k ] = v
 
                        if not m  or  k > m then
 
                            m = k
 
                        end
 
                    end
 
                end
 
            end
 
        end -- for k, v
 
        if type( arglist[ "-" ] ) == "string" then
 
            save = arglist[ arglist[ "-" ] ]
 
        end
 
        r = Multilingual.i18n( t, save, frame )
 
        if p  and  r  and  r:find( "$", 1, true ) then
 
            t = { }
 
            for i = 1, m do
 
                t[ i ] = p[ i ]  or  ""
 
            end -- for i
 
            r = mw.message.newRawMessage( r, t ):plain()
 
        end
 
    end
 
    return r  or  ""
 
end -- Multilingual.message()
 
 
 
 
 
 
 
Multilingual.sitelink = function ( all, frame )
 
    -- Make link at local or other site with optimal linktext translation
 
    -- Precondition:
 
    --    all    -- string or table or number, item ID or entity
 
    --    frame  -- frame, if available
 
    -- Postcondition:
 
    --    Returns string with any helpful internal link, or plain text
 
    local s = type( all )
 
    local object, r
 
    if s == "table" then
 
        object = all
 
    elseif s == "string" then
 
        object = mw.wikibase.getEntity( all )
 
    elseif s == "number" then
 
        object = mw.wikibase.getEntity( string.format( "Q%d", all ) )
 
    end
 
    if type( object ) == "table" then
 
        local collection = object.sitelinks
 
        local entry
 
        s = false
 
        if type( collection ) == "table" then
 
            Multilingual.site = Multilingual.site  or
 
                                mw.wikibase.getGlobalSiteId()
 
            entry = collection[ Multilingual.site ]
 
            if entry then
 
                s = ":" .. entry.title
 
            elseif collection.enwiki then
 
                s = "w:en:" .. collection.enwiki.title
 
            end
 
        end
 
        r = Multilingual.wikibase( object, "labels", frame )
 
        if s then
 
            if s == ":" .. r then
 
                r = string.format( "[[%s]]", s )
 
            else
 
                r = string.format( "[[%s|%s]]", s, r )
 
            end
 
        end
 
    end
 
    return r  or  ""
 
end -- Multilingual.sitelink()
 
 
 
 
 
 
 
Multilingual.tabData = function ( access, at, alt, frame )
 
    -- Retrieve translated keyword from commons:Data:****.tab
 
    -- Precondition:
 
    --    access  -- string, with page identification on Commons
 
    --    at      -- string, with keyword
 
    --    alt    -- string|nil|false, with fallback text
 
    --    frame  -- frame, if available
 
    --    Returns
 
    --        1. string|nil|false, with selected message
 
    --        2. language code, or "error"
 
    local data = fetchData( access )
 
    local r1, r2
 
    if  type( data ) == "table" then
 
        if type( at ) == "string" then
 
            local seek = mw.text.trim( at )
 
            if seek == "" then
 
                r1 = "EMPTY Multilingual.tabData key"
 
            else
 
                local e, poly
 
                for i = 1, #data do
 
                    e = data[ i ]
 
                    if type( e ) == "table" then
 
                        if e[ 1 ] == seek then
 
                            if type( e[ 2 ] ) == "table" then
 
                                poly = e[ 2 ]
 
                            else
 
                                r1 = "INVALID Multilingual.tabData bad #"
 
                                                        .. tostring( i )
 
                            end
 
                            break  -- for i
 
                        end
 
                    else
 
                        break  -- for i
 
                    end
 
                end  -- for i
 
                if poly then
 
                    data = poly
 
                else
 
                    r1 = "UNKNOWN Multilingual.tabData key: " .. seek
 
                end
 
            end
 
        else
 
            r1 = "INVALID Multilingual.tabData key"
 
        end
 
    else
 
        r1 = data
 
    end
 
    if r1 then
 
        r2 = "error"
 
    elseif data then
 
        r1, r2 = Multilingual.i18n( data, alt, frame )
 
        r2 = r2 or "error"
 
    end
 
    return r1, r2
 
end -- Multilingual.tabData()
 
 
 
 
 
 
 
Multilingual.userLang = function ( accept, frame )
 
    -- Try to support user language by application
 
    -- Precondition:
 
    --    accept  -- string or table
 
    --                space separated list of available ISO 639 codes
 
    --                Default: project language, or English
 
    --    frame  -- frame, if available
 
    -- Postcondition:
 
    --    Returns string with appropriate code
 
    local s = type( accept )
 
    local codes, r, slang
 
    if s == "string" then
 
        codes = mw.text.split( accept:lower(), "%s+" )
 
    elseif s == "table" then
 
        codes = { }
 
        for i = 1, #accept do
 
            s = accept[ i ]
 
            if type( s ) == "string"  and
 
              s ~= "" then
 
                table.insert( codes, s:lower() )
 
            end
 
        end -- for i
 
    end
 
    slang = User.favorize( codes, frame )
 
    if slang then
 
        if feasible( slang, codes ) then
 
            r = slang
 
        elseif slang:find( "-", 1, true ) then
 
            slang = Multilingual.getBase( slang )
 
            if feasible( slang, codes ) then
 
                r = slang
 
            end
 
        end
 
        if not r then
 
            local others = mw.language.getFallbacksFor( slang )
 
            for i = 1, #others do
 
                slang = others[ i ]
 
                if feasible( slang, codes ) then
 
                    r = slang
 
                    break -- for i
 
                end
 
            end -- for i
 
        end
 
    end
 
    if not r then
 
        local back = favorites()
 
        for i = 1, #back do
 
            slang = back[ i ]
 
            if feasible( slang, codes ) then
 
                r = slang
 
                break -- for i
 
            end
 
        end -- for i
 
        if not r  and  codes[ 1 ] then
 
            r = codes[ 1 ]
 
        end
 
    end
 
    return r  or  favorites()[ 1 ]
 
end -- Multilingual.userLang()
 
 
 
 
 
 
 
Multilingual.userLangCode = function ()
 
    -- Guess a user language code
 
    -- Postcondition:
 
    --    Returns code of current best guess
 
    return User.self  or  favorites()[ 1 ]
 
end -- Multilingual.userLangCode()
 
 
 
 
 
 
 
Multilingual.wikibase = function ( all, about, attempt, frame )
 
    -- Optimal translation of wikibase component
 
    -- Precondition:
 
    --    all      -- string or table, object ID or entity
 
    --    about    -- boolean, true "descriptions" or false "labels"
 
    --    attempt  -- string or not, code of preferred language
 
    --    frame    -- frame, if available
 
    -- Postcondition:
 
    --    Returns
 
    --        1. string, with selected message
 
    --        2. string, with language code, or not
 
    local s = type( all )
 
    local object, r, r2
 
    if s == "table" then
 
        object = all
 
    elseif s == "string" then
 
        object = mw.wikibase.getEntity( all )
 
    end
 
    if type( object ) == "table" then
 
        if about  and  about ~= "labels" then
 
            s = "descriptions"
 
        else
 
            s = "labels"
 
        end
 
        object = object[ s ]
 
        if type( object ) == "table" then
 
            if object[ attempt ] then
 
                r  = object[ attempt ].value
 
                r2 = attempt
 
            else
 
                local poly
 
                for k, v in pairs( object ) do
 
                    poly = poly or { }
 
                    poly[ k ] = v.value
 
                end -- for k, v
 
                if poly then
 
                    r, r2 = Multilingual.i18n( poly, nil, frame )
 
                end
 
            end
 
        end
 
    end
 
    return r  or  "",  r2
 
end -- Multilingual.wikibase()
 
 
 
 
 
 
 
Failsafe.failsafe = function ( atleast )
 
    -- Retrieve versioning and check for compliance
 
    -- Precondition:
 
    --    atleast  -- string, with required version
 
    --                        or wikidata|item|~|@ or false
 
    -- Postcondition:
 
    --    Returns  string  -- with queried version/item, also if problem
 
    --              false  -- if appropriate
 
    -- 2020-08-17
 
    local since = atleast
 
    local last    = ( since == "~" )
 
    local linked  = ( since == "@" )
 
    local link    = ( since == "item" )
 
    local r
 
    if last  or  link  or  linked  or  since == "wikidata" then
 
        local item = Failsafe.item
 
        since = false
 
        if type( item ) == "number"  and  item > 0 then
 
            local suited = string.format( "Q%d", item )
 
            if link then
 
                r = suited
 
            else
 
                local entity = mw.wikibase.getEntity( suited )
 
                if type( entity ) == "table" then
 
                    local seek = Failsafe.serialProperty or "P348"
 
                    local vsn  = entity:formatPropertyValues( seek )
 
                    if type( vsn ) == "table"  and
 
                      type( vsn.value ) == "string"  and
 
                      vsn.value ~= "" then
 
                        if last  and  vsn.value == Failsafe.serial then
 
                            r = false
 
                        elseif linked then
 
                            if mw.title.getCurrentTitle().prefixedText
 
                              ==  mw.wikibase.getSitelink( suited ) then
 
                                r = false
 
                            else
 
                                r = suited
 
                            end
 
                        else
 
                            r = vsn.value
 
                        end
 
                    end
 
                end
 
            end
 
        end
 
    end
 
    if type( r ) == "nil" then
 
        if not since  or  since <= Failsafe.serial then
 
            r = Failsafe.serial
 
        else
 
            r = false
 
        end
 
    end
 
    return r
 
end -- Failsafe.failsafe()
 
 
 
 
 
 
 
-- Export
 
local p = { }
 
 
 
 
 
 
 
p.fair = function ( frame )
 
    -- Format language code
 
    --    1  -- language code
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    return Multilingual.fair( s )  or  ""
 
end -- p.fair
 
 
 
 
 
 
 
p.fallback = function ( frame )
 
    -- Is another language suitable as replacement?
 
    --    1  -- language version specifier to be supported
 
    --    2  -- language specifier of a possible replacement
 
    local s1 = mw.text.trim( frame.args[ 1 ] or  "" )
 
    local s2 = mw.text.trim( frame.args[ 2 ] or  "" )
 
    local r  = Multilingual.fallback( s1, s2 )
 
    if type( r ) == "table" then
 
        r = r[ 1 ]
 
    else
 
        r = r  and  "1"  or  ""
 
    end
 
    return r
 
end -- p.fallback
 
 
 
 
 
 
 
p.findCode = function ( frame )
 
    -- Retrieve language code from language name
 
    --    1  -- name in current project language
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    return Multilingual.findCode( s )  or  ""
 
end -- p.findCode
 
 
 
 
 
 
 
p.fix = function ( frame )
 
    local r = frame.args[ 1 ]
 
    if r then
 
        r = Multilingual.fix( mw.text.trim( r ) )
 
    end
 
    return r or ""
 
end -- p.fix
 
 
 
 
 
 
 
p.format = function ( frame )
 
    -- Format one or more languages
 
    --    1          -- language list or item
 
    --    slang      -- language of the answer, if not native
 
    --                  * -- native
 
    --                  ! -- current project
 
    --                  any valid code
 
    --    shift      -- capitalize, if "c"; downcase, if "d"
 
    --                  capitalize first item only, if "f"
 
    --    link      -- 1 -- link items
 
    --    scream    -- category title in case of error
 
    --    split      -- split pattern, if list expected
 
    --    separator  -- list separator, else split
 
    --    start      -- prepend first element, if any
 
    local r
 
    local link
 
    if frame.args.link == "1" then
 
        link = true
 
    end
 
    r = Multilingual.format( frame.args[ 1 ],
 
                            frame.args.slang,
 
                            frame.args.shift,
 
                            link,
 
                            frame.args.scream,
 
                            frame,
 
                            frame.args.split,
 
                            frame.args.separator,
 
                            frame.args.start )
 
    return r or ""
 
end -- p.format
 
 
 
 
 
 
 
p.getBase = function ( frame )
 
    -- Retrieve base language from possibly combined ISO language code
 
    --    1  -- code
 
    local s = mw.text.trim( frame.args[ 1 ] or  "" )
 
    return Multilingual.getBase( s )  or  ""
 
end -- p.getBase
 
 
 
 
 
 
 
p.getName = function ( frame )
 
    -- Retrieve language name from ISO language code
 
    --    1  -- code
 
    --    2  -- language to be used for the answer, if not native
 
    --          ! -- current project
 
    --          * -- native
 
    --          any valid code
 
    local s    = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    local slang = frame.args[ 2 ]
 
    local r
 
    Multilingual.frame = frame
 
    if slang then
 
        slang = mw.text.trim( slang )
 
    end
 
    r = Multilingual.getName( s, slang )
 
    return r or ""
 
end -- p.getName
 
 
 
 
 
 
 
p.int = function ( frame )
 
    -- Translated system message
 
    --    1            -- message ID
 
    --    lang          -- language code
 
    --    $1, $2, ...  -- parameters
 
    local sysMsg = frame.args[ 1 ]
 
    local r
 
    if sysMsg then
 
        sysMsg = mw.text.trim( sysMsg )
 
        if sysMsg ~= "" then
 
            local n    = 0
 
            local slang = frame.args.lang
 
            local i, params, s
 
            if slang == "" then
 
                slang = false
 
            end
 
            for k, v in pairs( frame.args ) do
 
                if type( k ) == "string" then
 
                    s = k:match( "^%$(%d+)$" )
 
                    if s then
 
                        i = tonumber( s )
 
                        if i > n then
 
                            n = i
 
                        end
 
                    end
 
                end
 
            end -- for k, v
 
            if n > 0 then
 
                local s
 
                params = { }
 
                for i = 1, n do
 
                    s = frame.args[ "$" .. tostring( i ) ]  or  ""
 
                    table.insert( params, s )
 
                end -- for i
 
            end
 
            r = Multilingual.int( sysMsg, slang, params )
 
        end
 
    end
 
    return r or ""
 
end -- p.int
 
 
 
 
 
 
 
p.isLang = function ( frame )
 
    -- Could this be an ISO language code?
 
    --    1  -- code
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    local lucky, r = pcall( Multilingual.isLang, s )
 
    return r and "1" or ""
 
end -- p.isLang
 
 
 
 
 
 
 
p.isLangWiki = function ( frame )
 
    -- Could this be a Wiki language version?
 
    --    1  -- code
 
    -- Returns non-empty, if possibly language version
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    local lucky, r = pcall( Multilingual.isLangWiki, s )
 
    return r and "1" or ""
 
end -- p.isLangWiki
 
 
 
 
 
 
 
p.isRTL = function ( frame )
 
    -- Check whether language is written right-to-left
 
    --    1  -- string, with language code
 
    -- 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()
 
 
 
 
 
 
 
p.message = function ( frame )
 
    -- Translation of text element
 
    return Multilingual.message( fold( frame ), frame )
 
end -- p.message
 
 
 
 
 
 
 
p.sitelink = function ( frame )
 
    -- Make link at local or other site with optimal linktext translation
 
    --    1  -- item ID
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    local r
 
    if s:match( "^%d+$") then
 
        r = tonumber( s )
 
    elseif s:match( "^Q%d+$") then
 
        r = s
 
    end
 
    if r then
 
        r = Multilingual.sitelink( r, frame )
 
    end
 
    return r or s
 
end -- p.sitelink
 
 
 
 
 
 
 
p.tabData = function ( frame )
 
    -- Retrieve best message text from Commons Data
 
    --    1    -- page identification on Commons
 
    --    2    -- keyword
 
    --    alt  -- fallback text
 
    local suite = frame.args[ 1 ]
 
    local seek  = frame.args[ 2 ]
 
    local salt  = frame.args.alt
 
    local r    = Multilingual.tabData( suite, seek, salt, frame )
 
    return r
 
end -- p.tabData
 
 
 
 
 
 
 
p.userLang = function ( frame )
 
    -- Which language does the current user prefer?
 
    --    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
 
 
 
 
 
 
 
p.wikibase = function ( frame )
 
    -- Optimal translation of wikibase component
 
    --    1  -- object ID
 
    --    2  -- 1 for "descriptions", 0 for "labels".
 
    --          or either "descriptions" or "labels"
 
    local r
 
    local s = mw.text.trim( frame.args[ 1 ]  or  "" )
 
    if s ~= "" then
 
        local s2    = mw.text.trim( frame.args[ 2 ] or  "0" )
 
        local slang = mw.text.trim( frame.args.lang  or  "" )
 
        local large = ( s2 ~= ""  and  s2 ~= "0" )
 
        if slang == "" then
 
            slang = false
 
        end
 
        r = Multilingual.wikibase( s, large, slang, frame )
 
    end
 
    return r or ""
 
end -- p.wikibase
 
 
 
 
 
 
 
p.failsafe = function ( frame )
 
    -- Versioning interface
 
    local s = type( frame )
 
    local since
 
    if s == "table" then
 
        since = frame.args[ 1 ]
 
    elseif s == "string" then
 
        since = frame
 
    end
 
    if since then
 
        since = mw.text.trim( since )
 
        if since == "" then
 
            since = false
 
        end
 
    end
 
    return Failsafe.failsafe( since )  or  ""
 
end -- p.failsafe()
 
 
 
 
 
 
 
p.Multilingual = function ()
 
    return Multilingual
 
end -- p.Multilingual
 
 
 
return p
 

Revision as of 21:32, 6 April 2023