Módulo:Wikidata

De MacphersonWiki
Ir a la navegación Ir a la búsqueda

Uso[editar código]

Este módulo es un proyecto de declaración para la herramienta de formato Wikidata

Tiene las funciones Wikidata, getDeclaraciones, getPropiedad y setFrame.

Función Wikidata[editar código]

Permite instrucción de formato(s) para una propiedad específica del tema relacionado con la página actual (no podemos acceder a los otros ítems).

Parámetros[editar código]

propiedad

La identificación de la propiedad como "p18". Necesario .

valor

Si se da el valor anula el valor de Wikidata.

prioridad

Si se da prioridad = sí tendrá prioridad el valor de Wikidata que el valor que se de al parámetro valor

debeExistir

Si se informa con "sí" no se recuperan las entidades de Wikidata sin un enlace a un artículo de Wikipedia.

enlace

Puede tomar los valores enlace = sí o enlace = no.

  • Si se da enlace = no aparecerá solamente la etiqueta del valor sin enlace interno.
  • Si se utiliza enlace = sí se mostrará un enlace a la correspondiente página de la Wikipedia definida en Wikidata si existe, si no se enlazará a la página con nombre igual a la etiqueta de Wikidata (si no existe un artículo con ese nombre) y si no se mostrará un enlace al elemento de Wikidata.
formatoTexto

Si se da formatoTexto = mayúscula o cursiva o mayúscula cursiva (da igual el orden)

  • Con el valor mayúscula:

la primera letra de la propiedad se pondrá en mayúsculas. Cuando no se da el valor al parámetro separador y por consiguiente los valores aparecen separados por una coma a excepción de último que se separa por una conjunción por defecto y, solo se pondra en mayúscula la inicial del primer valor. En caso de que se dé valor al parámetro enlace todos los valores apareceran con la inicial en mayúscula.

  • Con el valor cursiva:

el texto de la propiedad se pondrá en cursivas.

formatoFecha

Los valores posibles son:

  • =año: Se devuelve la fecha como una año. Por ejemplo 2014 o 1 a. C.

Parámetros para listas[editar código]

lista(opcional): tipo de lista. Los valores posibles son:

  • =no (por implementar): Solo se devuelve el primer elemento de Wikidata. De momento puede utilizarse el parámetro uno=sí . Por ejemplo, en el artículo de España, si se escribe {{#invoke:Wikidata|Wikidata|propiedad=p37|uno=sí}} se generaría "Error de Lua en la línea 935: attempt to index field 'wikibase' (a nil value).".
  • =ordenada: Se devuelve una lista ordenada o numerada. Por ejemplo, en el artículo de España, si se escribe {{#invoke:Wikidata|Wikidata|propiedad=p37|lista=ordenada}} se generaría:
Error de Lua en la línea 935: attempt to index field 'wikibase' (a nil value).
  • =no ordenada: Se devuelve una lista no ordenada o con viñetas. Por ejemplo, en el artículo de España, si se escribe {{#invoke:Wikidata|Wikidata|propiedad=p37|lista=no ordenada}} se generaría:
Error de Lua en la línea 935: attempt to index field 'wikibase' (a nil value).
  • Si no se informa el tipo de lista se devuelve una lista de los elementos separados por coma. Por ejemplo, si se escribe{{#invoke:Wikidata|Wikidata|propiedad=p37}} se generaría "Error de Lua en la línea 935: attempt to index field 'wikibase' (a nil value)."
En este último caso se pueden utilizar los parámetros separador y conjunción que permiten separar los primeros valores y el último valor de una propiedad. Si no se especifica se toma por defecto como separador una coma y como conjunción "y" respectivamente. Por ejemplo, en el artículo de España, si se escribe {{#invoke:Wikidata|Wikidata|propiedad=p37|separador=/|conjunción=/}} se mostraría "Error de Lua en la línea 935: attempt to index field 'wikibase' (a nil value).".

Funciones específicas para el formato[editar código]

valor-función

Nombre de la función Lua que se llama para dar formato al valor. La función acepta como argumentos las siguientes tablas Lua:

  • valor: datos obtenidos de Wikidata para la propiedad. El único argumento obligatorio al llamar a la función
  • opciones: argumentos con los que se accede a la plantilla {{propiedad}} o en el tipo de dato específico
  • marco o frame:
  • calificativos: calificativos de la propiedad en Wikidata
valor-módulo

Nombre del módulo donde está definida la función. Si no se especifica el módulo se intentará buscar la función en el módulo:Wikidata/Formatos y si no se buscará en el módulo definido en la tabla modulosTipos del módulo Wikidata. Algunas de las funciones permitidas son:

tipo de dato / valor-función Módulo de Wikidata en el que se encuentra definido Descripción Usado en Ejemplos de propiedades de Wikidata
altura Ver magnitud
área Ver magnitud
bandera Formatos país Se muestra la bandera y el nombre del país. {{Ficha de biblioteca}}, {{Ficha de templo}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P17)
formatoCargo Formatos Ficha de persona Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P39)
educado en Formatos educación Se muestra el lugar donde se ha educado y en su caso entre paréntesis el grado académico, especialidad y periodo. Ficha de persona Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P69)
formatoGenero Ficha de película Ficha de película Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P136)
formatoId Formatos {{Infobox animanga principal}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P31)
imagen Formato imagen {{Ficha de programa de televisión}}, {{Ficha de entidad subnacional}}, {{Ficha de artista musical}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P18), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P154)
lugar Formato lugar Formato para lugares de la forma ciudad (unidad administrativa, país) Ficha de persona, {{Ficha de organización}}, {{Ficha de competición deportiva}}, {{Ficha de aeropuerto}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P19), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P20), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P159), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P276), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P131)
magnitud Formato magnitud Se muestra la magnitud junto a sus unidades y en su caso entre paréntesis el valor en el sistema internacional. Ficha de lugar ficticio, {{Ficha de entidad subnacional}}, {{Ficha de cuerpo de agua}}, {{Ficha de espacio natural}}{{Ficha de localidad de España}}, {{Ficha de faro}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2048)

Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2067)

Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2046), Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2053)

Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2929)

movimiento Formato movimiento Formato para movimientos Ficha de persona Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P135)
formatoNumero Formatos {{Ficha de epidemia}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P1603)
nacionalidad Formatos país Ficha de persona Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P27)
formatoObraAnyo Formatos Ficha de película

Ficha de libro

Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P527)
formatoObraAutor Formatos Ficha de película Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P144)
formatoOcupacionFemenino

formatoOcupacionMasculino

Ficha de persona Formato para ocupaciones de personas Ficha de persona Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P106)
periodicidad Formato magnitud Se muestra la periodicidad (anual, mensual, quincenal, semanal, etc). {{Ficha de periódico}}, {{Ficha de revista}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P2896)
premio Formato premio Formato para premios de obras eliminando los literales de la forma " a ...", " a la ..." o " en la categoría ...". Ficha de libro Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P166)
formatoURL

