Module:I18n

-- -- I18n storage module for FANDOM. -- @module     i18n -- @version    0.7.0 -- @usage      require("Dev:I18n") -- @author     KockaAdmiralac -- @author     Speedit -- @release    alpha; untested -- @todo       Fallbacks and unit testing.

-- Module package. local i18n = {} -- I18n datastore class. -- @classmod   i18nd local i18nd = {} -- Invocation frame cache. local frameCache -- Module variables. local title = mw.title.getCurrentTitle

-- Datastore language setter to user language. -- @name       i18nd:useUserLang -- @param      {table} frame Frame invocation. function i18nd.useUserLang(i18nd, frame) if frame then frameCache = frame -- Cache frame object. end i18nd.defaultLang = frameCache and i18n.getLang(frame) or i18nd.defaultLang end

-- Datastore language setter to user language. -- @name       i18nd:useContentLang function i18nd.useContentLang(i18nd) i18nd.defaultLang = mw.language.getContentLanguage:getCode end

-- Datastore language setter to specificed language. -- @name       i18nd:useLang -- @param      {string} lang Language code to use. function i18nd.useLang(i18nd, lang) i18nd.defaultLang = lang and mw.language.isValidCode(lang) == true and lang or       i18nd.defaultLang end

-- Datastore message utility. -- @param      {table} data Data table for i18n messages. -- @param      {string} key Message key to return. -- @return     {string} Message key or ' '. -- @todo       Better fallback system with Module:Fallbacklist. function i18nd.msg(i18nd, key, ...) if i18nd and key then -- Language handling. local defaultLang = i18nd.defaultLang or 'en' local moduleLang = frameCache and i18n.getLang(frameCache) or           i18n.getLang -- Message data. local msgData = (i18nd._messages[moduleLang] or {})[key] and i18nd._messages[moduleLang] or           (i18nd._messages[defaultLang] or {})[key] and i18nd._messages[defaultLang] or           i18nd._messages.en        local msg = msgData[key] -- Handling argument substitution from Scribunto. if type((arg or {})[1]) == table then arg  = arg[1] arg.n = #arg[1] end -- Handling argument substitution from Lua. if msg and (arg.n or 0) > 0 then msg = i18n.handleArgs(msg, arg) end return type(msg) ~= 'nil' and msg or           mw.text.nowiki('<' .. key .. '>') else error('missing arguments in i18nd.msg') end end

-- Argument substitution as $n where n > 0. -- @param      {string} msg Message to substitute arguments into. -- @param      {table} arg Arguments table to substitute. -- @return     {string} Resulting message. function i18n.handleArgs(msg, arg) for i, a in ipairs(arg) do       local ptn = '%$' .. i       msg = type(i) == 'number' and string.gsub(msg, ptn, a) or           msg end return msg end

-- Language code function. -- @param      {table} frame Frame table from invocation. -- @return     {string} lang Language code. function i18n.getLang(frame) -- Cache frame object. if frame then frameCache = frame end -- Default language code. local lang = defaultLang -- Language argument test. if frameCache.args and frameCache.args.lang and mw.language.isValidCode(frameCache.args.lang) == true then lang = frameCache.args.lang -- Subpage language test. elseif title.isSubpage then local text = title.subpageText local lang = mw.language.isValidCode(text) and text or lang -- User language fallback. elseif frameCache then lang = frameCache:preprocess('') -- Content language fallback. else lang = mw.language.getContentLanguage:getCode end return lang end

-- I18n message datastore loader. -- @param      {string} source ROOTPAGENAME of target i18n submodule. -- @return     {table} i18n I18n datastore instance. function i18n.loadMessages(source, frame) if type(source) == 'string' and source ~= '' then -- Cache frame object. if frame then frameCache = frame end -- Instantiate datastore. local data = {} setmetatable(data, i18nd) data.__index = i18nd -- Set default language. data.defaultLang = frameCache and i18n.getLang(frameCache) or           i18n.getLang -- Load messages. data._messages = mw.loadData('Module:' .. source .. '/i18n') -- Return datastore instance. return data else error('no source supplied') end end

-- I18n message function. -- @param      {table} frame Frame table from invocation. -- @param      {string} frame.args[1] ROOTPAGENAME of i18n submodule. -- @param      {string} frame.args[2] Key of i18n message. -- @return     {string} msg I18n message in localised language. -- @todo       Add support for argument substitution. function i18n.getMsg(frame) if frame and frame.args and #frame.args >= 2 then -- Cache frame. if frame then frameCache = frame end -- Read frame arguments. local source = frameCache.args[1] local key = frameCache.args[2] -- Pass through extra arguments. local extArgs = {} if #frameCache.args >= 3 then for i, a in ipairs(frameCache.args) do               if type(i) == 'number' then extArgs[i-2] = a               end end end -- Load message data. local i18nd = i18n.loadMessages(source, frameCache) -- Return message. return i18nd:msg(key, extArgs) else error('missing arguments in i18n.getMsg') end end

return i18n