Mòdulu:Interprugettu

La ducumintazzioni di stu mòdulu si pò criari nta Mòdulu:Interprugettu/doc

-- Modulo per implementare le funzionalità di template:Interprogetto
require('strict')

local p = {} -- per l'esportazione delle funzioni del modulo

local cfg = {}
local root = mw.html.create('') -- radice del markup html
local debug = {} -- per debug
local categories = {} -- categorie di errore da aggiungere
local errors_msg = {} -- messaggi di errore da aggiungere

-- per non usare numeri "magici" nel codice
local category_namespace_number = 14

-- ============================================================================================================
-- Ritorna la stringa se è definita e diversa da stringa vuota, altrimenti nil
-- ============================================================================================================
local function is_defined(s)
	if s and s ~= '' then
		return s
	else
		return nil
	end
end

-- ============================================================================================================
-- Aggiunge uno spazio alla stringa se non termina per "'" (apostrofo)
-- ============================================================================================================
local function add_space(s)
	if not is_defined(s) then
		return ''
	elseif mw.ustring.sub(s, -1) == "'" then
		return s
	else
		return s .. ' '
	end
end

-- ============================================================================================================
-- Aggiunge la categoria "category" alla lista di categorie da aggiungere alla voce
-- ============================================================================================================
local function add_category(category)
	if category then
		categories[category] = true
	end
end