url

Formatos Ficha de persona, {{Ficha de videojuego}} Error de Lua en Módulo:Wd en la línea 632: attempt to index field 'wikibase' (a nil value). (P856)

Valores devueltos[editar código]

Devuelve la declaración formateada de acuerdo a las opciones.

Función getDeclaraciones[editar código]

Para ser usado en otro módulos.

Valores devueltos[editar código]

Devuelve una tabla con todas las declaraciones del elemento

Función getPropiedad[editar código]

Para ser usado en otros módulos.

Parámetros[editar código]

declaraciones

Una tabla de declaraciones

opciones

Una tabla con las opciones. los elementos de la tabla son los parámetros de la función Wikidata.

Valores devueltos[editar código]

Devuelve la declaración formateada de acuerdo a las opciones.

Función setFrame[editar código]

Para pasar el frame desde otro módulo. Es necesario poner esta función cuando se usa la anterior en casos en que haya que expandir wikitexto como por ejemplo con las coordenadas o los formatos de banderas.

Parámetros[editar código]

frame

Una tabla/objeto que se pasa desde la invocación del módulo.

Valores devueltos[editar código]

Ninguno.

Función addLinkback(texto, identificador de la entidad, identificador de la propiedad)[editar código]

La función añade al texto recibido la imagen de un lápiz que enlaza a la propiedad de la entidad en Wikidata.

Valores devueltos[editar código]


--[[*********************************************************************************
	* Nombre: Módulo:Wikidata
	*
	* Descripción: Este módulo devuelve el valor o valores con o sin formato
	* específico a una propiedad de Wikidata.
	*
	* Fecha última revisión: 30 de junio de 2021.
	*
	* Estado: En uso.
	*
	*********************************************************************************`-- ]]
local p = {}
local datequalifiers = {'P585', 'P571', 'P580', 'P582'}
local es = mw.language.new('es')
local primera = true
--local marco Ojo. marco no debe definirse como local pues si se hace así puede fallar.
 --[[ =========================================================================
			Mensajes de error
	  ========================================================================= `-- ]]

local avisos = mw.loadData('Módulo:Wikidata/mensajes')

-- Módulos y funciones utilizadas
local elementoTabla = require('Módulo:Tablas').elemento
--
-- Módulos en los que están definidos los tipos de datos más habituales si son
-- diferentes de Wikidata/Formatos
--
local modulosTipos	=  mw.loadData('Módulo:Wikidata/modulosTipos')

local modulosTiposComplejos	=  {
	['nacionalidad']		= 'Módulo:Wikidata/Formatos país',	
}

 --[[ =========================================================================
	  Función para pasar el frame cuando se usa en otros módulos.	 
	 ========================================================================= `-- ]]
function p:setFrame(frame)
	marco = frame
end
 --[[ =========================================================================
	  Función para identificar el ítem correspondiente a la página o otro dado.
			  Esto último aún no funciona.	 
	 ========================================================================= `-- ]]

function SelecionEntidadPorId( id )

		if id and id ~= ''  then
			return mw.wikibase.getEntityObject( id )
		else
			return mw.wikibase.getEntityObject()
		end
end

 --[[ =========================================================================
	  Función que identifica si el valor devuelto es un ítem o una propiedad
	  y en función de eso añade el prefijo correspondiente	
	 ========================================================================= `-- ]]

function SelecionEntidadPorValor( valor )
	local prefijo = ''
	if valor['entity-type'] == 'item' then
		prefijo = 'q' -- Prefijo de ítem
	elseif valor['entity-type'] == 'property' then
		prefijo = 'p' -- Prefijo de propiedad
	else
		return formatoError( 'unknown-entity-type' )
	end
	return prefijo .. valor['numeric-id'] -- Se concatena el prefijo y el código numérico
end

 --[[ =========================================================================
	  Función auxiliar para dar formato a los mensajes de error	 
	 ========================================================================= `-- ]]

function formatoError( clave )
	return '<span class="error">' .. avisos.errores[clave] .. '</span>'
end
 --[[ =========================================================================
	  Función para determinar el rango	
	 ========================================================================= `-- ]]
function getRango(tablaDeclaraciones)

	local rank = 'deprecated'

	for indice, declaracion in pairs(tablaDeclaraciones) do
		if declaracion.rank == 'preferred' then
			return 'preferred'
		elseif declaracion.rank == 'normal' then
			rank = 'normal'
		end
	end

	return rank
end

 --[[ =========================================================================
	  Función para determinar la declaracion o declaraciones de mayor rango	
	 ========================================================================= `-- ]]
function p.filtrarDeclaracionPorRango(tablaDeclaraciones)
	local rango = getRango(tablaDeclaraciones)
	local tablaAuxiliar = tablaDeclaraciones
	tablaDeclaraciones = {}
	
	if rango == 'deprecated' then
		return {}
	end

	for indice, declaracion in pairs(tablaAuxiliar) do
		if declaracion.rank == rango then
			table.insert(tablaDeclaraciones, declaracion)
		end
	end
	return tablaDeclaraciones
end

 --[[ =========================================================================
	  Función para seleccionar el tipo de declaración: Referencia, valor principal
	  o calificador	 
	 ========================================================================= `-- ]]

function seleccionDeclaracion(declaracion, opciones)
	local fuente = {}
	local propiedadFuente = {}
	local calificador = opciones.formatoCalificador ~= '()' and opciones.calificador

	if calificador ~= '' and calificador  and declaracion['qualifiers'] then
		if declaracion['qualifiers'][mw.ustring.upper(calificador)] then
			return declaracion.qualifiers[mw.ustring.upper(calificador)][1] -- devuelve el calificador (solo devolverá el primer valor)
		else
			return "" --Para que no lance excepción si no existe el calificador
		end
	elseif opciones.dato == 'fuente' and declaracion['references'] then
		fuente = declaracion.references[1]['snaks']
		for k,v in pairs(fuente) do
			propiedadFuente = k
		end
		return declaracion.references[1]['snaks'][propiedadFuente][1]  -- devuelve la fuente (queda que se itinere la tabla)
	elseif (calificador == '' or not calificador) and (opciones.dato ~= 'fuente') then
		return declaracion.mainsnak -- devuelve el valor principal
	else
		return ''	
	end
end

 --[[ =========================================================================
	  Función para recopilar las declaraciones	 
	 ========================================================================= `-- ]]

function p.getDeclaraciones(entityId)

	-- == Comprobamos que existe un ítem enlazado a la página en Wikidata ==
	if not pcall (SelecionEntidadPorId, entityId ) then
		return false
	end
	local entidad  = SelecionEntidadPorId(entityId)
	if not entidad then
		return  '' -- Si la página no está enlazada a un ítem no devuelve nada
	end

	-- == Comprobamos que el ítem tiene declaraciones (claims) ==

	if not entidad.claims then
		return '' -- Si el ítem no tiene declaraciones no devuelve nada
	end
	-- == Declaración de formato y concatenado limpio ==
	return entidad.claims
