|
|
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
| |