Jump to content

Module:Record

From Srcfy Wiki

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

-- Helpers for {{Record infobox}}, {{Record data}} and {{Cite source}}.
-- Labels exist in English (en) and Malayalam (ml); the language comes from {{PAGELANGUAGE}}.
-- Controlled vocabularies are defined here once, so the infobox, the form and the search agree.
local p = {}

local CONTENT_TYPES = {
	documentation = { en = 'Documentation', ml = 'രേഖപ്പെടുത്തൽ' },
	report = { en = 'Report', ml = 'റിപ്പോർട്ട്' },
	investigation = { en = 'Investigation', ml = 'അന്വേഷണം' },
	interactive = { en = 'Interactive', ml = 'ഇന്ററാക്ടീവ്' },
}

-- Evidence status: what the record establishes, not how much we like it.
local EVIDENCE = {
	allegation = { en = 'Allegation', ml = 'ആരോപണം',
		hint = 'A claim made by someone, not yet corroborated.' },
	reported = { en = 'Reported', ml = 'റിപ്പോർട്ട് ചെയ്യപ്പെട്ടത്',
		hint = 'Reported by at least one credible source.' },
	corroborated = { en = 'Corroborated', ml = 'സ്ഥിരീകരിക്കപ്പെട്ടത്',
		hint = 'Supported by independent sources.' },
	confirmed = { en = 'Confirmed finding', ml = 'ഔദ്യോഗികമായി സ്ഥാപിക്കപ്പെട്ടത്',
		hint = 'Established by a court, inquiry or official record.' },
	disputed = { en = 'Disputed', ml = 'തർക്കത്തിലുള്ളത്',
		hint = 'Credible sources disagree.' },
	unresolved = { en = 'Unresolved', ml = 'പരിഹരിക്കപ്പെടാത്തത്',
		hint = 'Key facts remain unknown.' },
}

-- Editorial workflow: source → verify → review → publish.
local STATUS = {
	sourcing = { en = 'Sourcing', ml = 'ഉറവിട ശേഖരണം' },
	verification = { en = 'Verification', ml = 'പരിശോധന' },
	review = { en = 'Review', ml = 'അവലോകനം' },
	published = { en = 'Published', ml = 'പ്രസിദ്ധീകരിച്ചത്' },
}

local LABELS = {
	content_type = { en = 'Type', ml = 'തരം' },
	event_date = { en = 'Event date', ml = 'സംഭവ തീയതി' },
	period = { en = 'Period', ml = 'കാലയളവ്' },
	publication_date = { en = 'Published on srcfy', ml = 'srcfy-ൽ പ്രസിദ്ധീകരിച്ചത്' },
	location = { en = 'Location', ml = 'സ്ഥലം' },
	region = { en = 'Region', ml = 'പ്രദേശം' },
	country = { en = 'Country', ml = 'രാജ്യം' },
	community = { en = 'Community / identity', ml = 'സമുദായം / സ്വത്വം' },
	affiliation = { en = 'Belief / affiliation', ml = 'വിശ്വാസം / ബന്ധം' },
	religious_community = { en = 'Religious community', ml = 'മത സമുദായം' },
	caste = { en = 'Caste', ml = 'ജാതി' },
	ethnicity = { en = 'Ethnicity', ml = 'വംശം' },
	religious_belief = { en = 'Religious belief', ml = 'മത വിശ്വാസം' },
	political_ideology = { en = 'Political ideology', ml = 'രാഷ്ട്രീയ പ്രത്യയശാസ്ത്രം' },
	philosophy = { en = 'Philosophy', ml = 'തത്ത്വചിന്ത' },
	political_party = { en = 'Political party', ml = 'രാഷ്ട്രീയ പാർട്ടി' },
	topics = { en = 'Topics', ml = 'വിഷയങ്ങൾ' },
	evidence_status = { en = 'Evidence status', ml = 'തെളിവിന്റെ നില' },
	status = { en = 'Editorial status', ml = 'എഡിറ്റോറിയൽ നില' },
	last_reviewed = { en = 'Last reviewed', ml = 'അവസാനം പരിശോധിച്ചത്' },
	killed = { en = 'Killed', ml = 'കൊല്ലപ്പെട്ടവർ' },
	injured = { en = 'Injured', ml = 'പരിക്കേറ്റവർ' },
	correction_note = { en = 'Correction', ml = 'തിരുത്ത്' },
	interactive_path = { en = 'Interactive path', ml = 'ഇന്ററാക്ടീവ് പാത' },
	required_type = { en = 'Content type', ml = 'ഉള്ളടക്ക തരം' },
	required_publication_date = { en = 'Publication date', ml = 'പ്രസിദ്ധീകരണ തീയതി' },
	missing_required = { en = 'This record is marked Published but is missing required fields, so srcfy.com will not show it until they are filled:',
		ml = 'ഈ രേഖ പ്രസിദ്ധീകരിച്ചതായി അടയാളപ്പെടുത്തിയിട്ടുണ്ട്, പക്ഷേ ആവശ്യമായ ചില വിവരങ്ങൾ ഇല്ല. അവ പൂരിപ്പിക്കുന്നതുവരെ srcfy.com ഇത് കാണിക്കില്ല:' },
	sources_note = { en = 'Sources are cited in the text. To report an error, use the discussion page.',
		ml = 'ഉറവിടങ്ങൾ ലേഖനത്തിൽ ഉദ്ധരിച്ചിരിക്കുന്നു. തെറ്റ് അറിയിക്കാൻ ചർച്ചാ താൾ ഉപയോഗിക്കുക.' },
	archived = { en = 'archived', ml = 'ആർക്കൈവ്' },
	accessed = { en = 'Accessed', ml = 'പരിശോധിച്ചത്' },
}