end

 --[[ =========================================================================
	  Función para  crear la cadena que devolverá la declaración	
	 ========================================================================= `-- ]]
	
local function valinQualif(claim, qualifs)
	local claimqualifs = claim.qualifiers
	local i,qualif
	local vals, vals1, datavalue, value, datatype
	
	if not claimqualifs then
		return nil
	end
	for i, qualif in pairs(qualifs) do
		vals = claimqualifs[qualif]
		if vals then
			vals1 = vals[1]
			if vals1 then
				datavalue=vals1.datavalue
				
				if datavalue then
					datatype = datavalue.type
					value = datavalue.value
					
					if datatype == 'time' and value then
						return value.time
					elseif datatype == 'string' and value then
						return value
					end
				end
			end
		end
	end
end	

function p.getPropiedad(opciones, declaracion)
	local propiedad	 = {}

	-- Resolver alias de propiedad
	if opciones.propiedad == 'precisión' or opciones.propiedad == 'latitud' or opciones.propiedad == 'longitud'  then --latitud, longitud o precisión
		propiedad = 'P625'
	else
		propiedad = opciones.propiedad -- En el resto de casos se lee lo dado
    end

	if not propiedad then -- Comprobamos si existe la propiedad dada y en caso contrario se devuelve un error
		return formatoError( 'property-param-not-provided' )
	end
	local tablaOrdenada
	if declaracion then
		tablaOrdenada = declaracion
	elseif mw.wikibase.isValidEntityId(tostring(opciones.entityId)) and mw.wikibase.isValidEntityId(tostring(propiedad)) then
			tablaOrdenada = mw.wikibase.getAllStatements( opciones.entityId, mw.ustring.upper(propiedad) )
			if not tablaOrdenada[1] then return '' end
	else
		return ''
	end
	
	-- Función que separa la cadena de texto 'inputstr' utilizando un separador 'sep' 
	function split(inputstr, sep) 
		sep=sep or '%s' 
		local t={}
		for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do 
			table.insert(t,field)  
			if s=="" then 
				return t 
			end 
		end 
	end
	
	tablaOrdenada = p.filtroDesconocidos(tablaOrdenada)
	
	-- Aplicar filtro de calificador
	if (opciones.filtroCalificador ~= nil and opciones.filtroCalificador ~= '') then
		local opts = split(opciones.filtroCalificador, ';')
		local negative = false
		if (#opts > 2) then
			if (opts[3]=='n') then
				negative = true
			elseif (opts[3]=='p') then
				negative = false
			end
		end
	
		tablaOrdenada = p.filtroCalificadores(tablaOrdenada, opts[1], split(opts[2], ','), negative)
	end
	
	-- Aplicar filtro de valor
	if (opciones.filtroValor ~= nil and opciones.filtroValor ~= '') then
		local opts = split(opciones.filtroValor, ';')
		local negative = false
		if (#opts > 1) then
			if (opts[2]=='n') then
				negative = true
			elseif (opts[2]=='p') then
				negative = false
			end
		end
		
		tablaOrdenada = p.filtroValores(tablaOrdenada, split(opts[1], ','), negative)
	end
	
	-- Aplicar función de formato
	local modulo, funcion
	funcion = opciones['valor-función'] or opciones['value-function'] or opciones['funcion']
	if funcion then 
		modulo = modulosTiposComplejos[funcion]
	
		if modulo then
			return require(modulo)[funcion](tablaOrdenada, opciones)
		end
	end	

	-- Evitar que pete cuando se haga el find en opciones['formatoTexto'] si vale nil
	if not opciones['formatoTexto'] then
		opciones['formatoTexto'] = ''
	end

	-- Aplicar filtro de mayor rango
	if (opciones.rangoMayor == 'sí') then
		tablaOrdenada = p.filtrarDeclaracionPorRango(tablaOrdenada)
	end

	-- Ordenarsegún el calificador "orden dentro de la serie"
	if opciones.ordenar == 'sí' then
		require('Módulo:Tablas').ordenar(tablaOrdenada,
			function(elemento1,elemento2)
				local orden1 = valinQualif(elemento1, { 'P1545' }) or '' -- elemento1.qualifiers.P1545[1].datavalue.value or ''
				local orden2 = valinQualif(elemento2, { 'P1545' }) or '' -- elemento2.qualifiers.P1545[1].datavalue.value or ''
				
				return orden1 < orden2
			end
		 )
	end

	--Ordenar según la fecha. [Véase la función chronosort de :fr:Module:Wikidata/Récup]
	if opciones.ordenar == 'por fecha' then
		require('Módulo:Tablas').ordenar(tablaOrdenada,
			function(elemento1,elemento2)
				local fecha1 = valinQualif(elemento1, datequalifiers) or '' -- elemento1.qualifiers.P580[1].datavalue.value.time or ''
				local fecha2 = valinQualif(elemento2, datequalifiers) or '' -- elemento2.qualifiers.P580[1].datavalue.value.time or ''
				
				return fecha1 < fecha2
			end
		 )
	end
	
	-- Si después de todo no queda nada en la tabla retornar
	if not tablaOrdenada[1] then
		return
	end

	-- == Si solo se desea que devuelva un valor ==
	-- Pendiente eliminar el parámetro y sustituirlo por un nuevo valor del parámetro lista=no que haría lo mismo que opciones.uno = sí
	if opciones.uno == 'sí' then -- Para que devuelva el valor de índice 1
		tablaOrdenada = {tablaOrdenada[1]}
	elseif opciones.uno == 'último' then -- Para que devuelva la última entrada de la tabla
		tablaOrdenada = {tablaOrdenada[#tablaOrdenada]}
	end

-- == Creamos una tabla con los valores que devolverá ==

	local formatoDeclaraciones = {}
	local hayDeclaraciones
	
	for indice, declaracion in pairs(tablaOrdenada) do
   		declaracionFormateada = p.formatoDeclaracion(declaracion, opciones)
   		if declaracionFormateada and declaracionFormateada ~= '' then
		   	table.insert(formatoDeclaraciones, declaracionFormateada)
		   	hayDeclaraciones = true
	   	end	
   	end
   	
	primera = true
	
	if not hayDeclaraciones then
		return
	end

	-- Aplicar el formato a la lista de valores según el tipo de lista de las
	-- opciones
	
	return p.formatoLista(formatoDeclaraciones, opciones)
end

-- Función que sirve para comprobar si una entidad tiene una propiedad con un
-- valor específico
-- Parámetros:
--   · entidad: tabla de la entidad de Wikidata
--   · propiedad: identificador de Wikidata para la propiedad
--   · valor: valor de la propiedad en Wikidata
function p.tieneValorPropiedad(entidad, propiedad, valor)
	
	if entidad and entidad.claims and entidad.claims[propiedad] then
		
		local mainsnak
		
		for key,value in ipairs(entidad.claims[propiedad]) do
			if value and value.mainsnak then
				mainsnak = value.mainsnak
				if mainsnak.datatype == 'wikibase-item' and
						mainsnak.snaktype == 'value' and
						mainsnak.datavalue.value.id == valor then
					return true
				end
			end
		end
	end
	
	return false
end

-- Función que sirve para devolver la leyenda (P2096) de una imagen (P18) en Wikidata en un determinado idioma
-- La función se llama así: {{#invoke:Wikidata |getLeyendaImagen | <PARÁMETRO> | lang=<ISO-639code> |id=<QID>}}
-- Devuelve PARÁMETRO, a menos que sea igual a "FETCH_WIKIDATA", del objeto QID (llamada que consume recursos)
-- Si se omite QID o está vacio, se utiliza el artículo actual (llamada que NO consume recursos)
-- Si se omite lang se utiliza por defecto el idioma local de la wiki, en caso contrario el idioma del código ISO-639
-- ISO-639 está documentado aquí: https://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqisocodes.html#wp1252447
-- El ranking es: 'preferred' > 'normal' y devuelve la etiqueta de la primera imágen con ranking 'preferred'
-- O la etiqueta de la primera imagen with ranking 'normal' si no hay ningún 'preferred'
-- Ranks: https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua

p.getLeyendaImagen = function(frame)
	-- busca un un elemento concreto en Wikidata (QID), en caso contrario que sea nil
	local id = frame.args.id

	if id and (#id == 0) then
		id = nil
	end

	-- busca el parámetro del idioma que debería contender un código ISO-639 de dos dígitos
	-- si no se declara, toma por defecto el idioma local de la wiki (es)
	local lang = frame.args.lang
	if (not lang) or (#lang < 2) then
		lang = mw.language.getContentLanguage().code
	end

	-- el primer parámetro sin nombrar es el parámetro local, si se declara
	local input_parm = mw.text.trim(frame.args[1] or "")
	if input_parm == "FETCH_WIKIDATA" or input_parm == "" or input_parm == nil then
		local ent = mw.wikibase.getEntityObject(id)
		local imgs
		if ent and ent.claims then
			imgs = ent.claims.P18
		end
		local imglbl
		if imgs then
			-- busca una imagen con ranking 'preferred'
			for k1, v1 in pairs(imgs) do
				if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P2096 then
					local imglbls = v1.qualifiers.P2096
					for k2, v2 in pairs(imglbls) do
						if v2.datavalue.value.language == lang then
							imglbl = v2.datavalue.value.text
							break
						end
					end
				end
			end
			-- si no hay ninguna, busca una con ranking 'normal'
			if (not imglbl) then
				for k1, v1 in pairs(imgs) do
					if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P2096 then
						local imglbls = v1.qualifiers.P2096
						for k2, v2 in pairs(imglbls) do
							if v2.datavalue.value.language == lang then
								imglbl = v2.datavalue.value.text
								break
							end
						end
					end
				end
			end
		end
		return imglbl
	else
		return input_parm
	end
end

-- Función que devuelve el valor de entidad.claims[idPropiedad][ocurrencia].mainsnak.datavalue.value.text
-- con entidad.claims[idPropiedad][ocurrencia].mainsnak.datavalue.value.language = 'es'

-- Útil para obtener valores de propiedades de tipo monolingualtext

function p.getPropiedadEnEspanyol(idEntidad, idPropiedad)
	-- Ver cs:Modul:Wikidata/item	formatEntityWithGender
	
	--
	local entidad =  mw.wikibase.getEntityObject(idEntidad)
	
	if not entidad then
		return
	end
	
	local declaracion   = elementoTabla(entidad,'claims', idPropiedad)
	
	if not declaracion then
		return
	end
	
	local valor
	
	for k,v in pairs(declaracion) do
		valor = elementoTabla(v,'mainsnak', 'datavalue', 'value')
		
		if valor and valor.language == 'es' then
			return valor.text
		end
	end
end

-- devuelve el ID de la página en Wikidata (Q...), o nada si la página no está conectada a Wikidata
function p.pageId(frame)
	local entity = mw.wikibase.getEntityObject()
	if not entity then return nil else return entity.id end
end

function p.categorizar(opciones, declaracion)
	-- Evitar que pete cuando se haga el find en opciones['formatoTexto'] si vale nil
	if not opciones['formatoTexto'] then
		opciones['formatoTexto'] = ''
	end	
	
	local categoriaOpciones=opciones['categoría']	
	
	if not categoriaOpciones then
		return ''
	end

	opciones['enlace'] = 'no'

	-- Crear una tabla con los valores de la propiedad.	
	local valoresDeclaracion = {}

	if declaracion then
		valoresDeclaracion = declaracion
	elseif opciones.propiedad then
		local propiedad = {}
		if opciones.propiedad == 'precisión' or opciones.propiedad == 'latitud' or opciones.propiedad == 'longitud'  then
			propiedad = 'P625' -- Si damos el valor latitud, longitud o precisión equivaldrá a dar p625
		else
			propiedad = opciones.propiedad -- En el resto de casos se lee lo dado
		end
		
		if not p.getDeclaraciones(opciones.entityId) then
			return formatoError( 'other entity' )
		elseif p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)] then
			valoresDeclaracion = p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)]
		else
			return ''
		end		
	else
		return ''
	end

--  Creamos una tabla con cada categoría a partir de cada valor de la declaración
	local categorias	= {}
	local hayCategorias
	
	if type(categoriaOpciones) == 'string' then
		local ModuloPaginas = require('Módulo:Páginas')
	 
		for indice, valor in pairs(valoresDeclaracion) do
			valorFormateado = p.formatoDeclaracion(valor, opciones)
			if valorFormateado ~= '' then
				categoria = ModuloPaginas.existeCategoria(categoriaOpciones:gsub('$1',valorFormateado))
			
				if categoria then
					table.insert(categorias, categoria)
					hayCategorias = true
				end
			end	
		end
	elseif type(categoriaOpciones) == 'table' then
		for indice, valor in pairs(valoresDeclaracion) do
			categoria = categoriaOpciones[elementoTabla(valor, 'mainsnak', 'datavalue', 'value', 'numeric-id')]
			
			if categoria then
				table.insert(categorias, 'Categoría:' .. categoria)
				hayCategorias = true
			end
		end
	end
	
	if hayCategorias then
		return '[[' .. mw.text.listToText( categorias, ']][[',']][[') .. ']]'
	end
	
	return ''
end

 --[[ =========================================================================
		Función que filtra los valores de una propiedad y devuelve solo los que
		tengan el calificador "qualifier" indicado con uno de los valores "values"  
	 ========================================================================= `-- ]]
	 
