Módulo:Wikidata

Desde Chavacano de Zamboanga Wikipedia - El Libre Enciclopedia

Methods[revisa codigo]

The module "Wikidata" contains the following methods, that allow the calling script to retrieve the value for any property from Wikidata by supplying the property ID as the first parameter:

  • getValue: Returns wiki-linked values, if applicable. All other values will be output similar to {{#property:}}, except that if values with preferred rank exist, then only they are returned. Unlike formatStatements from ru:Модуль:Wikidata, getValue does not yet pick up any references (see Module talk:Wikidata/Archive 1#Why the references from Wikidata get dropped?).
  • getRawValue: Returns non-linked property values and numbers with the thousand separator. It also returns the plain numeric value of a property which is a quantity. All other values will be output similar to {{#property:}}, including normal values, even if preferred values exist.
  • getDateValue: Special method to return formatted dates. The default date format is [day month year]; an optional third parameter can be added for other date formats: for [month day, year], add "mdy"; for [month year], add "my"; for year only, add "y". A further optional parameter, which must be fourth, such as "BCE", may be added to override the default "BC" that is suffixed for dates BC.
  • getImages: Returns all of the images of a particular property, e.g. image (P18), Gene Atlas Image (P692), etc. Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=220px). The returned text will be in the format [[File:Filename | size]] for each image with a selectable size and separator (which may be html). If a property is supplied that is not of type "commonsMedia", it will return empty text.
  • getUnits This takes a propertyID which is a quantity as the first parameter, and returns the name of the units that the property is using on the current page. It returns empty if the property is not a quantity type or if the value is not set. The second parameter may be used to override fetching from Wikidata, if it is anything other than "FETCH_WIKIDATA".
  • getUnitID This takes a propertyID which is a quantity as the first parameter, and returns the QID of the units that the property is using on the current page. It returns empty if the property is not a quantity type or if the value is not set. The second parameter may be used to override fetching from Wikidata, if it is anything other than "FETCH_WIKIDATA".

Wikidata qualifier values (if present) can be retrieved by the following methods:

  • getQualifierValue: returns only wiki-linked values, if applicable.
  • getRawQualifierValue: returns non-linked values
  • getQualifierDateValue: returns formatted dates

If the property is not defined in Wikidata for the article that invokes this code, then an empty string ("") is returned.

Other methods:

  • pageId: returns the Wikidata id (Q…) of the current page or nothing if the page is not connected to Wikidata. To get the Wikidata id of another page, use {{#invoke:ResolveEntityId|page}}.
  • getTAValue: gets the TA98 (Terminologia Anatomica first edition 1998) values for property P1323. It takes no parameters and constructs its output as a list, with each value linked to an external resource. This is an exemplar for writing calls that need to return external links.
  • ViewSomething: gets anything in the structured data, including labels, descriptions, references and interwiki links. See [1]
  • getSiteLink: gets name of a page in given in argument wiki (like "enwikiquote" for English Wikiquote, "arwiki" for the Arabic Wikipedia).
  • Dump: {{#invoke:Wikidata|Dump|claims}} spies the structured data. It uses the same arguments as ViewSomething. Try this with preview only to see results. That helps you a lot in developing Lua scripts that access the data. If used without arguments, it dumps everything including labels, descriptions, references and interwiki links. There is the wrapper template, see {{Dump}}.
  • getImageLegend: returns an image legend (image is property P18; image legend is property P2096).
    Call as {{#invoke:Wikidata |getImageLegend | <PARAMETER> | lang=<ISO-639code> |id=<QID>}}
    Returns PARAMETER, unless it is equal to "FETCH_WIKIDATA", from Item QID (expensive call). If QID is omitted or blank, the current article is used (not an expensive call). If lang is omitted, it uses the local wiki language, otherwise it uses the provided ISO-639 language code.
    The label is returned from the first image with 'preferred' rank; or from the first image with 'normal' rank if no image has preferred rank.
  • getValueShortName: returns the same data as getValue, but utilizes the property short name as the label, if available. This allows for piped links to use a shorter label where preferred. If short name is not set on the item, the normal label is used.

Arbitrary Access[revisa codigo]

As of 16 September 2015, it is now possible to fetch data from other articles by using their QID. The following call:

  • {{#invoke:Wikidata|getValueFromID|<QID>|<Property>|FETCH_WIKIDATA}}

will do the same as getValue, but takes an extra parameter, which is the QID of the Wikidata item that you want to get the property value from. For example:

  • {{#invoke:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}}

will fetch a list of the linked values for 'spouse' (P26) from 'Richard Burton' (Q151973) from anywhere in the English Wikipedia.

This means that testing environments may be set up in user space, but remember that these calls are classed as expensive, so please use them as sparingly as possible.

Parameters[revisa codigo]

  • For the generalized case (getValue), two unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. P19 for birthplace or P26 for spouse). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value.
  • For the generalized unlinked case (getRawValue), two unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. P21 for gender). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value.
  • For the generalized date case (getDateValue), three unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. P569 for date of birth). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value. The third is the format that the date should be returned in, either dmy, mdy, my, or y.

Please note that lower-case parameters are no longer supported by the wikibase call: p123, so please check that upper-case, like P123, is used if problems should arise.

Usage[revisa codigo]

Example: spouse (P26)[revisa codigo]

  • {{#invoke:Wikidata|getValue|P26|}} = returns nothing, so suppresses the display of spouse in an infobox
  • {{#invoke:Wikidata|getValue|P26|FETCH_WIKIDATA}} = returns the linked value(s) of property P26 (spouse) stored in wikidata for the corresponding article (e.g. for article Bill Clinton, it returns Hillary Clinton)
  • {{#invoke:Wikidata|getValue|P26|[[Hillary Rodham Clinton]]}} = returns Hillary Rodham Clinton, allowing an infobox to use a local value rather than the value stored in Wikidata.

Example in Infobox template[revisa codigo]

Inside an infobox definition, it may be called like this:

  • | data55 = {{#invoke:Wikidata|getValue|P26|{{{spouse|FETCH_WIKIDATA}}} }}

which causes the infobox to:

  1. not display spouse if the infobox parameter |spouse is set to be blank (as "| spouse ="}
  2. display the linked value(s) from Wikidata if the infobox parameter |spouse is not supplied
  3. display the local infobox parameter |spouse if it is supplied (e.g. "|spouse = Hillary Rodham Clinton")

Optionally, it could be called as:

  • | data55 = {{#invoke:Wikidata|getValue|P26|{{{spouse|}}} }}

which causes the infobox to:

  1. not display spouse if the infobox parameter |spouse is set to be blank (as "| spouse ="}
  2. not display spouse if the infobox parameter |spouse is not supplied
  3. display the local infobox parameter |spouse if it is supplied (e.g. "|spouse = Hillary Rodham Clinton")
  4. display the linked value(s) from Wikidata if the infobox parameter is locally set to FETCH_WIKIDATA

See Module:WikidataIB for a modification that allows fields, on a per article basis, to be blacklisted so that they never display. It also allows the editor to specify, on a per article basis, which fields may be automatically fetched from Wikidata when local parameter is supplied; the default is none, allowing an infobox to be modified to accept Wikidata without any change in the articles using the infobox until the functionality is enabled in the article.

Example:birth place[revisa codigo]

This works in just the same way as the calls above:

  • {{#invoke:Wikidata|getValue|P19|}} = returns nothing, so suppresses the display of birth place in an infobox
  • {{#invoke:Wikidata|getValue|P19|FETCH_WIKIDATA}} = returns the linked value(s) of property P19 (place of birth) stored in wikidata for the corresponding article (e.g. for article Bill Clinton, it returns Hope, Arkansas)
  • {{#invoke:Wikidata|getValue|P19|[[Hope, Arkansas|Hope]]}} = returns Hope, allowing an infobox to use a local value rather than the value stored in Wikidata.

Example:gender[revisa codigo]

We don't want the returned value linked, so use:

  • - {{#invoke:Wikidata|getRawValue|P21|FETCH_WIKIDATA}}

Example:date of birth[revisa codigo]

If we want the date of birth in dmy format, we use:

  • - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|dmy}}

If we want the date of birth in mdy format, we use:

  • - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|mdy}}

If we want a year of birth, we use:

  • - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|y}}

If we want a year of birth that may be BC, but should read "BCE", we use:

  • - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|y|BCE}}

Example: Linking to Wikidata item[revisa codigo]

Use the following code to just retrieve the Q-ID:

  • - {{#invoke:Wikidata|pageId}}

Linking to Wikidata used the usual Wiki markup:

  • - [[d:{{#invoke:Wikidata|pageId}}|Name of Link]]

Example: Linking to another wiki page[revisa codigo]

Use code like this to link to another wiki. English Wikivoyage in the example:

  • - [[voy:{{#invoke:Wikidata|getSiteLink|enwikivoyage}}|Name of Link]]


Testing[revisa codigo]

Testing spouse[revisa codigo]

Copy and paste the following into any article and preview it (please don't save!):

 * - {{#invoke:Wikidata|getValue|P26|}}
 * - {{#invoke:Wikidata|getValue|P26|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getValue|P26|[[Hillary Rodham Clinton]]}}

In Bill Clinton you should get:


In Barack Obama you should get:


In Richard Burton you should get:


In Franz Kafka you should get:

Testing birthplace[revisa codigo]

Copy and paste the following into any article and preview it (please don't save!):

 * - {{#invoke:Wikidata|getValue|P19|}}
 * - {{#invoke:Wikidata|getValue|P19|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getValue|P19|[[Newport]]}}

Try William Ellery and check that the Wikidata call correctly disambiguates.

Testing getValue, getRawValue and getDateValue[revisa codigo]

Copy and paste the following into any article and preview it (please don't save!):

 * - {{#invoke:Wikidata|getValue|P19|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getValue|P26|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getValue|P27|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getValue|P140|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getRawValue|P21|FETCH_WIKIDATA}}
 * - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|dmy}}
 * - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|mdy}}
 * - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|y}}

This should return the Wikidata values for birthplace, spouse, citizenship, religion, gender, date of birth (twice) and year of birth, if they exist. The dob is first in dmy format and then in mdy.

Testing dates BC/BCE[revisa codigo]

Copy and paste the following into a short section of article such as Horace #See also and preview it (please don't save!):

 * - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|y}}
 * - {{#invoke:Wikidata|getDateValue|P569|FETCH_WIKIDATA|y|BCE}}

This should return 65 BC and 65 BCE, respectively.

See also[revisa codigo]


--[[*********************************************************************************
	* 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 = {
	["errores"] = {
		["property-param-not-provided"] = "Parámetro de la propiedad no proporcionado.",
		["entity-not-found"] = "Entrada no encontrada.",
		["unknown-claim-type"] = "Tipo de notificación desconocida.",
		["unknown-snak-type"] = "Tipo de dato desconocido.",
		["unknown-datavalue-type"] = "Formato de dato desconocido.",
		["unknown-entity-type"] = "Tipo de entrada desconocido.",
		["unknown-value-module"] = "Debe ajustar ambos parámetros de valor y el svalor del módulo de funciones.",
		["value-module-not-found"] = "No se ha encontrado el módulo apuntado por valor-módulo.",
		["value-function-not-found"] = "No se ha encontrado la función apuntada por valor-función.",
		["other entity"] = "Enlaces a elementos diferentes desactivado."
	},
	["somevalue"] = "''valor desconocido''",
	["novalue"] = ""
}

-- 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	=  {
	['altura']		= 'Módulo:Wikidata/Formato magnitud',
	['área']		= 'Módulo:Wikidata/Formato magnitud',
	['bandera']		= 'Módulo:Wikidata/Formatos país',	
	['educado en']	= 'Módulo:Wikidata/Formatos educación',
	['imagen']		= 'Módulo:Wikidata/Formato imagen',
	['lugar']		= 'Módulo:Wikidata/Formato lugar',
	['formatoLugar']= 'Módulo:Wikidata/Formato lugar',
	['magnitud']	= 'Módulo:Wikidata/Formato magnitud',
	['movimiento']	= 'Módulo:Wikidata/Formato movimiento',	
	['periodicidad']= 'Módulo:Wikidata/Formato magnitud',
	['premio']		= 'Módulo:Wikidata/Formato premio',
}

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	 = {}
	local tablaOrdenada = {}

	-- Resolver alias de propiedad
	if opciones.propiedad == 'precisión' or opciones.propiedad == 'latitud' or opciones.propiedad == 'longitud'  then --latitud, longitud o precisión
		-- Tierra
		propiedad = 'P625' 
		
		-- Luna
        if mw.wikibase.getEntityObject() and mw.wikibase.getEntityObject():formatPropertyValues("p376")["value"] == 'Luna' then
	    	propiedad = 'P8981'
        end 
	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

	if declaracion then
		tablaOrdenada = declaracion
	elseif not p.getDeclaraciones(opciones.entityId) then
		return formatoError( 'other entity' )
	elseif p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)] then
		tablaOrdenada = p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)]
	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
	
	-- 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.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 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 = '';
	else
		local ent = SelecionEntidadPorId(argumentos.entityId)
		argumentos.entityId = ent and ent.id or nil
		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 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  ~= '' 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