Module:LangSwitcher: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
mNo edit summary
mNo edit summary
Line 1: Line 1:
-- Module:LangSwitcher
-- Module:LangSwitcher
-- Language subpage switcher that outputs wikitext (no raw HTML).
-- Wikitext language switcher with normalized codes and builtin names.
-- 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 p = {}
Line 29: Line 14:
     end
     end
     for part in s:gmatch("([^,]+)") do
     for part in s:gmatch("([^,]+)") do
         local v = trim(part)
         local v = trim(part):lower()
         if v ~= "" then
         if v ~= "" then
             table.insert(t, v)
             table.insert(t, v)
Line 46: Line 31:
         local k, v = pair:match("^%s*([^=]+)%s*=%s*(.-)%s*$")
         local k, v = pair:match("^%s*([^=]+)%s*=%s*(.-)%s*$")
         if k and v then
         if k and v then
             out[trim(k)] = trim(v)
             out[trim(k):lower()] = trim(v)
         end
         end
     end
     end
Line 56: Line 41:
     local full = title.fullText
     local full = title.fullText
     local base, lang = full, nil
     local base, lang = full, nil
    -- Accept Base/xx or Base/pt-br (2+ letters/hyphens)
     local b, l = full:match("^(.-)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
     local b, l = full:match("^(.-)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
     if b and l then
     if b and l then
Line 72: Line 56:
     return string.format('[[%s|%s]]', page, label)
     return string.format('[[%s|%s]]', page, label)
end
end
local builtinNames = {
    en = "English",
    sv = "Svenska",
    da = "Dansk",
    nb = "Norsk bokmål",
    nn = "Nynorsk",
    no = "Norsk",
    fi = "Suomi",
    de = "Deutsch",
    fr = "Français",
    es = "Español",
    pt = "Português",
    ["pt-br"] = "Português (Brasil)",
    it = "Italiano",
    nl = "Nederlands",
    pl = "Polski",
    ru = "Русский",
    ja = "日本語",
    zh = "中文",
    ["zh-hans"] = "中文(简体)",
    ["zh-hant"] = "中文(繁體)",
    ko = "한국어",
}


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 langs = splitCSV(args.langs or args.languages or "en")
     local langs = splitCSV(args.langs or args.languages or "en")
     local labels = parseKVList(args.labels or "")
     local labels = parseKVList(args.labels or "")
Line 82: Line 89:
     local icon = args.icon or ""
     local icon = args.icon or ""


    -- Detect base/current
     local base, currentLang = getTitleParts()
     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()
     local defaultLang = trim(args.default or (langs[1] or "en")):lower()


    -- Label lookup with fallback to code
     local function labelFor(code)
     local function labelFor(code)
         return labels[code] or code
        code = (code or ""):lower()
         return labels[code] or builtinNames[code] or code
     end
     end


    -- Build ordered list, starting with defaultLang, then rest
     local seen = {}
     local seen = {}
     local ordered = {}
     local ordered = {}
Line 100: Line 103:
             return
             return
         end
         end
         local lc = code:lower()
         code = code:lower()
         if not seen[lc] then
         if not seen[code] then
             table.insert(ordered, lc)
             table.insert(ordered, code)
             seen[lc] = true
             seen[code] = true
         end
         end
     end
     end
Line 111: Line 114:
     end
     end


    -- Build wikitext pieces: "🌐 English • Svenska • Dansk"
     local pieces = {}
     local pieces = {}
     if icon ~= "" then
     if icon ~= "" then
Line 123: Line 125:
         if exists or showMissing then
         if exists or showMissing then
             local link = wikilink(target, labelFor(code))
             local link = wikilink(target, labelFor(code))
             local isActive
             local isActive = currentLang and (currentLang == code) or (code == defaultLang)
            if currentLang then
                isActive = (currentLang == code)
            else
                isActive = (code == defaultLang)
            end
             if isActive then
             if isActive then
                 link = "'''" .. link .. "'''"
                 link = "'''" .. link .. "'''"

Revision as of 13:09, 30 October 2025

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

-- Module:LangSwitcher
-- Wikitext language switcher with normalized codes and builtin names.

local p = {}

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

local function splitCSV(s)
    local t = {}
    if not s or s == "" then
        return t
    end
    for part in s:gmatch("([^,]+)") do
        local v = trim(part):lower()
        if v ~= "" then
            table.insert(t, v)
        end
    end
    return t
end

local function parseKVList(s)
    -- Parse "en=English,sv=Svenska"
    local out = {}
    if not s or s == "" then
        return out
    end
    for pair in s:gmatch("([^,]+)") do
        local k, v = pair:match("^%s*([^=]+)%s*=%s*(.-)%s*$")
        if k and v then
            out[trim(k):lower()] = trim(v)
        end
    end
    return out
end

local function getTitleParts()
    local title = mw.title.getCurrentTitle()
    local full = title.fullText
    local base, lang = full, nil
    local b, l = full:match("^(.-)/([A-Za-z%-][A-Za-z%-][A-Za-z%-]*)$")
    if b and l then
        base, lang = b, l:lower()
    end
    return base, lang, title
end

local function pageExists(page)
    local t = mw.title.new(page)
    return t and t.exists
end

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

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

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

    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 base, currentLang = getTitleParts()
    local defaultLang = trim(args.default or (langs[1] or "en")):lower()

    local function labelFor(code)
        code = (code or ""):lower()
        return labels[code] or builtinNames[code] or code
    end

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

    local pieces = {}
    if icon ~= "" then
        table.insert(pieces, "''" .. icon .. "'' ")
    end

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

    if #links == 0 then
        return ""
    end

    table.insert(pieces, table.concat(links, " • "))
    return table.concat(pieces)
end

return p