Modul:Multilingual: Unterschied zwischen den Versionen
w>PerfektesChaos (update) |
w>PerfektesChaos (2015-06-19) |
||
| Zeile 1: | Zeile 1: | ||
local Multilingual = { suite = "Multilingual", | |||
Multilingual | serial = "2015-06-19" }; | ||
local | -- local globals | ||
local Frame | local Frame | ||
local | |||
local favorite = function () | |||
-- Postcondition: | |||
-- Returns code of curent project language | |||
if not Multilingual.self then | |||
Multilingual.self = mw.language.getContentLanguage():getCode() | |||
:lower() | |||
end | |||
return Multilingual.self | |||
end -- favorite() | |||
| Zeile 20: | Zeile 29: | ||
-- Returns table or false, with library | -- Returns table or false, with library | ||
-- Throws error, if not available | -- Throws error, if not available | ||
if | if type( Multilingual.ext ) ~= "table" then | ||
elseif not | Multilingual.ext = { } | ||
end | |||
if Multilingual.ext[ access ] == false then | |||
elseif not Multilingual.ext[ access ] then | |||
local lucky, got = pcall( require, "Module:" .. access ) | local lucky, got = pcall( require, "Module:" .. access ) | ||
if lucky then | if lucky then | ||
if type( got ) == "table" then | if type( got ) == "table" then | ||
Multilingual.ext[ access ] = got | |||
if type( got[ access ] ) == "function" then | if type( got[ access ] ) == "function" then | ||
Multilingual.ext[ access ] = got[ access ]() | |||
end | end | ||
end | end | ||
end | end | ||
if type( | if type( Multilingual.ext[ access ] ) ~= "table" then | ||
error( got, 0 ) | if allow then | ||
Multilingual.ext[ access ] = false | |||
else | |||
got = string.format( "Module:%s invalid", access ) | |||
error( got, 0 ) | |||
end | |||
end | end | ||
end | end | ||
return | return Multilingual.ext[ access ] | ||
end -- fetch() | end -- fetch() | ||
function find( ask, alien ) | |||
-- Derive language code from name | |||
-- Precondition: | |||
-- ask -- language name, downcased | |||
-- alien -- language code of ask | |||
-- Postcondition: | |||
-- nil, or | |||
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 | |||
return r | |||
end -- find() | |||
function isSupported( ask, accept ) | function isSupported( ask, accept ) | ||
-- Is ask to supported by application? | -- Is ask to be supported by application? | ||
-- Precondition: | -- Precondition: | ||
-- ask -- lowercase code | -- ask -- lowercase code | ||
| Zeile 56: | Zeile 92: | ||
Multilingual.findCode = function ( ask ) | Multilingual.findCode = function ( ask ) | ||
-- Retrieve code of local (current project) language name | -- Retrieve code of local (current project or English) language name | ||
-- Precondition: | -- Precondition: | ||
-- ask -- string, with presumable language name | -- ask -- string, with presumable language name | ||
| Zeile 72: | Zeile 108: | ||
r = seek | r = seek | ||
else | else | ||
local | local slang = favorite() | ||
if not | r = find( seek, slang ) | ||
if not r and slang ~= "en" then | |||
r = find( seek, "en" ) | |||
end | end | ||
end | end | ||
end | end | ||
| Zeile 98: | Zeile 128: | ||
-- -- nil, false, "*": native | -- -- nil, false, "*": native | ||
-- -- "!": current project | -- -- "!": current project | ||
-- -- "#": code, downcased, space separated | |||
-- -- any valid code | -- -- any valid code | ||
-- alter -- capitalize, if "c"; downcase all, if "d" | -- alter -- capitalize, if "c"; downcase all, if "d" | ||
| Zeile 119: | Zeile 150: | ||
if adjacent then | if adjacent then | ||
separator = adjacent | separator = adjacent | ||
elseif alien == "#" then | |||
separator = " " | |||
else | else | ||
separator = assembly | separator = assembly | ||
| Zeile 148: | Zeile 181: | ||
slang = Multilingual.findCode( single ) | slang = Multilingual.findCode( single ) | ||
if slang then | if slang then | ||
r = Multilingual.getName( slang, alien ) | if alien == "#" then | ||
r = slang | |||
else | |||
r = Multilingual.getName( slang, alien ) | |||
if active then | |||
local cnf = fetch( "Multilingual/config", | |||
true ) | |||
if cnf then | |||
if not frame then | |||
if not Frame then | |||
Frame = mw.getCurrentFrame() | |||
end | |||
frame = Frame | |||
end | |||
slot = cnf.getLink( slang, frame ) | |||
if slot then | |||
local wlink = fetch( "WLink" ) | |||
slot = wlink.getTarget( slot ) | |||
else | |||
lapsus = alert | |||
end | end | ||
end | end | ||
end | end | ||
| Zeile 237: | Zeile 276: | ||
local r | local r | ||
if ask then | if ask then | ||
local slang = alien | local slang = alien | ||
local support = "Multilingual/names" | |||
local tLang | |||
if slang then | if slang then | ||
if slang == "*" then | if slang == "*" then | ||
slang = | slang = ask:lower() | ||
elseif slang == "!" then | elseif slang == "!" then | ||
slang = favorite() | |||
else | else | ||
slang = slang:lower() | slang = slang:lower() | ||
end | |||
else | |||
slang = ask:lower() | |||
end | |||
fetch( support, true ) | |||
tLang = Multilingual.ext.tNames | |||
if tLang then | |||
tLang = tLang[ slang ] | |||
if tLang then | |||
r = tLang[ ask ] | |||
end | end | ||
end | end | ||
r = mw.language.fetchLanguageName( ask, slang ) | 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, slang ) | |||
end | |||
else | else | ||
r = false | r = false | ||
| Zeile 329: | Zeile 396: | ||
local r, slang, support | local r, slang, support | ||
if not frame then | if not frame then | ||
if not Frame then | |||
Frame = mw.getCurrentFrame() | |||
end | |||
frame = Frame | |||
end | end | ||
slang = frame:callParserFunction( "int", "lang" ):lower() | slang = frame:callParserFunction( "int", "lang" ):lower() | ||
| Zeile 335: | Zeile 405: | ||
support = accept:lower() .. " " | support = accept:lower() .. " " | ||
else | else | ||
support = | support = favorite() | ||
if mw.language.isKnownLanguageTag( support ) then | if mw.language.isKnownLanguageTag( support ) then | ||
support = string.format( "%s en ", support ) | support = string.format( "%s en ", support ) | ||
| Zeile 345: | Zeile 415: | ||
r = slang | r = slang | ||
elseif slang:find( "-", 1, true ) then | elseif slang:find( "-", 1, true ) then | ||
slang = Multilingual.getBase() | slang = Multilingual.getBase( slang ) | ||
if isSupported( slang, support ) then | if isSupported( slang, support ) then | ||
r = slang | r = slang | ||
Version vom 24. Juni 2015, 20:53 Uhr
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
Verwendung in anderen Modulen
Dieses Modul ist notwendig für die Ausführung folgender Module. Bei Anpassungen sollte die Funktionstüchtigkeit der folgenden Module geprüft werden. Benutze dazu auch diese Tracking-Kategorie um Fehler zu finden, die sich dann auf Artikel auswirken:
- TemplateData
- Modul benötigt das Modul Multilingual – Wartungskategorie, in der nochmals alle Module gelistet sind, die von diesem Modul abhängig sind.|}}
local Multilingual = { suite = "Multilingual",
serial = "2015-06-19" };
-- local globals
local Frame
local favorite = function ()
-- Postcondition:
-- Returns code of curent project language
if not Multilingual.self then
Multilingual.self = mw.language.getContentLanguage():getCode()
:lower()
end
return Multilingual.self
end -- favorite()
local fetch = function ( access, allow )
-- Attach config or library module
-- Precondition:
-- access -- module title
-- allow -- permit non-existence
-- Postcondition:
-- Returns table or false, with library
-- Throws error, if not available
if type( Multilingual.ext ) ~= "table" then
Multilingual.ext = { }
end
if Multilingual.ext[ access ] == false then
elseif not Multilingual.ext[ access ] then
local lucky, got = pcall( require, "Module:" .. access )
if lucky then
if type( got ) == "table" then
Multilingual.ext[ access ] = got
if type( got[ access ] ) == "function" then
Multilingual.ext[ access ] = got[ access ]()
end
end
end
if type( Multilingual.ext[ access ] ) ~= "table" then
if allow then
Multilingual.ext[ access ] = false
else
got = string.format( "Module:%s invalid", access )
error( got, 0 )
end
end
end
return Multilingual.ext[ access ]
end -- fetch()
function find( ask, alien )
-- Derive language code from name
-- Precondition:
-- ask -- language name, downcased
-- alien -- language code of ask
-- Postcondition:
-- nil, or
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
return r
end -- find()
function isSupported( ask, accept )
-- Is ask to be supported by application?
-- Precondition:
-- ask -- lowercase code
-- accept -- space separated/terminated list of lowercase codes
-- Postcondition:
-- nil, or else
local seek = string.format( " %s ", ask )
local supported = string.format( " %s", accept )
return supported:find( seek, 1, true )
end -- isSupported()
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
seek = fetch( "WLink" ).getPlain( seek )
end
seek = mw.ustring.lower( seek )
if Multilingual.isLang( seek ) then
r = seek
else
local slang = favorite()
r = find( seek, slang )
if not r and slang ~= "en" then
r = find( seek, "en" )
end
end
end
return r
end -- Multilingual.findCode()
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
-- -- 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
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 == "#" 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
else
r = Multilingual.getName( slang, alien )
if active then
local cnf = fetch( "Multilingual/config",
true )
if cnf then
if not frame then
if not Frame then
Frame = mw.getCurrentFrame()
end
frame = Frame
end
slot = cnf.getLink( slang, frame )
if slot then
local wlink = fetch( "WLink" )
slot = wlink.getTarget( slot )
else
lapsus = alert
end
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 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
r = mw.ustring.lower( r )
elseif alter == "m" then
r = mw.ustring.lower( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
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 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.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 support = "Multilingual/names"
local tLang
if slang then
if slang == "*" then
slang = ask:lower()
elseif slang == "!" then
slang = favorite()
else
slang = slang:lower()
end
else
slang = ask:lower()
end
fetch( support, true )
tLang = Multilingual.ext.tNames
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, slang )
end
else
r = false
end
return r
end -- Multilingual.getName()
Multilingual.isLang = function ( ask )
-- Could this be an ISO language code?
-- Precondition:
-- ask -- language code
-- Postcondition:
-- Returns boolean
local r
local s = Multilingual.getBase( ask )
if s then
r = mw.language.isKnownLanguageTag( s )
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 )
else
r = false
end
return r
end -- Multilingual.isLangWiki()
Multilingual.kannDeutsch = function ( ask )
-- Kann man mit diesem Sprachcode deutsch verstehen?
-- Precondition:
-- ask -- language version specifier
-- Postcondition:
-- Returns boolean
local r
local s = Multilingual.getBase( ask )
if s then
local support = [=[ de als bar dsb frr gsw hsb ksh |
lb nds pdc pdt pfl sli stq vmf ]=]
if support:find( string.format( " %s ", s ), 1, true ) then
r = true
else
r = false
end
else
r = false
end
return r
end -- Multilingual.kannDeutsch()
Multilingual.userLang = function ( accept, frame )
-- Try to support user language by application
-- Precondition:
-- accept -- space separated list of available ISO 639 codes
-- Default: project language, or English
-- frame -- frame, if available
-- Postcondition:
-- Returns string with appropriate code
local r, slang, support
if not frame then
if not Frame then
Frame = mw.getCurrentFrame()
end
frame = Frame
end
slang = frame:callParserFunction( "int", "lang" ):lower()
if type( accept ) == "string" then
support = accept:lower() .. " "
else
support = favorite()
if mw.language.isKnownLanguageTag( support ) then
support = string.format( "%s en ", support )
else
support = "en "
end
end
if isSupported( slang, support ) then
r = slang
elseif slang:find( "-", 1, true ) then
slang = Multilingual.getBase( slang )
if isSupported( slang, support ) then
r = slang
end
end
if not r then
if Multilingual.kannDeutsch( slang ) and
isSupported( "de", support ) then
r = "de"
end
if not r then
r = support:match( "^(%S+) " )
end
end
return r
end -- Multilingual.userLang()
-- Export
local p = { }
p.findCode = function ( frame )
-- Retrieve language code from language name
-- 1 -- name in current project language
return Multilingual.findCode( frame.args[ 1 ] ) or ""
end -- p.findCode
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 assembly
-- 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
return Multilingual.getBase( frame.args[ 1 ] ) 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 slang = frame.args[ 2 ]
local r
if slang then
slang = mw.text.trim( slang )
end
r = Multilingual.getName( frame.args[ 1 ], slang )
return r or ""
end -- p.getName
p.isLang = function ( frame )
-- Could this be an ISO language code?
-- 1 -- code
local lucky, r = pcall( Multilingual.isLang,
frame.args[ 1 ] )
return r and "1" or ""
end -- p.isLang
p.isLangWiki = function ( frame )
-- Could this be a Wiki language version?
-- 1 -- code
local lucky, r = pcall( Multilingual.isLangWiki,
frame.args[ 1 ] )
return r and "1" or ""
end -- p.isLangWiki
p.kannDeutsch = function ( frame )
-- Kann man mit diesem Sprachcode deutsch verstehen?
-- 1 -- code
local r = Multilingual.kannDeutsch( frame.args[ 1 ] )
return r and "1" or ""
end -- p.kannDeutsch
p.userLang = function ( frame )
-- Which language does the current user prefer?
-- 1 -- space separated list of available ISO 639 codes
return Multilingual.userLang( frame.args[ 1 ], frame )
end -- p.userLang
p.Multilingual = function ()
return Multilingual
end -- p.Multilingual
return p