function p.filtroCalificadores(t, qualifier, values, negativo)
	local f = {}  -- Tabla que se devolverá con el resultado del filtrado
	for k,v in pairs(t) do
		local counts = false
		if(v["qualifiers"] ~= nil and v["qualifiers"][qualifier] ~= nil) then
			for k2,v2 in pairs(v["qualifiers"][qualifier]) do
				-- Comprobar si el identificador del valor del cualificador está en la lista
				for k3,v3 in pairs(values) do
					if (v2["datavalue"] ~= nil and v2["datavalue"]["value"] ~= nil and v2["datavalue"]["value"]["id"] ~= nil and v3 == v2["datavalue"]["value"]["id"])then  
						counts = true -- Si está marcar como true
					end
				end
			end
		end
		if counts and not negativo then -- Si uno de los valores del cualificador dio true se inserta el elemento
			table.insert(f, v)
		elseif not counts and negativo then -- Si ninguno de los valores del cualificador dio true se inserta el elemento
			table.insert(f, v)
		end
	end
	return f
end

 --[[ =========================================================================
		Función que filtra los valores de una propiedad y devuelve solo los que
		tengan uno de los valores "values"  
	 ========================================================================= `-- ]]
	 
function p.filtroValores(t, values, negativo)
	local f = {}  -- Tabla que se devolverá con el resultado del filtrado
	for k,v in pairs(t) do
		local counts = false
		if(v["mainsnak"]["datavalue"]["value"]["id"] ~= nil) then
			for k2,v2 in pairs(values) do
				if (v2 == v["mainsnak"]["datavalue"]["value"]["id"])then  
					counts = true -- Si está marcar como true
				end
			end
		end
		if counts and not negativo then -- Si uno de los valores del cualificador dio true se inserta el elemento
			table.insert(f, v)
		elseif not counts and negativo then -- Si ninguno de los valores del cualificador dio true se inserta el elemento
			table.insert(f, v)
		end
	end
	return f
end

 --[[ =========================================================================
		Función que filtra los valores de una propiedad y devuelve solo los que
		tengan formatos de valor, omitiendo los de formato desconocido o sin valor
	 ========================================================================= `-- ]]
