Module:LangSwitcher: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
mNo edit summary
No edit summary
 
(29 intermediate revisions by 3 users not shown)
Line 1: Line 1:
-- Module:LangSwitcher
local p = {}
-- Language subpage switcher that outputs wikitext (no raw HTML).
-- Usage:
--  {{#invoke:LangSwitcher|render
--      | langs  = en,sv,da
--      | labels = en=English,sv=Svenska,da=Dansk
--      | default = en
--      | show_missing = yes
--      | icon = 🌐
--  }}
--
-- Behavior:
-- * Base page (no suffix) represents the default language (e.g., 'en').
-- * Subpages at Base/xx (e.g., /sv, /da) are translations.
-- * Lists languages from |langs=, bolds the active language, links to each page.
-- * If show_missing = yes, includes languages whose page doesn’t exist yet (redlinks).
-- * Supports hyphenated codes like pt-br.


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


local function trim(s)
local function getTitleParts(link)
     return (s or ""):gsub("^%s+", ""):gsub("%s+$", "")
     local title = mw.title.getCurrentTitle()
end


local function splitCSV(s)
    if link then
    local t = {}
        local link = trim(link) or ""
    if not s or s == "" then
        if link ~= "" then
        return t
            local name, code = link:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
    end
            if name and code then
    for part in s:gmatch("([^,]+)") do
                return name, code:lower(), title
        local v = trim(part)
            end
        if v ~= "" then
            table.insert(t, v)
         end
         end
     end
     end
    return t
end


