Документация за този модул може да бъде създадена на Модул:Langs/doc

require('Module:No globals')
local ll = mw.loadData('Module:Langs/data')
local langs = ll.langs
local variants = ll.variants

local p = {}
local allLangVariantMsgs
local getLangsAsJson

local trim
trim = function (strToTrim)
   if not strToTrim then return '' end
   return string.gsub( string.gsub( strToTrim, '^%s+', '' ), '%s+$', '' )
end


local selectMsgs
selectMsgs = function (allMsgs, userLang)
   local msgs = allMsgs[userLang]
   if msgs == nil then -- TODO: check each message
      msgs = allMsgs['bg']
   end
   return msgs
end


local function getByCode(code)
   for i, v in ipairs(langs) do
      if v[1][1] == code then
         return v
      end
   end
   return nil
end


function p.getByCode_(code)
   return getByCode(code)
end


-- codeToName(args) :
--  args.code is the language code (required)
--  args.toLang is the user lang code
--  if any value is 'definite', 'я' is added to the string
--  if any value is 'langWord', ' език' is added to the string
function p.codeToName_ (args)
   args = args or {}
   local code = trim( args.code )
   assert(code ~= '', "code is nil or empty!")
   local toLang = trim( args.toLang )
   if toLang ~= 'en' then toLang = 'bg' end
   local langObj = getByCode(code)
   if not langObj then return nil end
   local langName = langObj[ toLang == 'en' and 2 or 3 ][1]
   local str = langName
   local addLangWord = false
   local definite = false

   for i, v in ipairs(args) do
      if trim( v ) == 'langWord' then addLangWord = true
      elseif trim( v ) == 'definite' then definite = true
      end
   end

   return str
end


function p.codeToName(frame)
   assert(frame.args.code and frame.args.code ~= '', "'code' argument missing or empty")
   codeToName(frame.args)
end


   --[[
function p.idLang(lang, userLang)
   local mainName = ''
   local mainCode = ''
   local found = false
   local lNames
   local lang = string.ulower(lang)

   for mainCode_i, v in pairs(p.langs) do
      lNames = v[1]

      for __, i_name in pairs(lNames) do
         if i_name == lang then
            mainName = lNames[1]
            mainCode = mainCode_i
            found = true
            break
         end
      end

      if found then break end
   end
   return mainCode, mainName
end

function p.langSectionHeading(langCode)
   local str = '<div style="clear:both;"></div>\n== ' .. p.codeToName(langCode).. ' =='
end

]]


local tableToJsonArrayStr
tableToJsonArrayStr = function (aTable)
   local str = ''
   for i, v in ipairs(aTable) do  -- can't use table.concal w/ loadData() tables
      str = str .. ( str == '' and '' or ', ' ) .. '"' .. v .. '"'
   end
   return '[' .. str .. ']'
end


function p.getLangsAsJson(frame)
   local userLang = trim( frame.args.userLang )
   local key = trim( frame.args.key )
   return getLangsAsJson( key, userLang )
end


getLangsAsJson = function (key, userLang)
   local bgNames, enNames
   local codesStr, enNamesStr, bgNamesStr
   local asArray = key == ''
   local str = (asArray and '[' or '{') .. ' \n'

   for i, langObj in ipairs(langs) do
      codesStr = tableToJsonArrayStr( langObj[1] )
      enNamesStr = tableToJsonArrayStr( langObj[2] )
      bgNamesStr = tableToJsonArrayStr( langObj[3] )
      str = str .. (not asArray and '"' .. langObj[1][1] .. '": ' or '') .. '{ "codes": ' .. codesStr
         .. ', "enNames": ' .. enNamesStr
         .. ', "bgNames": ' .. bgNamesStr .. ' }' .. ',\n'
   end
   str = str:sub(1, #str - 2) -- remove final ', '

   str = str .. '\n' .. (asArray and ']' or '}')
   return str
end


function p.langVariantName(frame)
   langVariantName( trim(frame.args[1]), trim(frame.args.userLang) )
end


local langVariantName
langVariantName = function (code, userLang)
   if code == nil or code == '' then return '' end

   local langVariants = selectMsgs(variants, userLang)
   return langVariants[code] or ''
end


return p