Module:Dir

From Chaosvermittlung Wiki
Jump to navigation Jump to search

-- This module implements Template:Dir.

-- local rtlOverrides = mw.loadData('Module:Dir/RTL overrides') -- !!! mw.loadData() is currently broken, it does NOT load anything local rtlOverrides = require('Module:Dir/RTL overrides') local p = {}

local function trim(s)

   if s and s ~=  then s = tostring(s):match('^%s*(.-)%s*$') end
   if s ==  then return nil end
   return s

end

function p.rtlLangs(isRTL)

   if isRTL == nil then isRTL = true end
   return rtlOverrides[isRTL] or {}

end

function p.isRTL(code)

   if type(code) ~= 'string' then return nil end
   local v = rtlOverrides[code] -- very fast and not limited in the number of supported languages
   if v ~= nil then return v end -- return it if mapped, otherwise use MediaWiki library:
   local success, ret = pcall(function ()
       return mw.language.new(code):isRTL() -- expensive and limited to 20 languages per MediaWiki instance
   end)
   return success and ret

end

function p.select(code, rtl, ltr)

   if p.isRTL(code) then
       return rtl
   else
       return ltr
   end

end

-- Used via a template wikitext if ltr -- which just calls ltr, the 3 parameters are automatically trimmed function p.main(frame)

   local args = frame:getParent().args -- Parameters used to transclude Template:Dir
   local code = trim(args[1])
   local rtl = trim(args[2]) or 'rtl'
   local ltr = trim(args[3]) or 'ltr'
   return p.select(code, rtl, ltr)

end

setmetatable(p, { quickTests = function ()

   local rtlLangs = p.rtlLangs(true)
   local ltrLangs = p.rtlLangs(false)
   -- utility: reverse order iterator on sequences
   local function revipairs(t)
       return function(t, i)
           i = i - 1
           local v = t[i]
           if v == nil then return nil end
           return i, v
       end, t, #t + 1
   end
   -- Basic check of data format
   local function checkLangs(name, langs)
       for k, lang in pairs(langs) do
           assert(type(k) == 'number' and k == math.floor(k)
               and type(lang) == 'string' and #lang >= 2 and #lang <= 16
               and lang:find('^[a-z][%-0-9a-z]*[0-9a-z]$') == 1,
               ": Invalid sequence of language codes, " .. name .. "['" .. k .. "'] = '" .. lang .. "'")
       end
       return true
   end
   local ok, msg
   ok, msg = pcall(checkLangs, 'rtlLangs', rtlLangs)
   if not ok then return false, msg end
   ok, msg = pcall(checkLangs, 'ltrLangs', ltrLangs)
   if not ok then return false, msg end
   -- Build inverse maps of languages having each direction
   local isrtl, isltr = {}, {}
   for _, lang in ipairs(rtlLangs) do isrtl[lang] = true end
   for _, lang in ipairs(ltrLangs) do isltr[lang] = true end
   -- Check conflicts using the two inverse maps
   for _, lang in ipairs(rtlLangs) do
       if isltr[lang] then return false, ": Direction conflict for '" .. lang .. "'" end
   end
   for _, lang in ipairs(ltrLangs) do
       if isrtl[lang] then return false, ": Direction conflict for '" .. lang .. "'" end
   end
   -- Log missing languages (allows filling the tables above) according to MediaWiki internal data
   local knownLangs = mw.language.fetchLanguageNames()
   for lang, _ in pairs(knownLangs) do
        if rtlOverrides[lang] == nil then -- only if we still don't have data for this language
            -- Note: we cannot check more than 20 languages at once, then MediaWiki raises an error.
            -- So this test only runs on the Lua console, where you can update the tables at top.
            ok, value = pcall(function() return tostring(mw.language.new(lang):isRTL()) end)
            mw.log("Missing direction for language '" .. lang .. "', MediaWiki returns '" .. value .. "'")
        end
   end
   -- Sort and deduplicate language code values (by scanning backward) for data cleanup
   table.sort(rtlLangs)
   table.sort(ltrLangs)
   for i, lang in revipairs(rtlLangs) do
       if rtlLangs[i - 1] == rtlLangs[i] then table.remove(rtlLangs, i) end
   end
   for i, lang in revipairs(ltrLangs) do
       if ltrLangs[i - 1] == ltrLangs[i] then table.remove(ltrLangs, i) end
   end
   -- Final presentation of current lists, sorted and deduplicated
   mw.log("local rtlLangs = { '" .. table.concat(rtlLangs, "', '") .. "' }")
   mw.log("local ltrLangs = { '" .. table.concat(ltrLangs, "', '") .. "' }")
   return true

end }) --[==[ Enter this to run tests in the Lua console: =getmetatable(p).quickTests() --]==]

return p