local function parseKVList(s)
    if title.subpageText ~= title.text then
    -- Parse "en=English,sv=Svenska"
        local last = title.subpageText
    local out = {}
        local code = last:match("^([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
    if not s or s == "" then
        if code then
         return out
            local baseTitle = mw.title.new(title.baseText, title.namespace)
            if baseTitle then
                return baseTitle.fullText, code:lower(), title
            end
         end
     end
     end
     for pair in s:gmatch("([^,]+)") do
     local full = title.fullText
        local k, v = pair:match("^%s*([^=]+)%s*=%s*(.-)%s*$")
    local base, code = full:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
        if k and v then
    if base and code then
            out[trim(k)] = trim(v)
        local baseTitle = mw.title.new(base, title.namespace)
        if baseTitle then
            return baseTitle.fullText, code:lower(), title
         end
         end
     end
     end
     return out
     return title.fullText, nil, title
end
end


local function getTitleParts()
local function makeTarget(baseFullText, code, defaultLang)
     local title = mw.title.getCurrentTitle()
     code = (code or ""):lower()
     local full = title.fullText
     if code == defaultLang then
    local base, lang = full, nil
        return baseFullText
     -- Accept Base/xx or Base/pt-br (2+ letters/hyphens)
     end
     local b, l = full:match("^(.-)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
     local baseTitle = mw.title.new(baseFullText)
     if b and l then
     if not baseTitle then
         base, lang = b, l:lower()
         return baseFullText .. "/" .. code
     end
     end
     return base, lang, title
     local targetTitle = mw.title.new(baseTitle.fullText .. "/" .. code, baseTitle.namespace)
end
     return (targetTitle and targetTitle.fullText) or (baseFullText .. "/" .. code)
 
local function pageExists(page)
    local t = mw.title.new(page)
     return t and t.exists
end
end


Line 72: Line 53:
     return string.format('[[%s|%s]]', page, label)
     return string.format('[[%s|%s]]', page, label)
end
end
local builtinNames = {
    en="English",
es="Español",
it="Italiano",
fr="Français",
de="Deutsch",
["pt-br"]="Português (Brasil)",
ja="日本語",
ko="한국어",
pl="Polski",
cs="Čeština",
nl="Nederlands",
uk="Українська",
da="Dansk",
sv="Svenska",
tr="Türkçe",
hu="Magyar",
ru="Русский",
["zh-hans"]="中文(简体)",
["zh-hant"]="中文(繁體)",
}


function p.render(frame)
function p.render(frame)
     local args = frame:getParent() and frame:getParent().args or frame.args
     local args = frame:getParent() and frame:getParent().args or frame.args


    -- Inputs
     local defaultLang = "en" -- fixed to English
     local langs = splitCSV(args.langs or args.languages or "en")
    local labels = parseKVList(args.labels or "")
    local showMissing = (args.show_missing or ""):lower() == "yes"
     local icon = args.icon or ""
     local icon = args.icon or ""


    -- Detect base/current
     local base, currentLang = getTitleParts(frame.args[1])
     local base, currentLang = getTitleParts()
 
    -- Default language: code that maps to the base page (no suffix)
    local defaultLang = trim(args.default or (langs[1] or "en")):lower()


     -- Label lookup with fallback to code
     -- Edit this list to control which languages always appear, in desired order.
     local function labelFor(code)
     local candidates = {
         return labels[code] or code
         "en","pl","ru","fr","ja","zh-hans"
     end
     }


     -- Build ordered list, starting with defaultLang, then rest
     -- Order: default first, then listed candidates (excluding duplicate default)
     local seen = {}
     local seen, ordered = {}, {}
    local ordered = {}
     local function add(code)
     local function add(code)
         if not code or code == "" then
         code = (code or ""):lower()
            return
         if code ~= "" and not seen[code] then
        end
             table.insert(ordered, code)
        local lc = code:lower()
             seen[code] = true
         if not seen[lc] then
             table.insert(ordered, lc)
             seen[lc] = true
         end
         end
     end
     end
     add(defaultLang)
     add(defaultLang)
     for _, code in ipairs(langs) do
     for _, code in ipairs(candidates) do
         add(code)
         if code:lower() ~= defaultLang then
    end
            add(code)
 
        end
    -- Build wikitext pieces: "🌐 English • Svenska • Dansk"
    local pieces = {}
    if icon ~= "" then
        table.insert(pieces, "''" .. icon .. "'' ")
     end
     end


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


Line 140: Line 121:
     end
     end


     table.insert(pieces, table.concat(links, " • "))
     local out = {}
     return table.concat(pieces)
    if icon ~= "" then
        table.insert(out, "''" .. icon .. "'' ")
    end
    table.insert(out, table.concat(links, " • "))
     return '<div style="text-align:center; font-size:0.9em; margin-top:0.5em; margin-bottom:1em">' .. table.concat(out) .. '</div>'
end
end


return p
return p

Latest revision as of 18:51, 17 July 2026

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(link)
    local title = mw.title.getCurrentTitle()

    if link then
        local link = trim(link) or ""
        if link ~= "" then
            local name, code = link:match("^(.*)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
            if name and code then
                return name, code:lower(), title
            end
        end
    end

    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",
	es="Español",
	it="Italiano",
	fr="Français",
	de="Deutsch",
	["pt-br"]="Português (Brasil)",
	ja="日本語",
	ko="한국어",
	pl="Polski",
	cs="Čeština",
	nl="Nederlands",
	uk="Українська",
	da="Dansk",
	sv="Svenska",
	tr="Türkçe",
	hu="Magyar",
	ru="Русский",
	["zh-hans"]="中文(简体)",
	["zh-hant"]="中文(繁體)",
}

function p.render(frame)
    local args = frame:getParent() and frame:getParent().args or frame.args

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

    local base, currentLang = getTitleParts(frame.args[1])

    -- Edit this list to control which languages always appear, in desired order.
    local candidates = {
        "en","pl","ru","fr","ja","zh-hans"
    }

    -- Order: default first, then listed candidates (excluding duplicate default)
    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

    if #links == 0 then
        return ""
    end

    local out = {}
    if icon ~= "" then
        table.insert(out, "''" .. icon .. "'' ")
    end
    table.insert(out, table.concat(links, " • "))
    return '<div style="text-align:center; font-size:0.9em; margin-top:0.5em; margin-bottom:1em">' .. table.concat(out) .. '</div>'
end

return p