Wikidata

De musiki

La documentación para este módulo puede ser creada en Módulo:Wikidata/doc

Error de secuencia de órdenes: Error de Lua: Error interno: El intérprete ha finalizado con el estado 127.

--[[*********************************************************************************
    * 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|{{Desvincular|' .. 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

-- 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 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 .. '<span class=\"wikidata-link 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
 
return p