local MONTHS = {
	en = { 'January', 'February', 'March', 'April', 'May', 'June', 'July',
		'August', 'September', 'October', 'November', 'December' },
	ml = { 'ജനുവരി', 'ഫെബ്രുവരി', 'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ', 'ജൂലൈ',
		'ഓഗസ്റ്റ്', 'സെപ്റ്റംബർ', 'ഒക്ടോബർ', 'നവംബർ', 'ഡിസംബർ' },
}

local function trim(s) return s and mw.text.trim(s) or '' end

local function lang(frame)
	local l = trim(frame.args.lang or '')
	-- {{PAGELANGUAGE}}, not title:getPageLanguage(), which this MediaWiki's Scribunto lacks.
	if l == '' then l = trim(frame:preprocess('{{PAGELANGUAGE}}')) end
	return l == 'ml' and 'ml' or 'en'
end

-- Accepts a key ("confirmed") or any label ("Confirmed finding") in any language.
local function lookup(tbl, value)
	local v = mw.ustring.lower(trim(value))
	if v == '' then return nil end
	if tbl[v] then return v, tbl[v] end
	for key, entry in pairs(tbl) do
		if mw.ustring.lower(entry.en) == v or entry.ml == trim(value) then return key, entry end
	end
	return nil
end

local function canonical(tbl, value)
	local _, entry = lookup(tbl, value)
	if entry then return entry.en end
	return trim(value)
end

-- Canonical English values, stored in SMW and used by the search index.
function p.typeName(frame) return canonical(CONTENT_TYPES, frame.args[1]) end
function p.evidenceName(frame) return canonical(EVIDENCE, frame.args[1]) end

-- Editorial status fails closed: empty or unknown values count as Sourcing, never Published.
function p.statusName(frame)
	local _, entry = lookup(STATUS, frame.args[1])
	return entry and entry.en or STATUS.sourcing.en
end

-- Featured and other yes/no fields: no, false, 0, off or empty store false; anything else true.
local FALSE = { [''] = true, no = true, ['false'] = true, ['0'] = true, off = true, n = true }
function p.boolean(frame)
	return FALSE[mw.ustring.lower(trim(frame.args[1]))] and 'false' or 'true'
end

-- Incident trigger as one of four canonical lower-case English tags; anything else stores nothing.
local TRIGGERS = { ['cattle transport'] = true, ['cow slaughter'] = true, ['cattle theft'] = true,
	['beef consumption'] = true }
function p.triggerName(frame)
	local v = mw.ustring.lower(trim(frame.args[1]))
	return TRIGGERS[v] and v or ''
end

