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 | ||
-- | -- Robust wikitext language switcher for Base and Base/xx pages. | ||
local p = {} | local p = {} | ||
| Line 23: | Line 23: | ||
local function parseKVList(s) | local function parseKVList(s) | ||
local out = {} | local out = {} | ||
if not s or s == "" then | if not s or s == "" then | ||
| Line 37: | Line 36: | ||
end | end | ||
-- Return base title text and current language code if page looks like Base/xx | |||
local function getTitleParts() | local function getTitleParts() | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
-- If the page has a subpage segment and it looks like a language code, split it | |||
if title.subpageText ~= title.text then | |||
local last = title.subpageText | |||
base, | 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) | |||
return baseTitle.fullText, code:lower(), title | |||
end | |||
end | |||
-- Otherwise, this is the base page | |||
return title.fullText, nil, title | |||
end | |||
-- Safely build the target page title for a given language code | |||
local function makeTarget(baseFullText, code, defaultLang) | |||
if code == defaultLang then | |||
return baseFullText | |||
end | |||
-- Use title objects to preserve namespace and special chars | |||
local baseTitle = mw.title.new(baseFullText) | |||
if not baseTitle then | |||
return baseFullText .. "/" .. code | |||
end | end | ||
return | local targetTitle = mw.title.new(baseTitle.fullText .. "/" .. code, baseTitle.namespace) | ||
return (targetTitle and targetTitle.fullText) or (baseFullText .. "/" .. code) | |||
end | end | ||
local function pageExists( | local function pageExists(fullTitleText) | ||
local t = mw.title.new( | local t = mw.title.new(fullTitleText) | ||
return t and t.exists | return t and t.exists | ||
end | end | ||
| Line 88: | Line 108: | ||
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 "" | ||
local debug = (args.debug or ""):lower() == "yes" | |||
local base, currentLang = getTitleParts() | local base, currentLang = getTitleParts() | ||
| Line 97: | Line 118: | ||
end | end | ||
local seen = {} | -- Order: defaultLang first, then the rest uniquely | ||
local seen, ordered = {}, {} | |||
local function add(code) | local function add(code) | ||
code = (code or ""):lower() | |||
if code ~= "" and not seen[code] then | |||
if not seen[code] then | |||
table.insert(ordered, code) | table.insert(ordered, code) | ||
seen[code] = true | seen[code] = true | ||
| Line 114: | Line 132: | ||
end | end | ||
local | local links, debugLines = {}, {} | ||
for _, code in ipairs(ordered) do | for _, code in ipairs(ordered) do | ||
local target = (code | local target = makeTarget(base, code, defaultLang) | ||
local exists = pageExists(target) | local exists = pageExists(target) | ||
if debug then | |||
table.insert(debugLines, string.format("code=%s target=%s exists=%s", code, target, tostring(exists))) | |||
end | |||
if exists or showMissing then | if exists or showMissing then | ||
local link = wikilink(target, labelFor(code)) | local link = wikilink(target, labelFor(code)) | ||
| Line 134: | Line 150: | ||
if #links == 0 then | if #links == 0 then | ||
if debug then | |||
return "LangSwitcher: no links; base=" .. base .. (currentLang and (" current=" .. currentLang) or " current=(none)") | |||
end | |||
return "" | return "" | ||
end | end | ||
local pieces = {} | |||
if icon ~= "" then | |||
table.insert(pieces, "''" .. icon .. "'' ") | |||
end | |||
table.insert(pieces, table.concat(links, " • ")) | table.insert(pieces, table.concat(links, " • ")) | ||
if debug and #debugLines > 0 then | |||
table.insert(pieces, "\n\n<small>" .. table.concat(debugLines, " • ") .. "</small>") | |||
end | |||
return table.concat(pieces) | return table.concat(pieces) | ||
end | end | ||
return p | return p | ||
Revision as of 13:17, 30 October 2025
Documentation for this module may be created at Module:LangSwitcher/doc
-- Module:LangSwitcher
-- Robust wikitext language switcher for Base and Base/xx pages.
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)
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
-- Return base title text and current language code if page looks like Base/xx
local function getTitleParts()
local title = mw.title.getCurrentTitle()
-- If the page has a subpage segment and it looks like a language code, split it
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)
return baseTitle.fullText, code:lower(), title
end
end
-- Otherwise, this is the base page
return title.fullText, nil, title
end
-- Safely build the target page title for a given language code
local function makeTarget(baseFullText, code, defaultLang)
if code == defaultLang then
return baseFullText
end
-- Use title objects to preserve namespace and special chars
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 pageExists(fullTitleText)
local t = mw.title.new(fullTitleText)
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 debug = (args.debug or ""):lower() == "yes"
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
-- Order: defaultLang first, then the rest uniquely
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(langs) do
add(code)
end
local links, debugLines = {}, {}
for _, code in ipairs(ordered) do
local target = makeTarget(base, code, defaultLang)
local exists = pageExists(target)
if debug then
table.insert(debugLines, string.format("code=%s target=%s exists=%s", code, target, tostring(exists)))
end
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
if debug then
return "LangSwitcher: no links; base=" .. base .. (currentLang and (" current=" .. currentLang) or " current=(none)")
end
return ""
end
local pieces = {}
if icon ~= "" then
table.insert(pieces, "''" .. icon .. "'' ")
end
table.insert(pieces, table.concat(links, " • "))
if debug and #debugLines > 0 then
table.insert(pieces, "\n\n<small>" .. table.concat(debugLines, " • ") .. "</small>")
end
return table.concat(pieces)
end
return p