function p.filtroDesconocidos(t)
	for k,v in pairs(t) do
		if(v["mainsnak"]["snaktype"] ~= "value") then
			t[k] = nil
		end
		local qual = v["qualifiers"]
		if(qual ~= nil) then
			for qualk,qualv in pairs(qual) do
				local prop = qualv
				for propk,propv in pairs(prop) do
					if(propv["snaktype"] ~= "value") then
						prop[propk] = nil
						-- same as: qual[prop] = nil
						-- same as: t["qualifiers"][prop] = nil
					end
				end
				if #prop == 0 then
					prop = nil
					qual[qualk] = nil
				end
			end
			if #qual == 0 then
				qual = nil
			end
		end
	end
	return t
end

 --[[ =========================================================================
		Función que comprueba si la página está enlazada a  Wikidata
		en caso de estarlo pasa el valor como a argumento a la función formatSnak()  
	 ========================================================================= `-- ]]

function p.formatoDeclaracion( declaracion, opciones)
	if not declaracion.type or declaracion.type ~= 'statement' then -- Se comprueba que tiene valor de tipo y que este sea statement (declaración) lo cual pasa siempre que existe la propiedad
		return formatoError( 'unknown-claim-type' ) -- Si no se cumple devuelve error
	end
	
	-- En el caso de que haya calificador se devuelve a la derecha del valor de la
	-- declaración entre paréntesis.
	
	local calificativo = opciones.calificativo or opciones.calificador

	if calificativo and declaracion.qualifiers then
		-- De momento los calificativos, normalmente años, no se enlazan
	   local opcionesCalificativo = {['formatoTexto']='', enlace='no', ['formatoFecha']='año'} -- Pendiente
	  
	   local wValorCalificativo
	   local wValorCalificativoFormateado
	  
	   local funcionCalificativo, mensajeError = obtenerFuncion(calificativo, opciones['módulo calificativo'])
	  
		if mensajeError then
			return mensajeError
		elseif funcionCalificativo then
	   	  -- Utilizar la función recibida sobre todos los calificativos
	   	  wValorCalificativo		   = declaracion.qualifiers
		  wValorCalificativoFormateado = funcionCalificativo(wValorCalificativo, opcionesCalificativo)
	   	elseif opciones.formatoCalificador and opciones.formatoCalificador == '()' then
			wValorCalificativo = declaracion.qualifiers[mw.ustring.upper(calificativo)]
			if wValorCalificativo and wValorCalificativo[1] then
				wValorCalificativoFormateado = p.formatoDato(wValorCalificativo[1], opcionesCalificativo)
			end
		elseif opciones.formatoCalificador and table.getn(mw.text.split(opciones.formatoCalificador, '%.')) == 2 then
			moduloFormatoCalificador = mw.text.split(opciones.formatoCalificador, '%.')
			formateado = require ('Módulo:' .. moduloFormatoCalificador[1])
			if not formateado then
				return formatoError( 'value-module-not-found' )
			end
			fun = formateado[moduloFormatoCalificador[2]]
			if not fun then
				return formatoError( 'value-function-not-found' )
			end
			
			if mw.ustring.find(opciones['formatoTexto'],'mayúscula', plain ) and
			   (primera or (opciones['separador'] and opciones['separador'] ~= 'null') or
			   	(opciones['lista'] and opciones['lista'] ~= '')) then
			  opciones['mayúscula'] = 'sí'
				  primera = false
			end
			
			if mw.ustring.find(opciones['formatoTexto'],'cursivas', plain ) then
				opcionesEntidad.cursivas = 'sí'
			end
			
			wValorCalificativoFormateado = fun( declaracion.qualifiers, opciones, marco)
			--return require('Módulo:Tablas').tostring(declaracion)
		else
	   	  -- Utilizar el primer valor del calificativo de la propiedad recibida
	   	  wValorCalificativo = declaracion.qualifiers[mw.ustring.upper(calificativo)]
	   	 
	   	  if wValorCalificativo and wValorCalificativo[1] then
			wValorCalificativoFormateado = p.formatoDato(wValorCalificativo[1], opcionesCalificativo)
		  end
		end
		if opciones.separadorcalificador then separador = opciones.separadorcalificador else separador = ' ' end
		if wValorCalificativoFormateado then
			datoFormateado = p.formatoDato(declaracion.mainsnak, opciones)
			
			-- Si el parámetro especificado era "|calificador="" no devolver propiedad y paréntesis
			if(opciones.calificador ~= nil and opciones.calificador ~= '') then
				return wValorCalificativoFormateado
			end
			-- Si el parámetro especificado era "|calificativo="" devolver propiedad y calificativo entre paréntesis
			return (datoFormateado and datoFormateado .. '&nbsp;<small>(' .. wValorCalificativoFormateado .. ')</small>') or nil
		end		
	end

	-- Si no hay calificativo.
	return p.formatoDato(seleccionDeclaracion(declaracion, opciones), opciones, declaracion.qualifiers)
end

 --[[ =========================================================================
		Función que comprueba el tipo de dato (snaktype)
		si es value pasa el valor como argumento a la función formatoValorDato()	
	 ========================================================================= `-- ]]