-- Required fields for a Published record, as the srcfy.com indexer checks them.
-- Returns a comma-separated list of missing field labels, or '' when nothing is missing
-- or the record is not Published. Used by {{Record data}} for its warning box.
function p.missing(frame)
	local a = frame.args
	local _, status = lookup(STATUS, a.status)
	if status ~= STATUS.published then return '' end
	local l = lang(frame)
	local out = {}
	local typeKey = lookup(CONTENT_TYPES, a.type)
	if not typeKey then table.insert(out, LABELS.required_type[l]) end
	if not lookup(EVIDENCE, a.evidence_status) then table.insert(out, LABELS.evidence_status[l]) end
	if not trim(a.publication_date):match('^%d%d%d%d') then table.insert(out, LABELS.required_publication_date[l]) end
	if typeKey == 'interactive'
		and not trim(a.interactive_path):gsub('^/+', ''):gsub('/+$', ''):match('^[a-z0-9][a-z0-9/-]*$') then
		table.insert(out, LABELS.interactive_path[l])
	end
	return table.concat(out, ', ')
end

function p.label(frame)
	local entry = LABELS[trim(frame.args[1])]
	return entry and entry[lang(frame)] or ''
end

local function localised(tbl, frame)
	local _, entry = lookup(tbl, frame.args[1])
	if not entry then return trim(frame.args[1]) end
	return entry[lang(frame)]
end

function p.typeLabel(frame) return localised(CONTENT_TYPES, frame) end
function p.statusLabel(frame) return localised(STATUS, frame) end

-- Evidence status as a text badge (never colour alone) with a tooltip explaining it.
function p.evidenceBadge(frame)
	local key, entry = lookup(EVIDENCE, frame.args[1])
	if not entry then return trim(frame.args[1]) end
	return string.format('<span class="record-evidence record-evidence-%s" title="%s">%s</span>',
		key, entry.hint, entry[lang(frame)])
end

-- YYYY, YYYY-MM or YYYY-MM-DD → localised text; anything else is shown as typed.
local function formatDate(iso, l)
	iso = trim(iso)
	local y, m, d = iso:match('^(%d%d%d%d)%-(%d%d)%-(%d%d)$')
	if not y then y, m = iso:match('^(%d%d%d%d)%-(%d%d)$') end
	if not y then return iso end
	local month = MONTHS[l][tonumber(m)]
	if not month then return iso end
	if l == 'ml' then return y .. ' ' .. month .. (d and (' ' .. tonumber(d)) or '') end
	return (d and (tonumber(d) .. ' ') or '') .. month .. ' ' .. y
end

function p.date(frame) return formatDate(frame.args[1], lang(frame)) end

-- {{#invoke:Record|period|2014-05|2019}} → "May 2014 – 2019"
function p.period(frame)
	local l = lang(frame)
	local a, b = trim(frame.args[1]), trim(frame.args[2])
	if b == '' or b == a then return formatDate(a, l) end
	return formatDate(a, l) .. ' – ' .. formatDate(b, l)
end

-- Comma-separated values → plain text for one value, a list for several.
function p.list(frame)
	local items = {}
	for item in mw.text.gsplit(trim(frame.args[1]), ',', true) do
		item = trim(item)
		if item ~= '' then table.insert(items, item) end
	end
	if #items <= 1 then return items[1] or '' end
	return '\n* ' .. table.concat(items, '\n* ')
end

-- Typed tag rows for the infobox: "Religious community: Muslims" etc. under one group heading.
function p.tags(frame)
	local l = lang(frame)
	local parent = frame:getParent()
	local kinds = mw.text.split(trim(frame.args[1]), ',', true)
	local rows = {}
	for _, kind in ipairs(kinds) do
		kind = trim(kind)
		local value = trim(parent.args[kind] or '')
		if value ~= '' then
			local values = {}
			for v in mw.text.gsplit(value, ',', true) do
				v = trim(v)
				if v ~= '' then table.insert(values, v) end
			end
			table.insert(rows, '<span class="record-tag-kind">' .. LABELS[kind][l] .. ':</span> '
				.. table.concat(values, ', '))
		end
	end
	return table.concat(rows, '<br>')
end

return p