Módulo:Wikidata

De Wikipedia, la enciclopedia libre
Ir a la navegación Ir a la búsqueda
Icono de documentación de módulo Documentación del módulo[ver] [editar] [historial] [purgar]

A continuación se muestra la documentación transcluida desde la subpágina /doc. [salta a la caja de código]


Uso

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

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

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

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 "español".
  • =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:
  1. español
  2. gallego
  3. euskera
  4. catalán
  5. occitano
  • =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:
  • 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 "español, gallego, euskera, catalán y occitano"
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 "español/gallego/euskera/catalán/occitano".

Funciones específicas para el formato

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 Ejemplos de propiedades de Wikidata
altura Formato magnitud Se muestra la altura junto a sus unidades y en su caso entre paréntesis el valor en el sistema internacional. altura (P2048)
área Formato magnitud Se muestra el área junto a sus unidades y en su caso entre paréntesis el valor en el sistema internacional. superficie (P2046)
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. educado en (P69)
imagen Formato imagen imagen (P18)
lugar Formato lugar Formato para lugares de la forma ciudad, unidad administrativa, país lugar de nacimiento (P19), lugar de fallecimiento (P20)
movimiento Formato movimiento Formato para movimientos movimiento (P135)
periodicidad Formato magnitud Se muestra la periodicidad (anual, mensual, quincenal, semanal, etc). periodicidad (P2896)
premio Formato premio Formato para premios de obras eliminando los literales de la forma " a ...", " a la ..." o " en la categoría ...". premio recibido (P166)

Valores devueltos

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

Función getDeclaraciones

Para ser usado en otro módulos.

Valores devueltos

Devuelve una tabla con todas las declaraciones del elemento

Función getPropiedad

Para ser usado en otros módulos.

Parámetros

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

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

Función setFrame

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

frame

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

Valores devueltos

Ninguno.

Función addLinkback(texto, identificador de la entidad, identificador de la propiedad)

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


Esta documentación está transcluida desde Módulo:Wikidata/doc.
Por favor, añade las categorías en la subpágina de documentación y los interwikis en Wikidata. Subpáginas de este módulo.
--[[*********************************************************************************
    * 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: 6 de septiembre de 2014.
    *
    * 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 valor 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',
	['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',
}
	
	
 --[[ =========================================================================
      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 filtrarDeclaracionPorRango(tablaDeclaraciones)
    local rango = getRango(tablaDeclaraciones)
    local tablaAuxiliar = tablaDeclaraciones
    tablaDeclaraciones = {}
 
    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
	
	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
					value = datavalue.value
					
					if value then
						return value.time
					end
				end
			end
		end
	end
end     
 
function p.getPropiedad(opciones, declaracion)
    local propiedad     = {}
    local tablaOrdenada = {}

    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 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

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

    --Dejar en su caso los valores de mayor rango
    if (opciones.rangoMayor == 'sí') then
        tablaOrdenada = filtrarDeclaracionPorRango(tablaOrdenada)
    end

    --Ordenar en su caso por fecha. Ver 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
    
    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
    if opciones['lista'] == 'no ordenada' then
    	-- Añadir en su caso un lápiz
    	if opciones.linkback == 'sí' then
    		return '<ul><li>' .. p.addLinkback(mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ), opciones.entityId, opciones.propiedad) .. '</li></ul>'
    	else
        	return '<ul><li>' .. mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ) .. '</li></ul>'
        end
    elseif opciones['lista'] == 'ordenada' then
    	-- Añadir en su caso un lápiz
		if opciones.linkback == 'sí' then
        	return '<ol><li>' .. p.addLinkback(mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ), opciones.entityId, opciones.propiedad) .. '</li></ol>'            			
		else
        	return '<ol><li>' .. mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ) .. '</li></ol>'            
        end
    else
     	-- valores separados por coma o por el separador y la
      	-- conjunción de las opciones
       	local separador, conjuncion
        	
        if opciones['conjunción'] == 'null' then
            conjuncion = nil
        else
            conjuncion = opciones['conjunción'] 
        end
    
        if opciones['separador'] == 'null' then
            separador	= nil
        else
            separador = opciones['separador']
        end
        
        if table.getn(formatoDeclaraciones) > 1 then
        	if not conjuncion then
        		conjuncion = 'y'
        	end
        	if marco and conjuncion == 'y' then
        		conjuncion = ' ' .. string.sub(marco:preprocess('{{y-e|{{desenlazar|' .. formatoDeclaraciones[#formatoDeclaraciones] .. '}}}}'), 1, 1) .. ' '
        	elseif conjuncion == 'y' or conjuncion == 'o' then
        		conjuncion = ' ' .. conjuncion .. ' '
        	end
        end
        
        -- Añadir en su caso un lápiz
    	if opciones.linkback == 'sí' then
			return p.addLinkback(mw.text.listToText( formatoDeclaraciones, separador,conjuncion ), opciones.entityId, opciones.propiedad)  		
    	else
        	return mw.text.listToText( formatoDeclaraciones, separador,conjuncion )
        end
    end
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

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 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)
    		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'], opciones['valor-módulo'])
	
	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 ==
 
--          * Para tipo coordenadas cuando se da como valor de propiedad: latitud, longitud o precisión
 
    if opciones.propiedad == 'latitud' then 
        return valorDato.value['latitude']
    elseif opciones.propiedad == 'longitud' then
        return valorDato.value['longitude']
    elseif opciones.propiedad == 'precisión' then
        return valorDato.value['precision']
 
--           * Con el resto de valores en propiedad
 
    elseif 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: monoligüe
    	if valorDato.value then
            return valorDato.value.text
        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
    	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
 
    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 )
    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 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
    	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 .. ' [[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 ..
    	 ']]'
    else
    	return valorPropiedad
    end
end
 
return p