function p.formatoDato( dato, opciones, calificativos)
	
	if not dato or dato == '' then
		return ''
	end
	if dato.snaktype == 'somevalue' then
		-- Fecha más temprana
		if calificativos then
			if calificativos['P1319'] and calificativos['P1319'][1] and
			   calificativos['P1319'][1].datavalue and
			   calificativos['P1319'][1].datavalue.type=='time' then
			   	
				local opcionesFecha={['formatoFecha']=opciones['formatoFecha'],enlace=opciones.enlace}
		
				return 'post. ' .. require('Módulo:Wikidata/Fecha').FormateaFechaHora(calificativos['P1319'][1].datavalue.value, opcionesFecha)
			end
		end
		
		-- Si no tiene un calificativo válido
		return avisos['somevalue'] -- Valor desconocido
	elseif dato.snaktype == 'novalue' then
		return avisos['novalue'] -- Sin valor
	elseif dato.snaktype == 'value' then
		return formatoValorDato( dato.datavalue, opciones, calificativos) -- Si tiene el tipo de dato se pasa el valor a la función formatDatavalue()
	else
		return formatoError( 'unknown-snak-type' ) -- Tipo de dato desconocido
	end
end

 --[[ =========================================================================
	   Función que establece el tipo de formato en función del tipo de valor
	   (valorDato.type) y en caso de solicitarse un formato complemetario asocia
	   el módulo donde se establece el formato y la función de este que lo establece	
	 ========================================================================= `-- ]]

function formatoValorDato( valorDato, opciones, calificativos)
	local funcion, mensajeError = obtenerFuncion(opciones['valor-función'] or opciones['value-function'] or opciones['funcion'], opciones['valor-módulo'] or opciones['modulo'])
	
	if mensajeError then
		return mensajeError
	elseif funcion then
		local opcionesEntidad = {}
		
		for k, v in pairs(opciones) do
			opcionesEntidad[k] = v
		end
		
		if mw.ustring.find(opciones['formatoTexto'],'mayúscula', plain ) and
		   (primera or (opciones['separador'] and opciones['separador'] ~= 'null') or
		   	(opciones['lista'] and opciones['lista'] ~= '')) then
		  opcionesEntidad['mayúscula'] = 'sí'
			  primera = false
		end	
		
		if mw.ustring.find(opciones['formatoTexto'],'cursivas', plain ) then
			opcionesEntidad.cursivas = 'sí'
		end
		
		return funcion(valorDato.value, opcionesEntidad, marco, calificativos)		
	end

	-- == Formatos por defecto en función del tipo de valor ==

--		   * Con el resto de valores en propiedad

	if valorDato.type == 'wikibase-entityid' then	-- Tipo: Número de entidad que puede ser un ítem o propiedad
		local opcionesEntidad = {}
		if mw.ustring.find(opciones['formatoTexto'],'mayúscula', plain ) and
		   (primera or (opciones['separador'] and opciones['separador'] ~= 'null') or
		   	(opciones['lista'] and opciones['lista'] ~= '')) then
		  opcionesEntidad['mayúscula'] = 'sí'
			  primera = false
		end
		opcionesEntidad.enlace		 = opciones.enlace
		opcionesEntidad.etiqueta	   = opciones.etiqueta
		opcionesEntidad['debeExistir'] = opciones['debeExistir']
		
		if mw.ustring.find(opciones['formatoTexto'],'cursivas', plain ) then
			opcionesEntidad.cursivas = 'sí'
		end
		return p.formatoIdEntidad( SelecionEntidadPorValor( valorDato.value ), opcionesEntidad)
	elseif valorDato.type == 'string' then			   -- Tipo: Cadena de texto (string)
		return valorDato.value
	elseif valorDato.type == 'url' then	 --Tipo URL (dirección web)
		return value.url
	elseif valorDato.type == 'time' then				 -- Tipo: Fecha/hora
		local opcionesFecha={['formatoFecha']=opciones['formatoFecha'],enlace=opciones.enlace}
	  
		if mw.ustring.find(opciones['formatoTexto'] or '','mayúscula', plain ) and primera then
			opcionesFecha['mayúscula']='sí'
		end
		
		return require('Módulo:Wikidata/Fecha').FormateaFechaHora(valorDato.value, opcionesFecha, calificativos)
	elseif valorDato.type == 'monolingualtext' then	   -- Tipo: monolingüe
		if valorDato.value then
			if opciones.idioma then
				for k, v in pairs(valorDato) do
					if v.language == opciones.idioma then
						return v.text
					end
				end
			else
				return valorDato.value.text
			end
		else
			return ''
		end
	elseif valorDato.type ==  'quantity' then			-- Tipo: Cantidad
		return require('Módulo:Wikidata/Formatos').formatoUnidad(valorDato, opciones)
	elseif  valorDato.value['latitude']  and valorDato.value['longitude'] then -- Tipo: Coordenadas



--		  * Para tipo coordenadas cuando se da como valor de propiedad: latitud, longitud o precisión
	if TIPOLLP == 'latitud' then
		return valorDato.value['latitude']
	elseif TIPOLLP == 'longitud' then
		return valorDato.value['longitude']
	elseif TIPOLLP == 'precisión' then
		return valorDato.value['precision']
    else
		local globo = require('Módulo:Wikidata/Globos')[valorDato.value.globe]

--Concatenamos los valores de latitud y longitud dentro de la plantilla Coord

		if globo ~= 'earth' then
			return  marco:preprocess('{{coord|' .. valorDato.value['latitude'] .. '|' ..
				   valorDato.value['longitude'] .. '|globe:' .. globo .. '_type:' .. opciones.tipo .. '|display=' ..
				   opciones.display ..'|formato=' .. opciones.formato..'}}')
		else
			return  marco:preprocess('{{coord|' .. valorDato.value['latitude'] .. '|' ..
				   valorDato.value['longitude'] .. '|type:' .. opciones.tipo .. '|display=' ..
				   opciones.display ..'|formato=' .. opciones.formato..'}}')
		end
    end
	else
		return formatoError( 'unknown-datavalue-type' ) -- Si no es de ninguno de estos tipos devolverá error valor desconocido
	end
end

  --[[ =========================================================================
		  Damos formato a los enlaces internos	
	   ========================================================================= `-- ]]

