Roovet Articles
Module:Lang/data
Documentation for this module may be created at Module:Lang/data/doc
-- Module:Lang/data (metatable-free & boolean-safe)
-- Goal: Provide plain tables for Module:Lang while tolerating minimal IANA stubs.
----------------------------------------------------------------
-- Safe loader: returns a table or {} (never errors out)
----------------------------------------------------------------
local function safeload(name)
local ok, t = pcall(mw.loadData, name)
if ok and type(t) == "table" then
return t
end
return {}
end
----------------------------------------------------------------
-- Deep copy that strips metatables everywhere (keys & values)
----------------------------------------------------------------
local function deep_plain_copy(x, seen)
if type(x) ~= "table" then
return x
end
seen = seen or {}
if seen[x] then
return seen[x]
end
local r = {}
seen[x] = r
for k, v in pairs(x) do
local nk = deep_plain_copy(k, seen)
local nv = deep_plain_copy(v, seen)
r[nk] = nv
end
return r
end
----------------------------------------------------------------
-- Upgrade any non-table entry (true/false/strings/numbers) to {}
-- so downstream code can safely index r[key][...]
----------------------------------------------------------------
local function upgrade_scalars_to_tables(t)
local out = {}
for k, v in pairs(t) do
if type(v) == "table" then
out[k] = upgrade_scalars_to_tables(v)
else
-- Turn booleans/strings/numbers into an empty info table.
-- (Keeps API simple/safe for callers that expect tables.)
out[k] = {}
end
end
return out
end
----------------------------------------------------------------
-- Load slice, deep-strip metatables, then normalize scalars
----------------------------------------------------------------
local function fetch_iana(slice_name, fallback)
-- 1) load (may be read-only with metatable)
local raw = safeload(slice_name)
-- 2) deep copy into plain tables (no metatables)
local plain = deep_plain_copy(raw)
-- 3) if empty, use fallback; else normalize booleans/scalars
local has_any = next(plain) ~= nil
if not has_any then
return fallback
end
return upgrade_scalars_to_tables(plain)
end
----------------------------------------------------------------
-- Minimal sensible fallbacks (if your stubs are missing)
----------------------------------------------------------------
local fallback_languages = {
en = {}, nl = {}, fr = {}, de = {}, es = {}, pt = {}, it = {},
ru = {}, ar = {}, zh = {}, ja = {}, ko = {}
}
local fallback_scripts = {
Latn = {}, Cyrl = {}, Arab = {}, Hans = {}, Hant = {}, Hebr = {}, Deva = {}, Grek = {}
}
local fallback_regions = {
US = {}, GB = {}, UK = {}, CA = {}, AU = {}, NZ = {}, IE = {},
BE = {}, NL = {}, FR = {}, DE = {}, LU = {}, CH = {}, AT = {}, IT = {},
ES = {}, PT = {}
}
----------------------------------------------------------------
-- Assemble IANA slices
----------------------------------------------------------------
local iana_languages = fetch_iana("Module:Lang/data/iana languages", fallback_languages)
local iana_scripts = fetch_iana("Module:Lang/data/iana scripts" , fallback_scripts)
local iana_regions = fetch_iana("Module:Lang/data/iana regions" , fallback_regions)
----------------------------------------------------------------
-- Minimal BCP47 policy tables (all plain)
----------------------------------------------------------------
local bcp47 = {
suppress = { -- languages whose default script is suppressed
en = "Latn", nl = "Latn", fr = "Latn", de = "Latn", es = "Latn",
pt = "Latn", it = "Latn"
},
deprecated = {},
preferred = {},
grandfathered= {},
redundant = {},
}
----------------------------------------------------------------
-- Return plain data only (no functions, no metatables)
----------------------------------------------------------------
return {
iana = {
languages = iana_languages,
scripts = iana_scripts,
regions = iana_regions,
},
-- Some Module:Lang forks use flat keys—expose those too
iana_languages = iana_languages,
iana_scripts = iana_scripts,
iana_regions = iana_regions,
bcp47 = bcp47,
}