-- ============================================================================================================
-- Aggiunge il messaggio di errore "error_msg" alla lista di messaggi di errore da visualizzare.
-- Se viene precisata una categoria di errore la aggiunge alle categorie in cui inserire la voce,
-- altrimenti inserisce la categoria di errore standard
-- ============================================================================================================
local function add_error(error_msg, category)
	if error_msg then
		errors_msg[#errors_msg+1] = error_msg
		if category then
			add_category(category)
		else
			add_category('Errori di compilazione del template Interprogetto')
		end
	end
end

-- ============================================================================================================
-- Ritorna un collegamento di default dato il nome di un progetto, nil in caso di errori
-- ============================================================================================================
local function get_default_collegamento(key_progetto, fullpagename)
	if cfg.parameters[key_progetto] then
		if cfg.parameters[key_progetto]['collegamento_non_esistente'] then
			add_error(cfg.parameters[key_progetto]['collegamento_non_esistente'])
			return nil
		elseif cfg.parameters[key_progetto].collegamento_default_minuscolo then
			return mw.ustring.gsub(fullpagename, '^%u', string.lower)
		else
			return fullpagename
		end
	else
		return nil
	end
end

-- ============================================================================================================
-- Ordina una tabella in funzione della chiave "ordine" degli elementi della tabella
-- ============================================================================================================
local function sort_by_ordine(t1, t2)
	if t1.ordine < t2.ordine or t1.ordine == t2.ordine and t1.lingua < t2.lingua then
		return true
	end
end

-- ============================================================================================================
-- Classe per gestire la raccolta di informazioni da Wikidata
-- ============================================================================================================
local Wikidata_entity = {}

function Wikidata_entity:new(ignore_wikidata)
	-- Carica i dati da Wikidata se esistono
	local self = {}
	if not ignore_wikidata then
		self.entity = mw.wikibase.getEntityObject()
	end
	setmetatable(self, { __index = Wikidata_entity,
						 __tostring = function(t) return self:__tostring() end })
	self.collegamenti = {}
	self.badge = {}
	self.from_property_category = {}
	self.article_link = {}
	self.lingua = {}
	if self.entity then
		self.etichetta = self.entity:getLabel('it')
		-- Imposta il corsivo se la pagina su Wikidata ha la proprietà P31 ("Istance of", [[wikidata:Property:P31]])
		-- con valore corrispondente a un'opera, come definito in cfg.check_opera
		self.corsivo = self:hasPropertyValue('P31', cfg.check_opera)
		-- Considera disambigua se la pagina su Wikidata ha la proprietà P31 ("Istance of", [[wikidata:Property:P31]])
		-- con valore 4167410 ("Wikimedia disambiguation page", [[wikidata:Q4167410]])
		self.disambigua = self:hasPropertyValue('P31', '4167410')
		-- Controlla se la voce è relativa a una categoria
		self.is_category = self:hasPropertyValue('P31', '4167836')
		self:loadCollegamenti()
	end
	return self
end

function Wikidata_entity:getClaim(property_id)
	if self.entity.claims and
			self.entity.claims[property_id] and
			self.entity.claims[property_id][1].mainsnak.datavalue and
			self.entity.claims[property_id][1].mainsnak.datavalue.type == 'string' then
		return self.entity.claims[property_id][1].mainsnak.datavalue.value
	else
		return nil
	end
end

function Wikidata_entity:getInterwiki(project, property_language)
	local interwiki = { project }
	if property_language and self.entity.claims and self.entity.claims[property_language] then
		project = project:sub(3)
		for _, claim in ipairs(self.entity.claims[property_language]) do
			if claim.mainsnak.datavalue.type == 'wikibase-entityid' then
				local entityId = 'Q' .. claim.mainsnak.datavalue.value['numeric-id']
				if entityId ~= 'Q652' then
					local claims = mw.wikibase.getBestStatements(entityId, 'P424')
					if claims[1] and claims[1].mainsnak.datavalue then
						local language_code = claims[1].mainsnak.datavalue.value
						if language_code then
							if project == 'wikisource' and language_code == 'grc' then
								language_code = 'el'
							end
							table.insert(interwiki, language_code .. project)
							self.lingua[language_code .. project] = language_code
						end
					end
				end
			end
		end
	end
	return interwiki
end

-- ============================================================================================================
-- Carica collegamenti e badge da Wikidata controllando i progetti elencati in cfg.automatic_link
-- ============================================================================================================
function Wikidata_entity:loadCollegamenti()
	for key_progetto, progetto in pairs(cfg.automatic_link) do
		-- Carica i collegamenti di un progetto solo se non disambigua o tipo di progetto abilitato in disambigua
		if not self.disambigua or cfg.parameters[key_progetto].abilita_in_disambigua then
			for i, interwiki in ipairs(self:getInterwiki(progetto.interwiki, progetto.property_language)) do
				local sitelink = self.entity:getSitelink(interwiki)
				-- Dà sempre precedenza al sitelink se è una categoria
				if sitelink and mw.ustring.find(sitelink, '^Category:') then
					-- 'false' disabilita la consultazione della proprietà
					self.from_property_category[key_progetto] = false
				end
				local claim
				if progetto.property_category and self.from_property_category[key_progetto] ~= false then
					claim = self:getClaim(progetto.property_category)
					if claim then
						self.collegamenti[key_progetto] = 'Category:' .. claim
						self.from_property_category[key_progetto] = true
					end
				end
				if sitelink then
					if self.from_property_category[key_progetto] then
						self.article_link[key_progetto] = sitelink
					elseif i > 1 then
						local lingua = self.lingua[interwiki]
						key_progetto = string.format('%s_%s', key_progetto, lingua)
						self.lingua[key_progetto] = lingua
						self.collegamenti[key_progetto] = string.format('%s:%s', lingua, sitelink)
					else
						self.collegamenti[key_progetto] = sitelink
					end
					if i == 1 and self.entity.sitelinks[interwiki].badges then
						local badge_class = {}
						local badge_title = {}
						for _, badge_quality in ipairs(self.entity.sitelinks[interwiki].badges) do
							if cfg.badges[badge_quality] then
								badge_class[#badge_class+1] = cfg.badges[badge_quality].class
								badge_title[#badge_title+1] = cfg.badges[badge_quality].title
							end
						end
						self.badge[key_progetto] = {}
						self.badge[key_progetto].class = table.concat(badge_class, ' ' )
						self.badge[key_progetto].title = table.concat(badge_title, ', ' )
					end
				elseif not self.is_category and progetto.property_gallery and not self.from_property_category[key_progetto] then
					claim = self:getClaim(progetto.property_gallery)
					self.collegamenti[key_progetto] = claim
				end
			end
		end
	end
end

-- ============================================================================================================
-- Verifica se una determinata proprietà ha uno dei valori specificati nella lista "values".
-- Riadattata da "hasPropertyValue" su [[wikiquote:it:Modulo:Interprogetto]] a sua volta
-- riadattata da "instanceof(arg)" su [[wikisource:it:Modulo:Autore]]
-- ============================================================================================================
function Wikidata_entity:hasPropertyValue(propertyId, values)
	if self.entity.claims and self.entity.claims[propertyId] then
		for _, claim in ipairs(self.entity.claims[propertyId]) do
			if claim.mainsnak.datavalue and claim.mainsnak.datavalue.value then
				local datavalue = claim.mainsnak.datavalue
				if datavalue.type == 'wikibase-entityid' and
						datavalue.value['entity-type'] == 'item' and
						(type(values) == 'table' and values[tostring(datavalue.value['numeric-id'])]) or
						values == tostring(datavalue.value['numeric-id']) then
					return true
				end
			end
		end
	end
	return false
end
-- ============================================================================================================
-- Fine definizione della classe Wikidata_entity
-- ============================================================================================================

-- ============================================================================================================
-- Classe per gestire i collegamenti interprogetto
-- ============================================================================================================
local Collegamento = {}

function Collegamento:new(key_progetto, args, entity, default)
	-- Crea un collegamento a un progetto, riceve il nome del progetto, gli argomenti da usare per determinare
	-- i valori dei vari parametri del collegamento. Si appoggia alla tabella esterna cfg.parameters per i
	-- valori di default del progetto e alla tabella globale default per i valori di default generali

	local self = {}
	setmetatable(self, { __index = Collegamento,
						 __tostring = function(t) return self:__tostring() end })
	local default_progetto = cfg.parameters[key_progetto:match('^[^_]+')]
	if default_progetto == nil then
		-- Progetto non riconosciuto
		return nil
	end
	self.collegamento = args[key_progetto]
	if not is_defined(self.collegamento) then
		-- Collegamento non definito correttamente
		return nil
	else
		self.default_progetto = default_progetto
		self.ordine = default_progetto.ordine
		self.badge_leftbar = {}
		self.badge_leftbar.class = (entity.badge[key_progetto] and entity.badge[key_progetto].class) or ''
		self.badge_leftbar.title = (entity.badge[key_progetto] and entity.badge[key_progetto].title) or ''
		self.etichetta = is_defined(args[key_progetto .. '_etichetta']) or (default_progetto.etichetta_lower and default.etichetta_lower) or default.etichetta
		-- elabora l'oggetto per i testi completi su wikisource quando il collegamento è ricavato da wikidata e il parametro testo_preposizione è compilato
		local alias_s_oggetto = key_progetto == 's' and args.testo_preposizione and not args.orig_s and not args.s_preposizione and cfg.parameters['testo'].oggetto
		self.oggetto = args[key_progetto .. '_oggetto'] or alias_s_oggetto or default.oggetto or default_progetto.oggetto
		if default.frase_unificata or default_progetto.preposizione then
			-- consulta il parametro testo_preposizione se il collegamento a wikisource non è manuale
			local alias_s_preposizione = key_progetto == 's' and not args.orig_s and args.testo_preposizione
			self.preposizione = args[key_progetto .. '_preposizione'] or alias_s_preposizione or default.preposizione or default_progetto.preposizione
		else
			self.preposizione = ''
		end
		if default.frase_unificata then
			self.testo_prima = ''
			self.testo_dopo = ''
		else
			self.testo_prima = default_progetto.testo_prima
			self.testo_dopo = default_progetto.testo_dopo
		end
		if key_progetto == 'notizia' and is_defined(args.data) then
			self.testo_dopo = ' <small>' .. args.data .. '</small>'
		end
		local lingua = key_progetto == 's_el' and 'lingua greca' or
				entity.lingua[key_progetto] and require('Modulo:Lingue').get_voce(entity.lingua[key_progetto]) or
				args[key_progetto .. '_lingua'] and 'lingua ' .. args[key_progetto .. '_lingua']
		if default_progetto.lingua and lingua then
			self.lingua = ' in ' .. lingua
		else
			self.lingua = ''
		end
		return self
	end
end

function Collegamento:Link()
	local default_progetto = self.default_progetto
	if default_progetto.link == 'Link' then
		return self:Link_text()
	elseif default_progetto.link == 'LinkWithLanguage' then
		return self:Link_language()
	elseif default_progetto.link == 'LinkRicette' then
		return self:Link_ricette()
	elseif default_progetto.link == 'LinkIncubator' then
		return self:Link_incubator()
	end
	add_error('Errore interno modulo Interprogetto')
	return ''
end

function Collegamento:Link_lb()
	local default_progetto = self.default_progetto
	if default_progetto.link == 'Link' then
		return self:Link_text_lb()
	elseif default_progetto.link == 'LinkWithLanguage' then
		return self:Link_language_lb()
	elseif default_progetto.link == 'LinkRicette' then
		return self:Link_text_lb()
	elseif default_progetto.link == 'LinkIncubator' then
		return self:Link_incubator_lb()
	end
	add_error('Errore interno modulo Interprogetto')
	return ''
end

function Collegamento:Link_text()
	local default_progetto = self.default_progetto
	return "* [[File:", default_progetto.icona, "|link=", default_progetto.prefix, "|", default_progetto.dimensione_icona, "|Collabora a ",
			default_progetto.nome_progetto, "]] [[", default_progetto.prefix, "|", default_progetto.nome_progetto, "]] contiene ",
			self.oggetto, self.lingua, " ", add_space(self.preposizione), self.testo_prima, "'''[[", default_progetto.prefix,
			self.collegamento, "|", self.etichetta, "]]'''", self.testo_dopo
end

function Collegamento:Link_text_lb()
	local default_progetto = self.default_progetto
	return "[[", default_progetto.prefix, self.collegamento, "|", default_progetto.nome_leftbar or default_progetto.nome_progetto, "]]"
end

function Collegamento:Link_ricette()
	local default_progetto = self.default_progetto
	return "* [[File:", default_progetto.icona, "|link=", default_progetto.prefix, "|", default_progetto.dimensione_icona,
			"|Collabora a ", default_progetto.nome_progetto, "]] Il ''[[b:Libro di cucina|Libro di cucina]]'' di [[b:|Wikibooks]] contiene '''[[",
			default_progetto.prefix, self.collegamento, "|ricette]]''' relative a questo argomento"
end

function Collegamento:Link_language()
	local default_progetto = self.default_progetto
	local main_page_link = tostring(mw.uri.fullUrl(default_progetto.prefix, {uselang='it'}))
	return "* [[File:", default_progetto.icona, "|link=", main_page_link, "|", default_progetto.dimensione_icona, "|Collabora a ",
			default_progetto.nome_progetto, "]] <span class=\"plainlinks\">[", main_page_link, " ", default_progetto.nome_progetto,
			"]</span> contiene ", self.oggetto, " ", add_space(self.preposizione), self.testo_prima,
			"'''<span class=\"plainlinks\">[", tostring(mw.uri.fullUrl(default_progetto.prefix .. self.collegamento, {uselang='it'})),
			" ", self.etichetta, "]</span>'''", self.testo_dopo
end

function Collegamento:Link_language_lb()
	local default_progetto = self.default_progetto
	return "<span class=\"plainlinks\" title=\"", default_progetto.prefix , self.collegamento, "\">[",
			tostring(mw.uri.fullUrl(default_progetto.prefix .. self.collegamento, {uselang='it'})), " ",
			default_progetto.nome_leftbar or default_progetto.nome_progetto, "]</span>"
end

function Collegamento:Link_incubator()
	local default_progetto = self.default_progetto
	local oggetto = self.oggetto
	if not cfg.prefix_incubator[oggetto] then
		oggetto = default_progetto.oggetto
	end
	local collegamento = tostring(mw.uri.fullUrl(table.concat({'incubator:', cfg.prefix_incubator[oggetto],
										'/', self.collegamento}), {uselang='it'}))
	local main_page_incubator = tostring(mw.uri.fullUrl('incubator:Incubator:Main Page/it', {uselang='it'}))
	local main_page_progetto = ''
	if oggetto == 'wikipedia' then
		main_page_progetto = '[[Wikipedia]]'
	else
		main_page_progetto = table.concat({'[[', oggetto, ':it:|', oggetto:gsub('^%l', string.upper), ']]'})
	end
	return "* [[File:", default_progetto.icona, "|link=", main_page_incubator, "|", default_progetto.dimensione_icona,
			"|Collabora a Incubator]] <span class=\"plainlinks\">[", main_page_incubator, " Incubator]</span> contiene un test su ",
			main_page_progetto, self.lingua, " ", add_space(self.preposizione), "'''<span class=\"plainlinks\">[", collegamento, " ", self.etichetta, "]</span>'''"
end

function Collegamento:Link_incubator_lb()
	local default_progetto = cfg.parameters[self.key_progetto]
	local oggetto = self.oggetto
	if not cfg.prefix_incubator[oggetto] then
		oggetto = default_progetto.oggetto
	end
	local collegamento = tostring(mw.uri.fullUrl(table.concat({'incubator:', cfg.prefix_incubator[oggetto],
										'/', self.collegamento}), {uselang='it'}))
	return mw.message.newRawMessage("<span class=\"plainlinks\" title=\"$1\">[$2 Incubator]</span>", {self.etichetta, collegamento}):plain()
end
-- ============================================================================================================
-- Fine definizione della classe Collegamento
-- ============================================================================================================

-- ============================================================================================================
-- Scandisce la tabella progetti e produce il codice html per l'elenco dei collegamenti nella barra di sinistra
-- Imposta il tag div id="interProject" (vedi [[MediaWiki:InterProject.js]] incluso da [[Mediawiki:Common.js]])
-- ============================================================================================================
local function RenderLeftBar(progetti)

	local leftbar = mw.html.create('ul'):attr('title', 'Collegamenti verso gli altri progetti Wikimedia')
	for _, progetto in ipairs(progetti) do
		leftbar:newline()
		leftbar:wikitext('<li class=\"', progetto.badge_leftbar.class, '\" title=\"', progetto.badge_leftbar.title, '\">')
		leftbar:wikitext(progetto:Link_lb())
		if progetto.default_progetto.nome_leftbar then
			leftbar:wikitext('<br />(', progetto.default_progetto.nome_progetto, ')')
		end
		leftbar:wikitext('</li>')
	end
	root:tag('div')
		:attr('id', 'interProject')
		:addClass('toccolours')
		:cssText('display: none; clear: both; margin-top: 2em')
		:tag('p')
			:attr('id', 'sisterProjects')
			:cssText('background-color: #efefef; color: black; font-weight: bold; margin: 0')
			:tag('span')
				:wikitext('Altri progetti')
				:done()
			:done()
		:node(leftbar)
end

-- ============================================================================================================
-- Scandisce la tabella progetti e produce il codice html per l'elenco puntato dei collegamenti interprogetto
-- ============================================================================================================
local function RenderLinksInText(progetti)
	for _, progetto in ipairs(progetti) do
		root:newline()
		root:wikitext(progetto:Link())
	end
end

-- ============================================================================================================
-- Confronta i collegamenti manuali con quelli automatici e genera le categorie di classificazione nei casi di:
-- - Presenza di link manuale e assenza di link su wikidata
-- - Differenza tra link manuale e link su wikidata
-- - Differenza tra link manuale a categoria e categoria su wikidata
-- - Presenza di link manuale a categoria e a categoria su wikidata
-- ============================================================================================================
local function check_with_wikidata(key_progetto, entity, collegamento)
	if collegamento == nil then return end -- se non c'è un collegamento manuale ritorna immediatamente
	local entity_collegamento = entity.collegamenti[key_progetto]
	-- si assicura che il collegamento manuale inizi con la 'C' maiuscola se è una categoria
	local collegamento_normalizzato = mw.ustring.gsub(collegamento, '^category:', 'Category:')
	local collegamento_is_category = mw.ustring.find(collegamento_normalizzato, '^Category:')
	-- Check se il collegamento manuale è una categoria, se il tipo di progetto prevede una proprietà a parte
	-- per le categorie e se la sua consultazione non è stata disabilitata
	if collegamento_is_category and cfg.automatic_link[key_progetto].property_category and entity.from_property_category[key_progetto] ~= false then
		-- se esiste un collegamento su wikidata dalla proprietà per la categoria la confronta con quello manuale
		if entity.from_property_category[key_progetto] then
			if entity_collegamento ~= collegamento_normalizzato then
				add_category(cfg.automatic_link[key_progetto].category_wikidata_category_diff)
			end
		-- se non esiste un collegamento manuale su wikidata lo marca come assente
		else
			add_category(cfg.automatic_link[key_progetto].category_wikidata_category_missing)
		end
	else
		local article_link
		-- recupera il collegamento automatico alla voce (può essere in entity.article_link[key_progetto] o
		-- in entity.collegamento[key_progetto] a seconda del sitelink e della proprietà per le categorie)
		if entity.from_property_category[key_progetto] then
			article_link = entity.article_link[key_progetto]
		else
			article_link = entity_collegamento
		end
		-- Se ha recuperato un valore per article_link lo confronta con quello normalizzato
		-- altrimenti aggiunge il tracking di collegamento mancante in wikidata
		if article_link then
			if article_link ~= collegamento_normalizzato then
				add_category(cfg.automatic_link[key_progetto].category_wikidata_diff)
			end
		else
			add_category(cfg.automatic_link[key_progetto].category_wikidata_missing)
		end
	end
end

-- ============================================================================================================
-- Funzione principale richiamata dal template Interprogetto
-- ============================================================================================================
function p.interprogetto(frame)


	-- se chiamata da una sandbox carica la configurazione della sandbox
	if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) then   
		cfg = mw.loadData('Module:Interprogetto/Configurazione/sandbox')	   
	else																
		cfg = mw.loadData('Module:Interprogetto/Configurazione')
	end
	local origArgs
	-- ========================================================================================================
	-- Se chiamata mediante #invoke, usa gli argomenti passati al template invocante.
	-- Altrimenti a scopo di test assume che gli argomenti siano passati direttamente
	-- ========================================================================================================
	if frame == mw.getCurrentFrame() then
		origArgs = frame:getParent().args
	else
		origArgs = frame
	end
	-- Tabella con i parametri di default valorizzati
	local default = {}
	-- ========================================================================================================
	-- Carica il nome della pagina corrente
	-- ========================================================================================================
	local current_page = mw.title.getCurrentTitle()
	local current_namespace = current_page.namespace
	local current_pagename = current_page.text
	-- Per i namespace usa il nome canonico (inglese) per non avere differenze tra progetti:
	-- esempio: Utente/User, Categoria/Category, ma anche Wikiquote/Wikipedia (Project), ecc.
	if current_namespace ~= 0 then
		default.current_fullpagename = mw.site.namespaces[current_namespace].canonicalName .. ':' .. current_pagename
	else
		default.current_fullpagename = current_pagename
	end
	-- ========================================================================================================
	-- Carica i dati da Wikidata nell'oggetto "entity"
	-- ========================================================================================================
	local ignore_wikidata = false
	local nowikidata = origArgs.nowikidata and origArgs.nowikidata:lower()
	if nowikidata == 's' or nowikidata == 'sì' or nowikidata == 'si' then
		ignore_wikidata = true
	end
	local entity = Wikidata_entity:new(ignore_wikidata)
	-- ========================================================================================================
	-- Calcola l'etichetta di default per i collegamenti, in ordine di priorità:
	-- 1) Se è definita l'etichetta in lingua italiana su Wikidata usa questa (eliminando un eventuale
	--	"Categoria:" di fronte alla voce)
	-- 2) Altrimenti usa il nome della pagina corrente, eliminando un'eventuale disambigua in coda alla voce,
	--	e definisce etichetta_lower come il nome della voce con iniziale minuscola.
	-- Se la voce è segnalata come opera su Wikidata allora l'etichetta è in corsivo (senza iniziale minuscola)
	-- ========================================================================================================
	if is_defined(origArgs.etichetta) then
		default.etichetta = origArgs.etichetta
	else
		if entity.etichetta then
			-- Elimina un eventuale "Categoria:" in fronte del nome
			default.etichetta = mw.ustring.gsub(entity.etichetta, '^Categoria:', '')
		else
			-- Elimina un'eventuale disambigua dal nome
			default.etichetta = mw.ustring.gsub(current_pagename, ' %(.*%)$', '')
			if current_namespace == 0 then
				default.etichetta_lower = mw.ustring.gsub(default.etichetta, '^%u', string.lower)
			end
		end
		if entity.corsivo then
			default.etichetta = '<span style=\"font-style:italic;\">' .. default.etichetta .. '</span>'
			default.etichetta_lower = default.etichetta
		end
	end
	-- ========================================================================================================
	-- Calcola preposizione e oggetto di default, modificandoli se il namespace quello delle categorie
	-- ========================================================================================================
	if current_namespace ~= category_namespace_number then
		default.preposizione = origArgs.preposizione
		default.oggetto = origArgs.oggetto
	else
		default.preposizione = origArgs.preposizione or "sull'argomento"
		default.oggetto = origArgs.oggetto or "una categoria"
		default.frase_unificata = true
	end
	-- ========================================================================================================
	-- Copia i parametri in una nuova tabella, creando coppie progetto/collegamento per i parametri posizionali
	-- e controllando per parametri duplicati e nomi di progetto non conosciuti
	-- ========================================================================================================
	local newArgs = {}
	local nolink = false
	newArgs.orig_s = origArgs.s
	for key, value in pairs(origArgs) do
		if tonumber(key) then
			local key_progetto = mw.text.trim(value)
			if cfg.parameters[key_progetto] then
				if origArgs[key_progetto] then
					add_error('Collegamento a \"' .. value .. '\" inserito sia come parametro posizionale che nominale')
				else
					if key_progetto == 's' then newArgs.orig_s = key_progetto end
					newArgs[key_progetto] = get_default_collegamento(key_progetto, default.current_fullpagename)
				end
			elseif key_progetto == 'nolink' then
				nolink = true
			else
				add_error('Il parametro \"' .. value .. '\" non corrisponde a nessun progetto riconosciuto dal template')
			end
		else
			newArgs[key] = value
		end
	end
	-- ========================================================================================================
	-- Controlla i collegamenti inseriti manualmente integrandoli eventualmente con quelli presenti in Wikidata.
	-- Salta questo passo se c'è un collegamento a "notizia" dato che in questo caso deve essere unico e quindi
	-- non deve aggiungere i collegamenti da Wikidata. Inoltre, in caso di "disambigua", salta i progetti non
	-- abilitati in disambigua che in ogni caso non devono essere aggiunti
	-- ========================================================================================================
	if not newArgs.notizia then
		-- ====================================================================================================
		-- Controlla il collegamento compilato manualmente e quello caricato da Wikidata
		-- ====================================================================================================
		for key_progetto, collegamento in pairs(newArgs) do
			if cfg.parameters[key_progetto] and cfg.automatic_link[key_progetto] and entity.entity then
				if not entity.disambigua or cfg.parameters[key_progetto].abilita_in_disambigua then
					check_with_wikidata(key_progetto, entity, collegamento)
				end
			end
		end
		-- ====================================================================================================
		-- Aggiunge il collegamento da Wikidata se non è presente quello compilato manualmente o se rinvia a
		-- un progetto in lingua non italiana che non è registrato nella configurazione e non va sovrascritto
		-- ====================================================================================================
		for key_progetto, collegamento in pairs(entity.collegamenti) do
			if not cfg.automatic_link[key_progetto] or not (newArgs[key_progetto] or newArgs[cfg.automatic_link[key_progetto].alias]) then
				newArgs[key_progetto] = collegamento
				-- Segnala che il collegamento è stato aggiunto da Wikidata
				add_category(cfg.automatic_link[key_progetto:match('^[^_]+')].category_wikidata)
			end
		end
	end
	-- ========================================================================================================
	-- Sulla base della lista di argomenti ripulita costruisce la lista dei collegamenti da inserire
	-- ========================================================================================================
	local progetti = {}
	local collegamento_found = false
	for key_progetto, collegamento in pairs(newArgs) do
		if cfg.parameters[key_progetto] or entity.collegamenti[key_progetto] then
			-- Salta i collegamenti a Wikidata per le voci nel namespace principale eccetto che per la Pagina principale
			if key_progetto ~= 'wikidata' or current_namespace ~= 0 or current_pagename == 'Pagina principale' then
				local progetto = Collegamento:new(key_progetto, newArgs, entity, default)
				if progetto then
					collegamento_found = true
					-- Se è disambigua registra solo i valori per i progetti abilitati in disambigua
					if not entity.disambigua or cfg.parameters[key_progetto] and cfg.parameters[key_progetto].abilita_in_disambigua then
						progetti[#progetti+1] = progetto
					end
				end
			end
		end
	end
	table.sort(progetti, sort_by_ordine)
	-- ========================================================================================================
	-- Genera il codice html
	-- ========================================================================================================
	if entity.disambigua and #progetti == 0 and collegamento_found then
		add_error('Collegamenti non visualizzabili perché la voce è una disambigua su Wikidata',
				  'Errori di compilazione del template Interprogetto - collegamenti in disambigua')
	elseif #progetti == 0 then
		--add_error('Template interprogetto vuoto e senza dati da recuperare da Wikidata', 'Errori di compilazione del template Interprogetto - template vuoto')
		add_error('', 'Errori di compilazione del template Interprogetto - template vuoto')
	else
		local nobarra = origArgs.nobarra and origArgs.nobarra:lower()
		if nobarra ~= 's' and nobarra ~= 'sì' and nobarra ~= 'si' then
			RenderLeftBar(progetti)
		end
		if not nolink then
			RenderLinksInText(progetti)
		end
	end
	-- =================================================================================================================================
	-- Nei namespace ammessi inserisce le categorie di segnalazione di errori/avvisi
	-- =================================================================================================================================
	if cfg.whitelist_category[current_namespace] then
		for category, _ in pairs(categories) do
			root:wikitext('[[Catigurìa:' .. category .. ']]')
		end
	end
	-- =================================================================================================================================
	-- Aggiunge i messaggi di errore
	-- =================================================================================================================================	
	if #errors_msg > 0 then
		if #progetti > 0 then
			root:wikitext('\n')
		end
		root:wikitext('<strong class=\"error\">' .. table.concat(errors_msg, '; ') .. '</strong>')
	end
	return tostring(root)
end

return p