-- Opciones:
--	 - enlace:		Valores posibles 'sí' o 'no'
--	 - mayúscula:		Valores posibles 'sí' o 'no'
--	 - cursivas:		Valores posibles 'sí' o 'no'

function p.formatoIdEntidad(idEntidad, opciones)
	local enlace   = mw.wikibase.sitelink(idEntidad)
	local etiqueta = mw.wikibase.label(idEntidad)
	return require('Módulo:Wikidata/Formatos').enlazar(enlace, etiqueta, idEntidad, opciones)
end

 --[[ =========================================================================
		Función principal	
	 ========================================================================= `-- ]]

function p.Wikidata( frame )

    TIPOLLP="" --Variable global para identificar los casos de latitud, longitud o precisión
    
	marco = frame
	local args = frame.args
	
	if args.valor == 'no' then
		return
	end

	local parentArgs = frame:getParent().args


	-- Copiar los argumentos
	local argumentos = {}
	
	for k, v in pairs(args) do
		argumentos[k] = v
	end
	
	for k, v in pairs(parentArgs) do
		if not argumentos[k] then
			argumentos[k] = v
		end
	end

    if argumentos[1]=='longitud' or argumentos[1]=='latitud' or argumentos[1]=='precisión' then
       TIPOLLP=argumentos[1]
       marco.args[argumentos[1]]='P625'
    end

	--if true then return require('Módulo:Tablas').tostring(argumentos) end
	
	-- No generar el valor de Wikidata si se ha facilitado un valor local y
	-- el valor local es prioritario.
	local valorWikidata;
	if (args.prioridad ~= 'sí' or (args.importar and args.importar == 'no')) and args.valor and args.valor ~= '' then
		valorWikidata = nil;
	else
		if not mw.wikibase.isValidEntityId(tostring(argumentos.entityId)) then
			argumentos.entityId = mw.wikibase.getEntityIdForCurrentPage() or nil
		end
		valorWikidata = p.getPropiedad(argumentos, nil);
	end
	
 	local categorias = '';
 	local namespace = frame:preprocess('{{NAMESPACENUMBER}}');
 	
 	if (namespace == '0' and (not args.categorias or args.categorias ~= 'no') and
 			args.propiedad and string.upper(args.propiedad) ~= 'P18' -- P18: imagen de Commons
 			and string.upper(args.propiedad) ~= 'P41' -- P41: imagen de la bandera
 			and string.upper(args.propiedad) ~= 'P94' -- P94: imagen del escudo de armas
 			and string.upper(args.propiedad) ~= 'P109' -- P109: firma de persona
 			and string.upper(args.propiedad) ~= 'P154') then -- P154: logotipo
	 	if valorWikidata and valorWikidata ~= '' and args.valor and args.valor ~= '' then
	 		categorias = '[[Categoría:Wikipedia:Artículos con datos locales]]'
	 	elseif valorWikidata and valorWikidata == '' and args.valor and args.valor ~= '' and
	 		(not args.calificador or args.calificador == '') and
	 		(not args.dato or args.dato == '' or args.dato ~= 'fuente') then
	 		categorias = '[[Categoría:Wikipedia:Artículos con datos por trasladar a Wikidata]]'
	 	end
	end

	if args.prioridad == 'sí' and valorWikidata and valorWikidata ~= '' then -- Si se da el valor sí a prioridad tendrá preferencia el valor de Wikidata
		if args.importar and args.importar == 'no' and args.valor and args.valor ~= '' then
			return args.valor .. categorias
		elseif valorWikidata then
			return valorWikidata .. categorias -- valor que sustituye al valor de Wikidata parámetro 2
		else
			return categorias
		end
	elseif args.valor and args.valor ~= '' then
		 return args.valor .. categorias
	elseif args.importar and args.importar == 'no' then
		 return ''
	elseif valorWikidata then -- Si el valor es nil salta una excepcion al concatenar
		return valorWikidata .. categorias
	else
		return ''
  end 
end

function obtenerFuncion(funcion, nombreModulo)
	if not funcion then
		return
	elseif type(funcion) == 'function' then -- Uso desde LUA
		return funcion
	elseif funcion == '' or not nombreModulo or nombreModulo == '' then
		return
	else -- Uso desde una plantilla
		local modulo
		
		if not nombreModulo or nombreModulo == '' or nombreModulo == 'Wikidata/Formatos' then
			modulo = require(modulosTipos[funcion] or 'Módulo:Wikidata/Formatos')
		else
			modulo = require ('Módulo:' .. nombreModulo)
		end
		
	   	if not modulo then
		   	return nil, formatoError( 'value-module-not-found' )
		elseif not modulo[funcion] then
		   	return nil, formatoError( 'value-function-not-found' )
		else
		   	return modulo[funcion]
	   	end
	end
end

function p.addLinkback(valorPropiedad, idEntidad, idPropiedad)
	local lidEntidad
	
	if valorPropiedad and idPropiedad then
		lidEntidad= (idEntidad ~='' and idEntidad) or mw.wikibase.getEntityIdForCurrentPage()
	end

	if lidEntidad then
		return valorPropiedad .. '<span class=\"wikidata-link lapiz noprint\"> [[Archivo:Blue_pencil.svg|Ver y modificar los datos en Wikidata|10px|baseline|alt=Ver y modificar los datos en Wikidata|enlace=https://www.wikidata.org/wiki/' .. lidEntidad .. '?uselang=es#' .. idPropiedad ..
		 ']]</span>'
	else
		return valorPropiedad
	end
end

function p.formatoLista(tabla, opciones)
	if not tabla or not tabla[1] then
		return
	end
	
	local tipo_lista = opciones.lista
	local lapiz
	
	if opciones.linkback == 'sí' and opciones.entityId and opciones.propiedad then
		lapiz = '<span class=\"wikidata-link lapiz noprint\"> [[Archivo:Blue_pencil.svg|Ver y modificar los datos en Wikidata|10px|baseline|alt=Ver y modificar los datos en Wikidata|enlace=https://www.wikidata.org/wiki/' .. opciones.entityId .. '?uselang=es#' .. opciones.propiedad ..
		 ']]</span>'
	else
		lapiz = ''
	end
	
	if not tabla[2] then
		-- Si la tabla solo tiene un elemento devolverlo
		return tabla[1] .. lapiz
	end
	
	if tipo_lista == 'no ordenada' or tipo_lista == 'ordenada' or tipo_lista == 'nobullet' then
		local lista = mw.text.listToText( tabla, '</li><li>', '</li><li>' )
		
		if tipo_lista == 'no ordenada' then
			return '<ul><li>' .. lista .. lapiz .. '</li></ul>'
		elseif tipo_lista == 'ordenada' then
			return '<ol><li>' .. lista .. lapiz .. '</li></ol>'			
		else
			return '<ul style="list-style-type:none;list-style-image:none;margin-left:0;padding-left:0"><li>' .. lista .. lapiz .. '</li></ul>'
		end
	else
		local separadores = {
			[''] = '',
			[','] = ', ',
			['null'] = ', ',
			['no'] = ''
		}
		local conjunciones = {
			[''] = '',
			['y'] = ' y ',
			['o'] = ' o ',			
			['null'] = ' y ',
			['no'] = ''
		}
		
		local separador = opciones.separador
		local conjuncion = opciones['conjunción']
		
		if not separador then
			separador = ', '
		else
			separador = separadores[separador] or separador
		end
		
		if not conjuncion then
			conjuncion = ' y '
		else
			conjuncion = conjunciones[conjuncion] or conjuncion
		end
		
		if conjuncion == ' y ' and marco and tabla[2] then
			conjuncion = ' ' .. marco:preprocess('{{y-e|{{Desvincular|' .. tabla[#tabla] .. '}}|sin texto}}') .. ' '
		end
		
		return mw.text.listToText( tabla, separador, conjuncion ) .. lapiz
	end
end

-- Funciones existentes en otros módulos
function p.obtenerEtiquetaWikidata(entidad, fallback)
	if not entidad then entidad = fallback end
	if entidad and entidad.labels and entidad.labels.es then
		return entidad.labels.es.value
	end
end

function p.obtenerImagenWikidata(entidad, propiedad)
	local imagen, valorImagen, piesDeImagen, k, pieDeImagen
	if not entidad then
		return
	end
	
	--  Obtener la primera imagen en Wikidata de la persona
	local imagen = elementoTabla(entidad, 'claims', propiedad, 1)
--[[	
	-- Obtener el objeto de imagen, ya sea la primera, la última (WIP) o por fecha (WIP)
	local imagen = (function()
		local ImagenObj = elementoTabla(entidad, 'claims', idPropiedad)
		if opciones.ordenar == 'por fecha' then
			--
		end

		return elementoTabla(ImagenObj, 1)
	end)()
--]]
	if not imagen then
		return
	end
	valorImagen =  elementoTabla(imagen, 'mainsnak', 'datavalue', 'value')
	piesDeImagen =  elementoTabla(imagen, 'qualifiers', 'P2096')
	-- Encontrar el pie en español
	if piesDeImagen then
		for k,pieDeImagen in pairs(piesDeImagen) do
			if pieDeImagen.datavalue.value.language == 'es' then
				return valorImagen, pieDeImagen.datavalue.value.text
			end
		end
	end
	-- Si no hay pie de imagen en español comprueba si hay fecha especificada para la imagen
	piesDeImagen = elementoTabla(imagen, 'qualifiers', 'P585')
	if piesDeImagen and piesDeImagen[1] then
		return valorImagen, 'En ' .. require('Módulo:Wikidata/Fecha').FormateaFechaHora(piesDeImagen[1].datavalue.value, {['formatoFecha']='año',['enlace']='no'})
	end
	-- Sin pie de imagen en español
	return valorImagen
end

function p.propiedad(entidad, idPropiedad, opciones)
	if entidad and entidad.claims and entidad.claims[idPropiedad] then
		if not opciones then
			opciones = {['linkback']='sí'}
		end
		--[[
		local ValorPosicional = (function()
			if opciones['valor_posicional'] == 'último' then return -1 end
			if type(opciones['valor_posicional']) == 'number' then return opciones['valor_posicional'] end
			return 1
		end)()

		local ValorPosicionalCalif =(function()
			if opciones['valor_posicional_calif'] == 'último' then return -1 end
			if type(opciones['valor_posicional_calif']) == 'number' then return opciones['valor_posicional_calif'] end
			return 1
		end)()
		
		local Calificador = opciones['calificador']

		local Obj = (function()
			local Obj = (function()
				local Obj = elementoTabla(entidad, 'claims', idPropiedad)
				if ValorPosicional == -1 then return elementoTabla(Obj, #Obj) end
				return elementoTabla(Obj, ValorPosicional)
			end)()

			if Calificador then
				Obj = (function()
					local Obj = elementoTabla(Obj, 'qualifiers', Calificador)
					if ValorPosicionalCalif == -1 then return elementoTabla(Obj, #Obj) end
					return elementoTabla(Obj, ValorPosicionalCalif)
				end)()
			end
			return Obj
		end)()
		
		Tipo	= elementoTabla(Obj, 'datavalue', 'type')
		
		-- Devolver el ID de la entidad, para propiedades de entidad
		if opciones['formato'] == 'entidadID' then
			return elementoTabla(Obj, 'datavalue', 'value', 'id')
		end
		
		-- Preparar para devolver el archivo más reciente en la propiedad. Buscar cómo hacerlo con los calificadores
		if opciones['formato'] == 'archivo' then
			if Calificador then return elementoTabla(Obj, 'datavalue', 'value') end
			if not opciones['uno'] then opciones['uno'] = 'último' end
			opciones['ordenar'] = 'por fecha'
		end

		-- Obtener la propiedad como cadena sin formato
		if opciones['formato'] == 'cadena' then
			opciones['linkback'] = 'no'
			if Tipo == 'string' then
				return elementoTabla(Obj, 'datavalue', 'value')
			end
		end

		-- Devolver una cadena numérica correctamente formateada
		if opciones['formato'] == 'número' then
			if Tipo == 'quantity' then
				return formatoNumero(elementoTabla(Obj, 'datavalue', 'value', 'amount'))
			end
		end

		-- Devolver una cadena numérica con su unidad
		if opciones['formato'] == 'unidad' then
			if elementoTabla(entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue') then
				return formatoNumero(elementoTabla(entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue', 'value', 'amount')) .. '&nbsp;-&nbsp;' .. numeroUnidad(elementoTabla(entidad, 'claims', idPropiedad, 2, 'mainsnak', 'datavalue'), opciones)
			else
				return numeroUnidad(elementoTabla(entidad, 'claims', idPropiedad, 1, 'mainsnak', 'datavalue'), opciones)
			end
		end
		--]]
		
		opciones.entityId  = entidad.id
		opciones.propiedad = idPropiedad
		
		return p.getPropiedad(opciones, entidad.claims[idPropiedad])
	end
end

function p.esUnValor(entidad, idPropiedad, idaBuscar)
	if not entidad or not idPropiedad then
		return false
	end
	
	local declaracion = elementoTabla(entidad, 'claims', idPropiedad)
	local idBuscado
	if not declaracion then
		return false
	end

	for k,v in pairs(declaracion) do
		idBuscado = elementoTabla(v,'mainsnak','datavalue','value','id')
		if idBuscado == idaBuscar then
			return true
		end
	end
	return false
end

-- Obtener el objeto mw.language, para usar sus funciones en otros módulos
function p.language()
	return es
end

return p