Difference between revisions of "Module:TNT"

From The HILLSIDE
Jump to navigation Jump to search
en>Yurik
(fix templatedata doc having just the positional parameters)
en>Yurik
(make i18n/ prefix optional, support for usage from modules)
Line 23: Line 23:
 
--    | source-table              <!-- uses a translation message with id = "source-table" -->
 
--    | source-table              <!-- uses a translation message with id = "source-table" -->
 
--    | param1 }}                <!-- optional parameter -->
 
--    | param1 }}                <!-- optional parameter -->
--  
+
--
--  
+
--
 
--    The "doc" function will generate the <templatedata> parameter documentation for templates.
 
--    The "doc" function will generate the <templatedata> parameter documentation for templates.
 
--    This way all template parameters can be stored and localized in a single Commons dataset.
 
--    This way all template parameters can be stored and localized in a single Commons dataset.
Line 36: Line 36:
 
local p = {}
 
local p = {}
 
local i18nDataset = 'I18n/Module:TNT.tab'
 
local i18nDataset = 'I18n/Module:TNT.tab'
 +
local checkType = require('libraryUtil').checkType
 +
 +
-- Forward declaration of the local functions
 +
local formatMessage, loadData, link
  
 
function p.msg(frame)
 
function p.msg(frame)
Line 47: Line 51:
 
id = mw.text.trim(v)
 
id = mw.text.trim(v)
 
elseif type(k) == 'number' then
 
elseif type(k) == 'number' then
table.insert(params, v)
+
table.insert(params, mw.text.trim(v))
 
elseif k == 'lang' and v ~= '_' then
 
elseif k == 'lang' and v ~= '_' then
 
lang = mw.text.trim(v)
 
lang = mw.text.trim(v)
Line 53: Line 57:
 
end
 
end
 
return formatMessage(dataset, id, params, lang)
 
return formatMessage(dataset, id, params, lang)
 +
end
 +
 +
-- Identical to p.msg() above, but used from other lua modules
 +
function p.format(dataset, key, params, lang)
 +
checkType('format', 1, dataset, 'string')
 +
checkType('format', 2, key, 'string')
 +
checkType('format', 3, params, 'table', true)
 +
checkType('format', 4, lang, 'string', true)
 +
return formatMessage(dataset, key, params, lang)
 
end
 
end
  
Line 59: Line 72:
 
function p.link(frame)
 
function p.link(frame)
 
return link(frame.args[1])
 
return link(frame.args[1])
end
 
 
-- Given a dataset name, convert it to a title with the 'commons:data:' prefix
 
function link(dataset)
 
dataset = 'Data:' .. mw.text.trim(dataset or '')
 
if mw.site.siteName == 'Wikimedia Commons' then
 
return dataset
 
else
 
return 'commons:' .. dataset
 
end
 
 
end
 
end
  
 
function p.doc(frame)
 
function p.doc(frame)
 
return frame:extensionTag(
 
return frame:extensionTag(
'templatedata',
+
'templatedata',
p.getTemplateData(frame.args[1])
+
p.getTemplateData(mw.text.trim(frame.args[1]))
) .. tntMessage('edit_doc', {link(dataset)})
+
) .. formatMessage(i18nDataset, 'edit_doc', {link(dataset)})
 
end
 
end
  
 
function p.getTemplateData(page)
 
function p.getTemplateData(page)
dataset = 'Templatedata/' .. normalizeDataset(page)
+
dataset = 'Templatedata/' .. mw.text.trim(page)
 
-- TODO: add '_' parameter once lua starts reindexing properly for "all" languages
 
-- TODO: add '_' parameter once lua starts reindexing properly for "all" languages
 
local data = loadData(dataset)
 
local data = loadData(dataset)
Line 89: Line 92:
 
local params = {}
 
local params = {}
 
local paramOrder = {}
 
local paramOrder = {}
    for _, row in pairs(data.data) do
+
for _, row in pairs(data.data) do
    local newVal = {}
+
local newVal = {}
    local name = nil
+
local name = nil
    for pos, val in pairs(row) do
