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,
}