Module:LangSwitcher: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
m Protected "Module:LangSwitcher" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))
test
Line 3: Line 3:
local function trim(s) return (s or ""):gsub("^%s+",""):gsub("%s+$","") end
local function trim(s) return (s or ""):gsub("^%s+",""):gsub("%s+$","") end


-- Determine base page (without language suffix) and current language code if present
local function getTitleParts()
local function getTitleParts()
     local title = mw.title.getCurrentTitle()
     local title = mw.title.getCurrentTitle()
    -- If the page has a subpage segment, check if the last segment is a language code
     if title.subpageText ~= title.text then
     if title.subpageText ~= title.text then
         local last = title.subpageText
         local last = title.subpageText
        -- Allow 2+ letters and hyphens (e.g., sv, da, pt-br)
         local code = last:match("^([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
         local code = last:match("^([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
         if code then
         if code then
Line 19: Line 15:
         end
         end
     end
     end
    -- Fallback: try to split the full title manually on the last slash
     local full = title.fullText
     local full = title.fullText
     local base, code = full:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
     local base, code = full:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
Line 29: Line 23:
         end
         end
     end
     end
    -- Otherwise, we are on the base page
     return title.fullText, nil, title
     return title.fullText, nil, title
end
end


-- Build full target title for a given language code, relative to base
local function makeTarget(baseFullText, code, defaultLang)
local function makeTarget(baseFullText, code, defaultLang)
     code = (code or ""):lower()
     code = (code or ""):lower()
Line 46: Line 37:
     local targetTitle = mw.title.new(baseTitle.fullText .. "/" .. code, baseTitle.namespace)
     local targetTitle = mw.title.new(baseTitle.fullText .. "/" .. code, baseTitle.namespace)
     return (targetTitle and targetTitle.fullText) or (baseFullText .. "/" .. code)
     return (targetTitle and targetTitle.fullText) or (baseFullText .. "/" .. code)
end
local function exists(fullTitleText)
    local t = mw.title.new(fullTitleText)
    return t and t.exists
end
end


Line 57: Line 43:
end
end


-- Built-in human-readable names; extend as needed
local builtinNames = {
local builtinNames = {
     en="English", sv="Svenska", da="Dansk",
     en="English", sv="Svenska", da="Dansk",
Line 66: Line 51:
}
}


-- Render function (kept for explicit calls if desired)
function p.render(frame)
function p.render(frame)
     local args = frame:getParent() and frame:getParent().args or frame.args
    return p._main(frame)
end
 
-- Main entrypoint: used for direct invocation {{#invoke:LangSwitcher|Some Title}} or with named args.
function p._main(frame)
     local args = frame.args or {}
    -- If invoked positionally, first positional param is the display title.
    local displayTitle = nil
    if frame.args[1] and trim(frame.args[1]) ~= "" then
        displayTitle = trim(frame.args[1])
    elseif frame:getParent() and frame:getParent().args and frame:getParent().args[1] and trim(frame:getParent().args[1]) ~= "" then
        displayTitle = trim(frame:getParent().args[1])
    end
    -- Also accept named param displaytitle
    if not displayTitle and args.displaytitle and trim(args.displaytitle) ~= "" then
        displayTitle = trim(args.displaytitle)
    end


    -- Which code corresponds to the base page? Default to 'en'
     local defaultLang = "en" -- fixed to English
     local defaultLang = trim((args.default or "en")):lower()
     local icon = args.icon or ""
     local icon = args.icon or ""


    -- Resolve base and current language from the current title
     local base, currentLang = getTitleParts()
     local base, currentLang = getTitleParts()


     -- Candidate codes to scan; add more if you support them
     -- Configure languages to always show here:
     local candidates = {
     local candidates = {
         "en","sv","da","de","fr","es","fi","it","nl","pl","pt","pt-br","ru","ja","zh","zh-hans","zh-hant","ko"
         "en","sv","da","de","fr","es","fi","it","nl","pl","pt","pt-br","ru","ja","zh","zh-hans","zh-hant","ko"
     }
     }


    -- Order: default first, then other codes that exist as Base/xx
     local seen, ordered = {}, {}
     local seen, ordered = {}, {}
     local function add(code)
     local function add(code)
Line 91: Line 90:
     end
     end
     add(defaultLang)
     add(defaultLang)
    -- Scan from the base page, regardless of being on Base or Base/xx
     for _, code in ipairs(candidates) do
     for _, code in ipairs(candidates) do
         if code ~= defaultLang then
         if code:lower() ~= defaultLang then
             local target = makeTarget(base, code, defaultLang)
             add(code)
            if exists(target) then
                add(code)
            end
         end
         end
     end
     end


    -- Build the link list
     local links = {}
     local links = {}
     for _, code in ipairs(ordered) do
     for _, code in ipairs(ordered) do
Line 108: Line 101:
         local label = builtinNames[code] or code
         local label = builtinNames[code] or code
         local link = wikilink(target, label)
         local link = wikilink(target, label)
         local isActive = currentLang and (currentLang == code) or (code == defaultLang)
         local isActive = (currentLang and (currentLang == code)) or (code == defaultLang and not currentLang)
         if isActive then
         if isActive then
             link = "'''" .. link .. "'''"
             link = "'''" .. link .. "'''"
         end
         end
         table.insert(links, link)
         table.insert(links, link)
    end
    if #links == 0 then
        return ""
     end
     end


Line 124: Line 113:
     end
     end
     table.insert(out, table.concat(links, " • "))
     table.insert(out, table.concat(links, " • "))
    -- Set display title if requested.
    if displayTitle and displayTitle ~= "" then
        -- Prefer API via mw.title.setDisplayTitle (if available in this MW build).
        if mw.title.setDisplayTitle then
            -- setDisplayTitle expects only the title string.
            pcall(function() mw.title.setDisplayTitle(displayTitle) end)
        else
            -- Fallback: emit raw wikitext that sets DISPLAYTITLE (will be output on page).
            table.insert(out, 1, "{{DISPLAYTITLE:" .. displayTitle .. "}}\n")
        end
    end
     return table.concat(out)
     return table.concat(out)
end
end


return p
return p

Revision as of 14:28, 30 October 2025

Documentation for this module may be created at Module:LangSwitcher/doc

local p = {}

local function trim(s) return (s or ""):gsub("^%s+",""):gsub("%s+$","") end

local function getTitleParts()
    local title = mw.title.getCurrentTitle()
    if title.subpageText ~= title.text then
        local last = title.subpageText
        local code = last:match("^([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
        if code then
            local baseTitle = mw.title.new(title.baseText, title.namespace)
            if baseTitle then
                return baseTitle.fullText, code:lower(), title
            end
        end
    end
    local full = title.fullText
    local base, code = full:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
    if base and code then
        local baseTitle = mw.title.new(base, title.namespace)
        if baseTitle then
            return baseTitle.fullText, code:lower(), title
        end
    end
    return title.fullText, nil, title
end

local function makeTarget(baseFullText, code, defaultLang)
    code = (code or ""):lower()
    if code == defaultLang then
        return baseFullText
    end
    local baseTitle = mw.title.new(baseFullText)
    if not baseTitle then
        return baseFullText .. "/" .. code
    end
    local targetTitle = mw.title.new(baseTitle.fullText .. "/" .. code, baseTitle.namespace)
    return (targetTitle and targetTitle.fullText) or (baseFullText .. "/" .. code)
end

local function wikilink(page, label)
    return string.format('[[%s|%s]]', page, label)
end

local builtinNames = {
    en="English", sv="Svenska", da="Dansk",
    de="Deutsch", fr="Français", es="Español", fi="Suomi",
    it="Italiano", nl="Nederlands", pl="Polski", pt="Português",
    ["pt-br"]="Português (Brasil)", ru="Русский", ja="日本語",
    zh="中文", ["zh-hans"]="中文(简体)", ["zh-hant"]="中文(繁體)", ko="한국어",
}

-- Render function (kept for explicit calls if desired)
function p.render(frame)
    return p._main(frame)
end

-- Main entrypoint: used for direct invocation {{#invoke:LangSwitcher|Some Title}} or with named args.
function p._main(frame)
    local args = frame.args or {}
    -- If invoked positionally, first positional param is the display title.
    local displayTitle = nil
    if frame.args[1] and trim(frame.args[1]) ~= "" then
        displayTitle = trim(frame.args[1])
    elseif frame:getParent() and frame:getParent().args and frame:getParent().args[1] and trim(frame:getParent().args[1]) ~= "" then
        displayTitle = trim(frame:getParent().args[1])
    end
    -- Also accept named param displaytitle
    if not displayTitle and args.displaytitle and trim(args.displaytitle) ~= "" then
        displayTitle = trim(args.displaytitle)
    end

    local defaultLang = "en" -- fixed to English
    local icon = args.icon or ""

    local base, currentLang = getTitleParts()

    -- Configure languages to always show here:
    local candidates = {
        "en","sv","da","de","fr","es","fi","it","nl","pl","pt","pt-br","ru","ja","zh","zh-hans","zh-hant","ko"
    }

    local seen, ordered = {}, {}
    local function add(code)
        code = (code or ""):lower()
        if code ~= "" and not seen[code] then
            table.insert(ordered, code)
            seen[code] = true
        end
    end
    add(defaultLang)
    for _, code in ipairs(candidates) do
        if code:lower() ~= defaultLang then
            add(code)
        end
    end

    local links = {}
    for _, code in ipairs(ordered) do
        local target = makeTarget(base, code, defaultLang)
        local label = builtinNames[code] or code
        local link = wikilink(target, label)
        local isActive = (currentLang and (currentLang == code)) or (code == defaultLang and not currentLang)
        if isActive then
            link = "'''" .. link .. "'''"
        end
        table.insert(links, link)
    end

    local out = {}
    if icon ~= "" then
        table.insert(out, "''" .. icon .. "'' ")
    end
    table.insert(out, table.concat(links, " • "))

    -- Set display title if requested.
    if displayTitle and displayTitle ~= "" then
        -- Prefer API via mw.title.setDisplayTitle (if available in this MW build).
        if mw.title.setDisplayTitle then
            -- setDisplayTitle expects only the title string.
            pcall(function() mw.title.setDisplayTitle(displayTitle) end)
        else
            -- Fallback: emit raw wikitext that sets DISPLAYTITLE (will be output on page).
            table.insert(out, 1, "{{DISPLAYTITLE:" .. displayTitle .. "}}\n")
        end
    end

    return table.concat(out)
end

return p