+
for pos, val in pairs(row) do
    local columnName = names[pos]
+
local columnName = names[pos]
    if columnName == 'name' then
+
if columnName == 'name' then
    name = val
+
name = val
    else
+
else
    newVal[columnName] = val
+
newVal[columnName] = val
    end
+
end
    end
+
end
    if name then
+
if name then
    params[name] = newVal
+
params[name] = newVal
    table.insert(paramOrder, name)
+
table.insert(paramOrder, name)
    end
+
end
    end
+
end
   
+
 
    -- Work around json encoding treating {"1":{...}} as an [{...}]
+
-- Work around json encoding treating {"1":{...}} as an [{...}]
    params['zzz123']=''
+
params['zzz123']=''
+
 
 
local json = mw.text.jsonEncode({
 
local json = mw.text.jsonEncode({
 
params=params,
 
params=params,
Line 120: Line 123:
 
end
 
end
  
function formatMessage(dataset, key, params, lang)
+
-- Local functions
    for _, row in pairs(loadData(dataset, lang).data) do
 
    local id, msg = unpack(row)
 
    if id == key then
 
    local result = mw.message.newRawMessage(msg, unpack(params))
 
    return result:plain()
 
    end
 
    end
 
if dataset == i18nDataset then
 
-- Prevent cyclical calls
 
error('Invalid message key "' .. key .. '"')
 
else
 
error(tntMessage('error_bad_msgkey', {key, link(dataset)}))
 
end
 
end
 
 
 
function tntMessage(key, params)
 
return formatMessage(i18nDataset, key, params)
 
end
 
  
function normalizeDataset(dataset)
+
loadData = function(dataset, lang)
 
if not dataset or dataset == '' then
 
if not dataset or dataset == '' then
error(tntMessage('error_no_dataset', {}))
+
error(formatMessage(i18nDataset, 'error_no_dataset', {}))
 
end
 
end
 
if string.sub(dataset,-4) ~= '.tab' then
 
if string.sub(dataset,-4) ~= '.tab' then
 
dataset = dataset .. '.tab'
 
dataset = dataset .. '.tab'
 
end
 
end
return dataset
 
end
 
  
function loadData(dataset, lang)
 
 
local data = mw.ext.data.get(dataset, lang)
 
local data = mw.ext.data.get(dataset, lang)
 +
 
if data == false then
 
if data == false then
 
if dataset == i18nDataset then
 
if dataset == i18nDataset then
Line 157: Line 140:
 
error('Missing Commons dataset ' .. i18nDataset)
 
error('Missing Commons dataset ' .. i18nDataset)
 
else
 
else
error(tntMessage('error_bad_dataset', {link(dataset)}))
+
error(formatMessage(i18nDataset, 'error_bad_dataset', {link(dataset)}))
 
end
 
end
 
end
 
end
 
return data
 
return data
 +
end
 +
 +
-- Given a dataset name, convert it to a title with the 'commons:data:' prefix
 +
link = function(dataset)
 +
dataset = 'Data:' .. mw.text.trim(dataset or '')
 +
if mw.site.siteName == 'Wikimedia Commons' then
 +
return dataset
 +
else
 +
return 'commons:' .. dataset
 +
end
 +
end
 +
 +
formatMessage = function(dataset, key, params, lang)
 +
-- Message tables must always start with I18n/...
 +
if dataset and string.sub(dataset,1,5) ~= 'I18n/' then
 +
dataset = 'I18n/' .. dataset
 +
end
 +
for _, row in pairs(loadData(dataset, lang).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
 +
-- Prevent cyclical calls
 +
error('Invalid message key "' .. key .. '"')
 +
else
 +
error(formatMessage(i18nDataset, 'error_bad_msgkey', {key, link(dataset)}))
 +
end
 
end
 
end
  
 
return p
 
return p

Revision as of 07:03, 28 April 2019

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

--
-- INTRO:   (!!! DO NOT RENAME THIS PAGE !!!)
--    This module allows any template or module to be copy/pasted between
--    wikis without any translation changes. All translation text is stored
--    in the global  Data:*.tab  pages on Commons, and used everywhere.
--
-- SEE:   https://www.mediawiki.org/wiki/Multilingual_Templates_and_Modules
--
-- ATTENTION:
--    Please do NOT rename this module - it has to be identical on all wikis.
--    This code is maintained at https://www.mediawiki.org/wiki/Module:TNT
--    Please do not modify it anywhere else, as it may get copied and override your changes.
--    Suggestions can be made at https://www.mediawiki.org/wiki/Module_talk:TNT
--
-- DESCRIPTION:
--    The "msg" function uses a Commons dataset to translate a message
--    with a given key (e.g. source-table), plus optional arguments
--    to the wiki markup in the current content language.
--    Use lang=xx to set language.  Example:
--
--    {{#invoke:TNT | msg
--     | I18n/Template:Graphs.tab  <!-- https://commons.wikimedia.org/wiki/Data:I18n/Template:Graphs.tab -->
--     | source-table              <!-- uses a translation message with id = "source-table" -->
--     | param1 }}                 <!-- optional parameter -->
--
--
--    The "doc" function will generate the <templatedata> parameter documentation for templates.
--    This way all template parameters can be stored and localized in a single Commons dataset.
--    NOTE: "doc" assumes that all documentation is located in Data:Templatedata/* on Commons.
--
--    {{#invoke:TNT | doc | Graph:Lines }}
--        uses https://commons.wikimedia.org/wiki/Data:Templatedata/Graph:Lines.tab
--        if the current page is Template:Graph:Lines/doc
--

local p = {}
local i18nDataset = 'I18n/Module:TNT.tab'
local checkType = require('libraryUtil').checkType

-- Forward declaration of the local functions
local formatMessage, loadData, link

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

-- Identical to p.msg() above, but used from other lua modules
function p.format(dataset, key, params, lang)
	checkType('format', 1, dataset, 'string')
	checkType('format', 2, key, 'string')
	checkType('format', 3, params, 'table', true)
	checkType('format', 4, lang, 'string', true)
	return formatMessage(dataset, key, params, lang)
end

-- Converts first parameter to a interwiki-ready link. For example, it converts
-- "Sandbox/Sample.tab" -> 'commons:Data:Sandbox/Sample.tab'
function p.link(frame)
	return link(frame.args[1])
end

function p.doc(frame)
	return frame:extensionTag(
			'templatedata',
			p.getTemplateData(mw.text.trim(frame.args[1]))
	) .. formatMessage(i18nDataset, 'edit_doc', {link(dataset)})
end

function p.getTemplateData(page)
	dataset = 'Templatedata/' .. mw.text.trim(page)
	-- TODO: add '_' parameter once lua starts reindexing properly for "all" languages
	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 [{...}]
	params['zzz123']=''

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

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

	return json
end

-- Local functions

loadData = function(dataset, lang)
	if not dataset or dataset == '' then
		error(formatMessage(i18nDataset, 'error_no_dataset', {}))
	end
	if string.sub(dataset,-4) ~= '.tab' then
		dataset = dataset .. '.tab'
	end

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

	if data == false then
		if dataset == i18nDataset then
			-- Prevent cyclical calls
			error('Missing Commons dataset ' .. i18nDataset)
		else
			error(formatMessage(i18nDataset, 'error_bad_dataset', {link(dataset)}))
		end
	end
	return data
end

-- Given a dataset name, convert it to a title with the 'commons:data:' prefix
link = function(dataset)
	dataset = 'Data:' .. mw.text.trim(dataset or '')
	if mw.site.siteName == 'Wikimedia Commons' then
		return dataset
	else
		return 'commons:' .. dataset
	end
end

formatMessage = function(dataset, key, params, lang)
	-- Message tables must always start with I18n/...
	if dataset and string.sub(dataset,1,5) ~= 'I18n/' then
		dataset = 'I18n/' .. dataset
	end
	for _, row in pairs(loadData(dataset, lang).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
		-- Prevent cyclical calls
		error('Invalid message key "' .. key .. '"')
	else
		error(formatMessage(i18nDataset, 'error_bad_msgkey', {key, link(dataset)}))
	end
end

return p