وحدة:TNT

يمكن إنشاء صفحة توثيق الوحدة في وحدة:TNT/شرح

--
-- Module:TNT
-- Marefa-compatible version
--
-- Loads JsonConfig datasets when available.
-- If the global Commons dataset cannot be loaded through mw.ext.data.get,
-- it falls back to a local Data: page.
--

local p = {}

local i18nDataset = 'I18n/Module:TNT.tab'

-- Forward declarations
local sanitizeDataset
local loadData
local link
local formatMessage


function p.msg(frame)
	local dataset, id
	local params = {}
	local lang = nil

	for k, v in pairs(frame.args) do
		if k == 1 then
			dataset = mw.text.trim(v)

		elseif k == 2 then
			id = mw.text.trim(v)

		elseif type(k) == 'number' then
			table.insert(params, mw.text.trim(v))

		elseif k == 'lang' and v ~= '_' then
			lang = mw.text.trim(v)
		end
	end

	return formatMessage(dataset, id, params, lang)
end


function p.format(dataset, key, ...)
	local checkType = require('libraryUtil').checkType

	checkType('format', 1, dataset, 'string')
	checkType('format', 2, key, 'string')

	return formatMessage(dataset, key, {...})
end


function p.formatInLanguage(lang, dataset, key, ...)
	local checkType = require('libraryUtil').checkType

	checkType('formatInLanguage', 1, lang, 'string')
	checkType('formatInLanguage', 2, dataset, 'string')
	checkType('formatInLanguage', 3, key, 'string')

	return formatMessage(dataset, key, {...}, lang)
end


function p.link(frame)
	return link(frame.args[1])
end


function p.doc(frame)
	local dataset =
		'Templatedata/' .. sanitizeDataset(frame.args[1])

	return frame:extensionTag(
		'templatedata',
		p.getTemplateData(dataset)
	) ..
	formatMessage(
		i18nDataset,
		'edit_doc',
		{link(dataset)}
	)
end


function p.getTemplateData(dataset)

	local data = loadData(dataset)

	local names = {}

	for _, field in pairs(data.schema.fields) do
		table.insert(names, field.name)
	end

	local params = {}
	local paramOrder = {}

	for _, row in pairs(data.data) do

		local newVal = {}
		local name = nil

		for pos, val in pairs(row) do

			local columnName = names[pos]

			if columnName == 'name' then
				name = val
			else
				newVal[columnName] = val
			end
		end

		if name then
			params[name] = newVal
			table.insert(paramOrder, name)
		end
	end

	-- Work around JSON encoding treating
	-- {"1": {...}} as an array.
	params['zzz123'] = ''

	local json = mw.text.jsonEncode({
		params = params,
		paramOrder = paramOrder,
		description = data.description
	})

	json = string.gsub(
		json,
		'"zzz123":"",?',
		''
	)

	return json
end


--------------------------------------------------
-- Dataset name
--------------------------------------------------

sanitizeDataset = function(dataset)

	if not dataset then
		return nil
	end

	dataset = mw.text.trim(dataset)

	if dataset == '' then
		return nil

	elseif string.sub(dataset, -4) ~= '.tab' then
		return dataset .. '.tab'

	else
		return dataset
	end
end


--------------------------------------------------
-- Load dataset
--------------------------------------------------

loadData = function(dataset, lang)

	dataset = sanitizeDataset(dataset)

	if not dataset then

		if dataset == i18nDataset then
			error('No TNT dataset specified')
		end

		error(
			formatMessage(
				i18nDataset,
				'error_no_dataset',
				{}
			)
		)
	end


	--------------------------------------------------
	-- 1. Try JsonConfig
	--------------------------------------------------

	local data = false

	if mw.ext
		and mw.ext.data
		and mw.ext.data.get
	then

		local success, result =
			pcall(
				mw.ext.data.get,
				dataset,
				lang
			)

		if success
			and result
			and type(result) == 'table'
		then
			data = result
		end
	end


	if data then
		return data
	end


	--------------------------------------------------
	-- 2. Marefa fallback:
	--    try a local Data: page
	--------------------------------------------------

	local localTitle =
		'Data:' .. dataset

	local success, result =
		pcall(
			mw.loadJsonData,
			localTitle
		)

	if success
		and result
		and type(result) == 'table'
	then
		return result
	end


	--------------------------------------------------
	-- 3. Dataset unavailable
	--------------------------------------------------

	if dataset == i18nDataset then

		error(
			'Missing local dataset Data:' ..
			i18nDataset
		)

	else

		-- Do not call formatMessage here if the TNT
		-- translation dataset is also unavailable.
		local message

		local ok, translated =
			pcall(
				formatMessage,
				i18nDataset,
				'error_bad_dataset',
				{link(dataset)}
			)

		if ok then
			message = translated
		else
			message =
				'Dataset Data:' ..
				dataset ..
				' is not available on this wiki.'
		end

		error(message)
	end
end


--------------------------------------------------
-- Link to original Commons dataset
--------------------------------------------------

link = function(dataset)

	return 'c:Data:' ..
		mw.text.trim(dataset or '')
end


--------------------------------------------------
-- Get translated message
--------------------------------------------------

formatMessage = function(dataset, key, params, lang)

	local data = loadData(dataset, lang)

	if not data.data then
		error(
			'Dataset Data:' ..
			tostring(dataset) ..
			' has no data field.'
		)
	end


	for _, row in pairs(data.data) do

		local id, msg = unpack(row)

		if id == key then

			local result =
				mw.message.newRawMessage(
					msg,
					unpack(params or {})
				)

			return result:plain()
		end
	end


	if dataset == i18nDataset then

		error(
			'Invalid message key "' ..
			tostring(key) ..
			'"'
		)

	else

		return formatMessage(
			i18nDataset,
			'error_bad_msgkey',
			{
				key,
				link(dataset)
			}
		)
	end
end


return p