Module:Template translation/sandbox2

Module documentation
-----
-- Private functions

--- Get the translatable (main) page from arguments or guess
-- 
-- @private
-- 
-- @param args table Arguments supplied to the current frame
-- @return Title Title of the translatable page (possible not existing)
function getTranslatablePage(args)
    
    local title
    local template = args['template']
    local namespace = args['namespace'] or ''
    
    if( namespace ~= '' ) -- Checks for namespace parameter for custom ns.
    then
        title = mw.title.new(template, namespace) -- Costly
    else -- Supposes that set page is a template
        title = mw.title.new(template, 'Template') -- Costly
        if( title.id == 0 )
        then -- not found in the Template namespace, assume the main namespace
             -- (for backward compatibility with "Template:Translatable template")
            title = mw.title.new(template, '') -- Costly
        end
    end
    return title
end

--- Get the translated page in the nearest language specified
-- 
-- @private
-- Require MediaWiki 1.23
-- 
-- @param title Title Title of the main translatable page
-- @param code string Known language code for the requested translation
-- @return Title,string Title of the best translation (possibly not existing), and the language code
function getTranslationFor(title,code)
    
    local newtitle, fallbacks, i
    
    -- Create the fallback language sequence: code, MediaWiki fallback, content language, base page
    fallbacks = mw.language.getFallbacksFor(code)
    fallbacks[math.max(1,#fallbacks)] = mw.language.getContentLanguage():getCode()
    if( code ~= mw.language.getContentLanguage():getCode() ) then
        table.insert(fallbacks,1,code)
    end
    
    -- Check the existence of each potential translation, exit when found
    for i, code in ipairs( fallbacks ) do
        newtitle = mw.title.new( title.text .. '/' .. code, title.nsText ) -- Costly
        if( newtitle.id ~= 0 )
        then
            return newtitle, code
        end
    end
    return title, mw.language.getContentLanguage():getCode()
end


-----
-- Public functions

local this = {}

--- Return the subpage if it is a valid language code, else the default text.
-- 
-- (mainly used internally)
-- 
-- @param lang string Text to be tested if it is a language code
-- @param default string Text in the case lang is not a language code
-- @return string Language code or input default string
function this.checkLanguage(lang,default)
    
    if( mw.language.isKnownLanguageTag(lang) )
    then
        return lang
    end
    
    return default
end

--- Get the last subpage of the current page if it is a translation, else empty string.
-- 
-- @return string Language code or empty string
function this.getLanguageSubpage()
    local subpage = mw.title.getCurrentTitle().subpageText
    return this.checkLanguage(subpage, '')
end

--- Get the last subpage of the current frame if it is a translation, else empty string.
-- 
--   (not used locally)
-- 
-- @param frame Frame Current frame
-- @return string Language code or empty string
function this.getFrameLanguageSubpage(frame)
    local titleparts = mw.text.split(frame:getParent():getTitle(), '/')
    local subpage = titleparts[#titleparts]
    return this.checkLanguage(subpage, '')
end

--- Get the language of the current page.
-- 
--   (not used locally)
-- 
-- @return string Language code
function this.getLanguage()
    local subpage = mw.title.getCurrentTitle().subpageText
    return this.checkLanguage(subpage, mw.language.getContentLanguage():getCode())
end

--- Get the language of the current frame.
-- 
--   (not used locally)
-- 
-- @param frame Frame Current frame
-- @return string Language code
function this.getFrameLanguage(frame)
    local titleparts = mw.text.split(frame:getParent():getTitle(), '/')
    local subpage = titleparts[#titleparts]
    return this.checkLanguage(subpage, mw.language.getContentLanguage():getCode())
end

--- Fallback language for a given title
-- 
--   (not used locally)
-- 
-- @param frame Frame Current frame, must contain the arguments 'title' and 'code'
-- @return string Best language code
function this.getFallbackLanguage(frame)
    
    -- Create the title object in the Template namespace for backward compatibility with Template:Fallback
    local title = mw.title.new( frame.args['title'], 'Template' )
    
    -- Get the best translation
    local code
    title, code = getTranslationFor( title, frame.args['code'] )
    
    return code
end

--- Expands the best translation of a given template
-- 
-- If on a translation subpage (like Foobar/de), this function renders
--  a given template in the same language, if the translation is available.
--  Otherwise, the template is rendered in its nearest language, and in
--  ultimate case in the content language.
--  This is mainly used in the current implementation of "Template:Translatable template".
-- 
-- @param frame Frame Current frame, must contain the argument 'template' and can contain the argument 'namespace'
-- @return string Expanded template
function this.renderTranslatedTemplate(frame)
    
    -- Get the specified pagename (arguments 'namespace' and 'template' of the frame), or
    --  check whether the pagename is actually in the Template namespace, or
    --  if we're transcluding a main-namespace page (backward compatibility of Template:TNT).
    local title = getTranslatablePage(frame.args)
    
    -- Get the last subpage and get the best translation.
    title = getTranslationFor( title, this.getLanguage() )
    
    -- Copy args pseudo-table to a proper table so we can feed it to expandTemplate.
    -- Then render the pagename.
    local k, v
    local arguments = {}
    for k, v in pairs((frame:getParent() or {}).args) do
        -- numbered args >= 1 need to be shifted
        if( type(k) == 'number' and k >= 2 )
        then
            arguments[k - 1] = v
        else
            arguments[k] = v
        end
    end
    arguments['template'] = nil
    arguments['namespace'] = nil
    
    -- Final rendering of the translated template
    return frame:expandTemplate{ title = title.prefixedText, args = arguments }
end

return this