Importer, Bürokraten, Moderatoren (CommentStreams), Strukturierte-Diskussionen-Bots, Oberflächenadministratoren, Push-Abonnementverwalter, Oversighter, Administratoren, Kampagnenbearbeiter (Hochladeassistent)
855
Bearbeitungen
w>PerfektesChaos (2019-11-01) |
K (43 Versionen von wikivoyage:Modul:Multilingual importiert) |
||
| (10 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
local Multilingual = { suite = "Multilingual", | local Multilingual = { suite = "Multilingual", | ||
serial = " | serial = "2020-12-10", | ||
item = 47541920, | item = 47541920, | ||
globals = { ISO15924 = 71584769, | globals = { ISO15924 = 71584769, | ||
WLink = 19363224 } | WLink = 19363224 } | ||
} | } | ||
local Failsafe = Multilingual | --[=[ | ||
local | Utilities for multilingual texts and ISO 639 (BCP47) issues etc. | ||
local User | * 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 | Multilingual.globals.Multilingual = Multilingual.item | ||
Multilingual.exotic = { simple = true, | Multilingual.exotic = { simple = true, | ||
no = 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 } | |||
| Zeile 44: | Zeile 63: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns whatever, probably table | -- Returns whatever, probably table | ||
-- | -- 2020-01-01 | ||
local storage = access | local storage = access | ||
local finer = function () | local finer = function () | ||
| Zeile 79: | Zeile 98: | ||
end | end | ||
if not lucky and alert then | if not lucky and alert then | ||
error( "Missing or invalid page: " .. storage | error( "Missing or invalid page: " .. storage ) | ||
end | end | ||
end | end | ||
return r | return r | ||
end -- foreignModule() | 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() | |||
| Zeile 98: | Zeile 187: | ||
-- * en | -- * en | ||
local r = Multilingual.polyglott | local r = Multilingual.polyglott | ||
if not r then | if not r then | ||
local self = mw.language.getContentLanguage():getCode():lower() | local self = mw.language.getContentLanguage():getCode():lower() | ||
local sub = mw.title.getCurrentTitle().subpageText | 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 = { } | r = { } | ||
if sub:find( "/", 2, true ) then | if sub:find( "/", 2, true ) then | ||
| Zeile 119: | Zeile 208: | ||
table.insert( r, sub ) | table.insert( r, sub ) | ||
end | end | ||
elseif sub:find( "^%l%l%l?%-?%a?%a?%a?%a?$" ) and | |||
mw.language.isSupportedLanguage( sub ) then | |||
table.insert( r, sub ) | |||
end | end | ||
f( self ) | f( self ) | ||
| Zeile 167: | Zeile 259: | ||
if not got and got ~= false then | if not got and got ~= false then | ||
local global = Multilingual.globals[ access ] | local global = Multilingual.globals[ access ] | ||
got = foreignModule( access, | local lib = ( not append or append == "config" ) | ||
got = foreignModule( access, lib, append, global ) | |||
if type( got ) == "table" then | if type( got ) == "table" then | ||
if | if lib then | ||
local startup = got[ access ] | local startup = got[ access ] | ||
if type( startup ) == "function" then | if type( startup ) == "function" then | ||
| Zeile 182: | Zeile 275: | ||
return got | return got | ||
end -- fetch() | 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() | |||
| Zeile 205: | Zeile 334: | ||
local f, lucky, s | local f, lucky, s | ||
Multilingual.tmplLang = template | Multilingual.tmplLang = template | ||
if type( source ) ~= "string" | if type( source ) ~= "string" and | ||
type( template.namePat ) == "string" and | |||
template.namePat:find( "%s", 1, true ) then | |||
source = string.format( template.namePat, access ) | |||
end | end | ||
if type( source ) == "string" then | if type( source ) == "string" then | ||
| Zeile 307: | Zeile 435: | ||
end | end | ||
if User.sin then | if User.sin then | ||
local order = { } | |||
local post = { } | |||
local three = { } | |||
local unfold = { } | |||
local s, sin | local s, sin | ||
for i = 1, #accept do | for i = 1, #accept do | ||
s = accept[ i ] | s = accept[ i ] | ||
if not User.trials[ s ] then | 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 | else | ||
if Multilingual.prefer[ s ] then | |||
table.insert( order, s ) | |||
else | |||
table.insert( post, s ) | |||
end | |||
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 | ||
end -- for i | end -- for i | ||
| Zeile 367: | Zeile 524: | ||
-- Precondition: | -- Precondition: | ||
-- able -- language version specifier to be supported | -- able -- language version specifier to be supported | ||
-- another -- language specifier of a possible replacement | -- another -- language specifier of a possible replacement, | ||
-- or not to retrieve a fallback table | |||
-- Postcondition: | -- Postcondition: | ||
-- Returns boolean | -- Returns boolean, or table with fallback codes | ||
local r | local r | ||
if type( able ) == "string" and | if type( able ) == "string" and #able > 0 then | ||
if type( another ) == "string" and #another > 0 then | |||
if able == another then | |||
r = true | 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 | else | ||
local s = Multilingual.getBase( able ) | local s = Multilingual.getBase( able ) | ||
if s | if s then | ||
r | r = mw.language.getFallbacksFor( s ) | ||
if r[ 1 ] == "en" then | |||
local d = fetchISO639( "fallback" ) | |||
r = | 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 | end | ||
| Zeile 431: | Zeile 603: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with correction, or false if no problem known | -- Returns string with correction, or false if no problem known | ||
local r = fetchISO639( "correction" )[ attempt:lower() ] | |||
return r or false | |||
end -- Multilingual.fix() | end -- Multilingual.fix() | ||
| Zeile 740: | Zeile 913: | ||
return r | return r | ||
end -- Multilingual.getName() | end -- Multilingual.getName() | ||
| Zeile 766: | Zeile 920: | ||
-- Precondition: | -- Precondition: | ||
-- available -- table, with mapping language code ./. text | -- available -- table, with mapping language code ./. text | ||
-- alt -- string|nil|false, with fallback | -- alt -- string|nil|false, with fallback text | ||
-- frame -- frame, if available | -- frame -- frame, if available | ||
-- Returns | -- Returns | ||
| Zeile 883: | Zeile 1.037: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns boolean | -- Returns boolean | ||
local r | local r = true | ||
if ask then | if ask then | ||
local cnf = fetch( "Multilingual", "config" ) | local cnf = fetch( "Multilingual", "config" ) | ||
| Zeile 908: | Zeile 1.062: | ||
Multilingual. | Multilingual.isRTL = function ( ask ) | ||
-- Check whether | -- Check whether language is written right-to-left | ||
-- Precondition: | -- Precondition: | ||
-- ask | -- ask -- string, with language (or script) code | ||
-- Returns true, if right-to-left | |||
-- | |||
local r | local r | ||
if type( bib ) == "table" and | Multilingual.rtl = Multilingual.rtl or { } | ||
r = Multilingual.rtl[ ask ] | |||
r = | 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 | end | ||
return r | return r | ||
end -- Multilingual. | end -- Multilingual.isRTL() | ||
| Zeile 937: | Zeile 1.095: | ||
if type( arglist ) == "table" then | if type( arglist ) == "table" then | ||
local t = { } | local t = { } | ||
local m, p | local m, p, save | ||
for k, v in pairs( arglist ) do | for k, v in pairs( arglist ) do | ||
if type( k ) == "string" and | if type( k ) == "string" and | ||
| Zeile 956: | Zeile 1.114: | ||
end | end | ||
end -- for k, v | end -- for k, v | ||
r = Multilingual.i18n( t, | 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 | if p and r and r:find( "$", 1, true ) then | ||
t = { } | t = { } | ||
| Zeile 1.011: | Zeile 1.172: | ||
return r or "" | return r or "" | ||
end -- Multilingual.sitelink() | 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() | |||
| Zeile 1.093: | Zeile 1.312: | ||
-- frame -- frame, if available | -- frame -- frame, if available | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with | -- Returns | ||
-- 1. string, with selected message | |||
-- 2. string, with language code, or not | |||
local s = type( all ) | local s = type( all ) | ||
local object, r | local object, r, r2 | ||
if s == "table" then | if s == "table" then | ||
object = all | object = all | ||
| Zeile 1.102: | Zeile 1.323: | ||
end | end | ||
if type( object ) == "table" then | if type( object ) == "table" then | ||
if about then | if about and about ~= "labels" then | ||
s = "descriptions" | s = "descriptions" | ||
else | else | ||
| Zeile 1.110: | Zeile 1.331: | ||
if type( object ) == "table" then | if type( object ) == "table" then | ||
if object[ attempt ] then | if object[ attempt ] then | ||
r = object[ attempt ].value | r = object[ attempt ].value | ||
r2 = attempt | |||
else | else | ||
local poly | local poly | ||
| Zeile 1.118: | Zeile 1.340: | ||
end -- for k, v | end -- for k, v | ||
if poly then | if poly then | ||
r = Multilingual.i18n( poly, nil, frame ) | r, r2 = Multilingual.i18n( poly, nil, frame ) | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
return r or "" | return r or "", r2 | ||
end -- Multilingual.wikibase() | end -- Multilingual.wikibase() | ||
| Zeile 1.131: | Zeile 1.353: | ||
-- Retrieve versioning and check for compliance | -- Retrieve versioning and check for compliance | ||
-- Precondition: | -- Precondition: | ||
-- atleast -- string, with required version | -- atleast -- string, with required version | ||
-- | -- or wikidata|item|~|@ or false | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string -- with queried version, also if problem | -- Returns string -- with queried version/item, also if problem | ||
-- false -- if appropriate | -- false -- if appropriate | ||
-- | -- 2020-08-17 | ||
local since = atleast | local since = atleast | ||
local last = ( since == "~" ) | |||
local linked = ( since == "@" ) | |||
local link = ( since == "item" ) | |||
local r | local r | ||
if last or since == "wikidata" then | if last or link or linked or since == "wikidata" then | ||
local item = Failsafe.item | local item = Failsafe.item | ||
since = false | since = false | ||
if type( item ) == "number" and item > 0 then | if type( item ) == "number" and item > 0 then | ||
local | 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 | |||
r = false | type( vsn.value ) == "string" and | ||
vsn.value ~= "" then | |||
r = vsn.value | 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 | ||
| Zeile 1.191: | Zeile 1.426: | ||
-- 1 -- language version specifier to be supported | -- 1 -- language version specifier to be supported | ||
-- 2 -- language specifier of a possible replacement | -- 2 -- language specifier of a possible replacement | ||
local s1 | local s1 = mw.text.trim( frame.args[ 1 ] or "" ) | ||
local s2 | 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 | end -- p.fallback | ||
| Zeile 1.276: | Zeile 1.517: | ||
return r or "" | return r or "" | ||
end -- p.getName | end -- p.getName | ||
| Zeile 1.350: | Zeile 1.576: | ||
-- Could this be a Wiki language version? | -- Could this be a Wiki language version? | ||
-- 1 -- code | -- 1 -- code | ||
-- Returns non-empty, if possibly language version | |||
local s = mw.text.trim( frame.args[ 1 ] or "" ) | local s = mw.text.trim( frame.args[ 1 ] or "" ) | ||
local lucky, r = pcall( Multilingual.isLangWiki, s ) | local lucky, r = pcall( Multilingual.isLangWiki, s ) | ||
| Zeile 1.357: | Zeile 1.584: | ||
p. | p.isRTL = function ( frame ) | ||
-- Check whether language is written right-to-left | |||
-- Check whether | -- 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 "" | ||
local | end -- p.isRTL() | ||
return Multilingual. | |||
end -- p. | |||
| Zeile 1.393: | Zeile 1.616: | ||
return r or s | return r or s | ||
end -- p.sitelink | end -- p.sitelink | ||
p.tabData = function ( frame ) | |||
-- Retrieve best message text from Commons Data | |||
-- 1 -- page identification on Commons | |||
-- 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 | |||
| Zeile 1.408: | Zeile 1.645: | ||
-- Optimal translation of wikibase component | -- Optimal translation of wikibase component | ||
-- 1 -- object ID | -- 1 -- object ID | ||
-- 2 -- either "descriptions" or "labels" | -- 2 -- 1 for "descriptions", 0 for "labels". | ||
-- or either "descriptions" or "labels" | |||
local r | local r | ||
local s = mw.text.trim( frame.args[ 1 ] or "" ) | local s = mw.text.trim( frame.args[ 1 ] or "" ) | ||