Modul:Multilingual: Unterschied zwischen den Versionen

Aus FreeWiki
Wechseln zu: Navigation, Suche
te>PerfektesChaos
(update)
te>PerfektesChaos
(2015-06-19)
Zeile 1: Zeile 1:
--[=[ 2014-11-28
+
local Multilingual = { suite  = "Multilingual",
Multilingual
+
                      serial = "2015-06-19" };
]=]
 
  
  
  
local Multilingual = { }
+
-- local globals
 
local Frame
 
local Frame
local Got = { }
+
 
local SelfLang
+
 
 +
 
 +
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 Got[ access ] == false then
+
     if type( Multilingual.ext ) ~= "table" then
     elseif not Got[ access ] then
+
        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
                 Got[ access ] = got
+
                 Multilingual.ext[ access ] = got
 
                 if type( got[ access ] ) == "function" then
 
                 if type( got[ access ] ) == "function" then
                     Got[ access ] = got[ access ]()
+
                     Multilingual.ext[ access ] = got[ access ]()
 
                 end
 
                 end
 
             end
 
             end
            got = "Module" .. access .. " invalid"
 
 
         end
 
         end
         if type( Got[ access ] ) ~= "table" then
+
         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 Got[ access ]
+
     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 codes
+
             local slang = favorite()
             if not SelfLang then
+
            r = find( seek, slang )
                 SelfLang = mw.language.getContentLanguage():getCode()
+
             if not r  and  slang ~= "en" then
 +
                 r = find( seek, "en" )
 
             end
 
             end
            codes = mw.language.fetchLanguageNames( SelfLang, "all" )
 
            for k, v in pairs( codes ) do
 
                if mw.ustring.lower( v ) == seek then
 
                    r = k
 
                    break -- for k, v
 
                end
 
            end -- for k, v
 
 
         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
                    if active then
+
                        r = slang
                        local cnf = fetch( "Multilingual/config", true )
+
                    else
                        if cnf then
+
                        r = Multilingual.getName( slang, alien )
                            if not frame then
+
                        if active then
                                if not Frame then
+
                            local cnf = fetch( "Multilingual/config",
                                    Frame = mw.getCurrentFrame()
+
                                              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
                                frame = Frame
 
                            end
 
                            slot = cnf.getLink( slang, frame )
 
                            if slot then
 
                                slot = fetch( "WLink" ).getTarget( slot )
 
                            else
 
                                lapsus = alert
 
 
                             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 = nil
+
                 slang = ask:lower()
 
             elseif slang == "!" then
 
             elseif slang == "!" then
                 if not SelfLang then
+
                 slang = favorite()
                    SelfLang = mw.language.getContentLanguage():getCode()
 
                end
 
                slang = SelfLang
 
 
             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
         frame = mw.getCurrentFrame()
+
         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 = mw.language.getContentLanguage():getCode()
+
         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

Die Dokumentation für dieses Modul kann unter Modul:Multilingual/Doku erstellt werden

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