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 | -- Language subpage switcher that outputs wikitext (no raw HTML). | ||
-- Usage: | -- Usage: | ||
-- {{#invoke:LangSwitcher|render | -- {{#invoke:LangSwitcher|render | ||
-- | langs = en,sv,da | -- | langs = en,sv,da | ||
-- | labels = en=English,sv=Svenska,da=Dansk | -- | labels = en=English,sv=Svenska,da=Dansk | ||
-- | default = en | |||
-- | show_missing = yes | |||
-- | icon = 🌐 | -- | icon = 🌐 | ||
-- }} | -- }} | ||
-- | -- | ||
-- Behavior: | -- 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 30: | Line 31: | ||
local v = trim(part) | local v = trim(part) | ||
if v ~= "" then | if v ~= "" then | ||
table.insert(t, v) | table.insert(t, v) | ||
end | end | ||
end | end | ||
| Line 55: | Line 56: | ||
local full = title.fullText | local full = title.fullText | ||
local base, lang = full, nil | local base, lang = full, nil | ||
-- Accept | -- 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 63: | Line 64: | ||
end | end | ||
local function | local function pageExists(page) | ||
local t = mw.title.new(page) | local t = mw.title.new(page) | ||
return t and t.exists | return t and t.exists | ||
end | end | ||
local function | local function wikilink(page, label) | ||
return string.format('[[%s|%s]]', page, label) | return string.format('[[%s|%s]]', page, label) | ||
end | end | ||
| Line 79: | Line 76: | ||
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 "") | ||
local showMissing = (args.show_missing or ""):lower() == "yes" | 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() | 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 | return labels[code] or code | ||
end | end | ||
-- Build ordered list, starting with defaultLang | -- Build ordered list, starting with defaultLang, then rest | ||
local seen = {} | local seen = {} | ||
local ordered = {} | local ordered = {} | ||
local function add(code) | local function add(code) | ||
if not code or code == "" then | if not code or code == "" then | ||
| Line 107: | Line 106: | ||
end | end | ||
end | end | ||
add(defaultLang) | add(defaultLang) | ||
for _, code in ipairs(langs) do | for _, code in ipairs(langs) do | ||
| Line 113: | Line 111: | ||
end | end | ||
local | -- Build wikitext pieces: "🌐 English • Svenska • Dansk" | ||
local pieces = {} | |||
if icon ~= "" then | |||
table.insert(pieces, "''" .. icon .. "'' ") | |||
end | |||
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 = (code == defaultLang) and base or (base .. "/" .. code) | ||
local pageExists | local exists = pageExists(target) | ||
if exists or showMissing then | |||
if | local link = wikilink(target, labelFor(code)) | ||
local isActive | local isActive | ||
if currentLang then | if currentLang then | ||
| Line 126: | Line 129: | ||
isActive = (code == defaultLang) | isActive = (code == defaultLang) | ||
end | end | ||
if isActive then | if isActive then | ||
link = "'''" .. link .. "'''" | |||
end | end | ||
table.insert(links, link) | |||
table.insert( | |||
end | end | ||
end | end | ||
if # | if #links == 0 then | ||
return "" | return "" | ||
end | end | ||
table.insert(pieces, table.concat(links, " • ")) | |||
return table.concat(pieces) | |||
table.insert( | |||
return table.concat( | |||
end | end | ||
return p | return p | ||
Revision as of 13:06, 30 October 2025
Documentation for this module may be created at Module:LangSwitcher/doc
-- Module:LangSwitcher
-- 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 splitCSV(s)
local t = {}
if not s or s == "" then
return t
end
for part in s:gmatch("([^,]+)") do
local v = trim(part)
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)] = trim(v)
end
end
return out
end
local function getTitleParts()
local title = mw.title.getCurrentTitle()
local full = title.fullText
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%-]*)$")
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
function p.render(frame)
local args = frame:getParent() and frame:getParent().args or frame.args
-- Inputs
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 ""
-- Detect base/current
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
local function labelFor(code)
return labels[code] or code
end
-- Build ordered list, starting with defaultLang, then rest
local seen = {}
local ordered = {}
local function add(code)
if not code or code == "" then
return
end
local lc = code:lower()
if not seen[lc] then
table.insert(ordered, lc)
seen[lc] = true
end
end
add(defaultLang)
for _, code in ipairs(langs) do
add(code)
end
-- Build wikitext pieces: "🌐 English • Svenska • Dansk"
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
if currentLang then
isActive = (currentLang == code)
else
isActive = (code == defaultLang)
end
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


