Módulo:Wikidata

En Galifontes, o Wikisource en galego.
Indicacións de uso do módulo

Aínda non se redactaron as instrucións sobre como usar este módulo.
Engadir a explicación sobre o seu uso.

Os editores poden probar cambios no mesmo en Módulo:Wikidata/probas.
Por favor, engade as categorías na subpáxina de documentación e os interwikis no Wikidata. Ver as subpáxinas deste módulo.
--[[*********************************************************************************
    * Nome: Módulo:Wikidata
    *
    * Descrición: Este módulo devolve o valor ou valores con ou sen formato específico
    *             a unha propiedade de Wikidata.
    *
    * Data última revisión: 6 de setembro de 2014.
    *if
    * Estado: En uso.
    * Nota: Adaptado de es.wiki
    *********************************************************************************`-- ]]

local p = {}
local es = mw.language.new('gl')
local primera = true
local marco

 --[[ =========================================================================
            Mensaxes de erro
      ========================================================================= `-- ]]

local avisos = {
    ["errores"] = {
        ["property-param-not-provided"] = "Parámetro da propiedade non proporcionado.",
        ["entity-not-found"] = "Entrada non atopada.",
        ["unknown-claim-type"] = "Tipo de notificación descoñecida.",
        ["unknown-snak-type"] = "Tipo de dato descoñecido.",
        ["unknown-datavalue-type"] = "Formato de dato descoñecido.",
        ["unknown-entity-type"] = "Tipo de entrada descoñecida.",
        ["unknown-value-module"] = "Debe axustar ambos parámetros de valor e o valor do módulo de funcións.",
        ["value-module-not-found"] = "Non se atopou o módulo apuntado por valor-módulo.",
        ["value-function-not-found"] = "Non se atopou a función apuntada por valor-función.",
        ["other entity"] = "Ligazóns a elementos diferentes desactivado."
    },
    ["somevalue"] = "''valor descoñecido''",
    ["novalue"] = ""
}

local elementoTabla = require('Módulo:Táboas').elemento

-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
-- Función copiada de Module:Wikidata de en.wiki devolve o identificador Q da páxina actual ou nada se a páxina non 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

-- Función copiada de Module:Wikidata de en.wiki
local function findClaims(entity, property)
	if not property or not entity or not entity.claims then return end

	if mw.ustring.match(property, "^P%d+$") then
		-- if the property is given by an id (P..) access the claim list by this id
		return entity.claims[property]
	else
		property = mw.wikibase.resolvePropertyId(property)
		if not property then return end

		return entity.claims[property]
	end
end

-- Función copiada de Module:Wikidata de en.wiki
function p.claim(frame)
	local property = frame.args[1] or ""
	local id = frame.args["id"]
	local qualifierId = frame.args["qualifier"]
	local parameter = frame.args["parameter"]
	local list = frame.args["list"]
	local references = frame.args["references"]
	local showerrors = frame.args["showerrors"]
	local default = frame.args["default"]
	if default then showerrors = nil end

	-- get wikidata entity
	local entity = mw.wikibase.getEntityObject(id)
	if not entity then
		if showerrors then return printError("entity-not-found") else return default end
	end
	-- fetch the first claim of satisfying the given property
	local claims = findClaims(entity, property)
	if not claims or not claims[1] then
		if showerrors then return printError("property-not-found") else return default end
	end

	-- get initial sort indices
	local sortindices = {}
	for idx in pairs(claims) do
		sortindices[#sortindices + 1] = idx
	end
	-- sort by claim rank
	local comparator = function(a, b)
		local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
		local ranka = rankmap[claims[a].rank or "normal"] .. string.format("%08d", a)
		local rankb = rankmap[claims[b].rank or "normal"] .. string.format("%08d", b)
		return ranka < rankb
	end
	table.sort(sortindices, comparator)

	local result
	local error
	if list then
		local value
		-- iterate over all elements and return their value (if existing)
		result = {}
		for idx in pairs(claims) do
			local claim = claims[sortindices[idx]]
			value, error = getValueOfClaim(claim, qualifierId, parameter)
			if not value and showerrors then value = error end
			if value and references then value = value .. getReferences(frame, claim) end
			result[#result + 1] = value
		end
		result = table.concat(result, list)
	else
		-- return first element
		local claim = claims[sortindices[1]]
		result, error = getValueOfClaim(claim, qualifierId, parameter)
		if result and references then result = result .. getReferences(frame, claim) end
	end

	if result then return result else
		if showerrors then return error else return default end
	end
end


function p.traballoFemenino_wikidata(frame)
    marco = frame
    local args = frame.args
	-- Para las ocupaciones más frecuentes no se accederá a Wikidata
	local tablaOcupacionesFemeninas={
		['Q40348'   ] = 'abogada',
		['Q16631371'] = 'académica',
		['Q15253558'] = 'activista',
		['Q1476215' ] = 'activista por los derechos humanos',
		['Q33999'   ] = 'actriz',
		['Q10800557'] = 'actriz de cine',
		['Q11481802'] = 'actriz de doblaje',
		['Q948329'  ] = 'actriz de género',		
		['Q2259451' ] = 'actriz de teatro',
		['Q10798782'] = 'actriz de televisión',
		['Q2405480' ] = 'actriz de voz',
		['Q488111'  ] = 'actriz pornográfica',
		['Q10873124'] = 'ajedrecista',
		['Q4773904' ] = 'antropóloga',			
		['Q2478141' ] = 'aristócrata',		
		['Q42973'   ] = 'arquitecta',
		['Q483501'  ] = 'artista',
		['Q7019111' ] = 'asistenta social',
		['Q11063'   ] = 'astrónoma',		
		['Q18814623'] = 'autobiógrafa',		
		['Q482980'  ] = 'autora',
		['Q5716684' ] = 'bailarina',
		['Q805221'  ] = 'bailarina de ballet',		
		['Q864503'  ] = 'bióloga',
		['Q8246794' ] = 'bloguera',		
		['Q177220'  ] = 'cantante',
		['Q2865819' ] = 'cantante de ópera',
		['Q488205'  ] = 'cantautora',		
		['Q901'     ] = 'científica',
		['Q15212951'] = 'cineasta',
		['Q1086863' ] = 'columnista',		
		['Q245068'  ] = 'comediante',
		['Q36834'   ] = 'compositora',
		['Q2722764' ] = 'conductora radiofónica',		
		['Q2490358' ] = 'coreógrafa',
		['Q18939491'] = 'diarista',
		['Q193391'  ] = 'diplomática',
		['Q2526255' ] = 'directora de cine',
		['Q5322166' ] = 'deseñadora',
		['Q627325'  ] = 'deseñadora gráfica',
		['Q462390'  ] = 'docente',
		['Q214917'  ] = 'dramaturga',
		['Q188094'  ] = 'economista',
		['Q974144'  ] = 'educadora',
		['Q131524'  ] = 'emprendedora',
		['Q43845'   ] = 'empresaria',
		['Q186360'  ] = 'enfermera',
		['Q11774202'] = 'ensayista',		
		['Q36180'   ] = 'escritora',
		['Q4853732' ] = 'escritora de literatura infantil',
		['Q1281618' ] = 'escultora',
		['Q11900058'] = 'exploradora',		
		['Q13472585'] = 'filántropa',
		['Q4964182' ] = 'filósofa',
		['Q169470'  ] = 'física',		
		['Q33231'   ] = 'fotógrafa',
		['Q28389'   ] = 'guionista',
		['Q201788'  ] = 'historiadora',
		['Q715301'  ] = 'historietista',		
		['Q82594'   ] = 'informática teórica',
		['Q16533'   ] = 'jueza',
		['Q185351'  ] = 'jurista',
		['Q644687'  ] = 'ilustradora',
		['Q14467526'] = 'lingüista',				
		['Q1371925' ] = 'locutora',		
		['Q2251335' ] = 'maestra',		
		['Q191633'  ] = 'mangaka',
		['Q170790'  ] = 'matemática',
		['Q39631'   ] = 'médica',
		['Q4610556' ] = 'modelo',
		['Q639669'  ] = 'música',
		['Q6625963' ] = 'novelista',
		['Q1930187' ] = 'periodista',
		['Q1028181' ] = 'pintora',
		['Q728711'  ] = 'playmate',
		['Q49757'   ] = 'poeta',		
		['Q82955'   ] = 'política',
		['Q270389'  ] = 'presentadora de noticias',
		['Q947873'  ] = 'presentadora de televisión',		
		['Q3282637' ] = 'productora de cine',
		['Q37226'   ] = 'profesora',
		['Q121594'  ] = 'profesora',
		['Q16145150'] = 'profesora de música',
                ['Q1622272' ] = 'profesora de universidad',
		['Q212980'  ] = 'psicóloga',
		['Q3242115' ] = 'revolucionaria',
		['Q3068305' ] = 'salonnière',		
		['Q622807'  ] = 'seiyū',
		['Q512314'  ] = 'socialité',		
		['Q2306091' ] = 'socióloga',
		['Q1141526' ] = 'stripper',		
		['Q1234713' ] = 'teóloga',		
		['Q333634'  ] = 'traductora',
		['Q350979'  ] = 'zoóloga',
	}
	
	local etiquetaOcupacionCorregida = tablaOcupacionesFemeninas[args.traballo]
	
 --       return etiquetaOcupacionCorregida 
          return 'traballo recibido: ' .. args.traballo        -- non concateno co de arriba pq da erro xa que é nil, mostra "veterinario e primatólogo"

end

-- Función que devolve o valor de entidad.claims[idPropiedad][ocurrencia].mainsnak.datavalue.value.text
-- con entidad.claims[idPropiedad][ocurrencia].mainsnak.datavalue.value.language = 'gl'

-- Útil para obter valores de propiedades de tipo monolingualtext
-- Adaptada de es.wiki. Gardamos de novo.

function p.getPropiedadEnGalego(frame)
    marco = frame
    local args = frame.args
--(idEntidade, idPropiedade)
	-- Ver cs:Modul:Wikidata/item	formatEntityWithGender
	
	-- 
	local entidade =  mw.wikibase.getEntityObject(args.idEntidade)
	
	if not entidade then
		return
	end
	
	local declaracion   = elementoTabla(entidade,'claims', args.idPropiedade)
	
	if not declaracion then
		return 'non atopou 2'
	end
	
	local valor
	
	for k,v in pairs(declaracion) do
		valor = elementoTabla(v,'mainsnak', 'datavalue', 'value')
		
		if valor.language == 'gl' then
			return valor.text
		end
	end
end

 --[[ =========================================================================
      Función para pasar o frame cando se usa noutros módulos.
     ========================================================================= `-- ]]
function p:setFrame(frame)
	marco = frame
end


 --[[ =========================================================================
      Función para identificar o ítem correspondente á páxina ou outro dado.
              Isto último aínda non 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 se o valor devolto é un ítem ou unha propiedade
      e en función diso engade o prefixo correspondente
     ========================================================================= `-- ]]

function SelecionEntidadPorValor( valor )
    local prefijo = ''
    if valor['entity-type'] == 'item' then
        prefijo = 'q' -- Prefixo de ítem
    elseif valor['entity-type'] == 'property' then
        prefijo = 'p' -- Prefixo de propiedade
    else
        return formatoError( 'unknown-entity-type' )
    end
    return prefijo .. valor['numeric-id'] -- Concaténase o prefixo e o código numérico
end

 --[[ =========================================================================
      Función auxiliar para dar formato ás mensaxes de erro
     ========================================================================= `-- ]]

function formatoError( clave )
    return '<span class="error">' .. avisos.errores[clave] .. '</span>'
end
 --[[ =========================================================================
      Función para determinar o rango
     ========================================================================= `-- ]]
function p.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 a declaración ou declaracións de maior 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 o tipo de declaración: Referencia, valor principal
      ou cualificador
     ========================================================================= `-- ]]

function seleccionDeclaracion(declaracion, opciones)
    local fuente = {}
    local propiedadFuente = {}
    local calificador = 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] -- devolve o cualificador (só devolverá o primeiro valor)
        else
        	return "" --Para que non lance excepción se non existe o cualificador
        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]  -- devolve a fonte (queda que se itinere a táboa)
    elseif (calificador == '' or not calificador) and (opciones.dato ~= 'fuente') then
        return declaracion.mainsnak -- devolve o valor principal
    else
    	return ''
    end
end

 --[[ =========================================================================
      Función para recopilar as declaracións
     ========================================================================= `-- ]]

function p.getDeclaraciones(entityId)


    -- == Comprobamos que existe un ítem ligando á páxina en Wikidata ==
    if not pcall (SelecionEntidadPorId, entityId ) then
    	return false
    end
    local entidad  = SelecionEntidadPorId(entityId)

    if not entidad then
        return  '' -- Se a páxina non está ligada a un ítem non devolve nada
    end

    -- == Comprobamos que o ítem ten declaracións (claims) ==

    if not entidad.claims then
        return '' -- Se o ítem non ten declaracións non devolve nada
    end
    -- == Declaración de formato e concatenado limpo ==

    return entidad.claims
end

 --[[ =========================================================================
      Función para  crear a cadea que devolverá a declaración
     ========================================================================= `-- ]]

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' -- Se damos o valor latitude, lonxitude ou precisión será equivalente a dar P625
    else
        propiedad = opciones.propiedad -- No resto de casos lese o dado
    end

    if not propiedad then -- Comprobamos se existe a propiedade dada e, en caso contrario, devólvese un erro
        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 dea erro cando se faga o find en opciones['formatoTexto'] se vale nil
    if not opciones['formatoTexto'] then
    	opciones['formatoTexto'] = ''
    end

    -- Deixar, no seu caso, os valores de maior rango
    if (opciones.rangoMayor == 'sí') then
        tablaOrdenada = filtrarDeclaracionPorRango(tablaOrdenada)
    end

    -- == Se só se desexa que devolva un valor ==
    if opciones.uno == 'sí' then -- Para que devolva o valor de índice 1
        tablaOrdenada = {tablaOrdenada[1]}
    end

-- == Creamos unha táboa cos valores que devolverá ==

    local formatoDeclaraciones = {}
    local hayDeclaraciones
    for indice, declaracion in pairs(tablaOrdenada) do
    	declaracionFormateada = 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 o formato á lista de valores segundo o tipo de lista das
    -- opcións
    if opciones['lista'] == 'no ordenada' then
        return '<ul><li>' .. mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ) .. '</li></ul>'
    elseif opciones['lista'] == 'ordenada' then
        return '<ol><li>' .. mw.text.listToText( formatoDeclaraciones, '</li><li>','</li><li>' ) .. '</li></ol>'
    else
     	-- valores separados por coma ou polo separador e a
      	-- conxunción das opcións
       	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

        return mw.text.listToText( formatoDeclaraciones, separador,conjuncion )
    end
end

function p.categorizar(opciones, declaracion)
	-- Evitar que dea erro cando se faga o find en opciones['formatoTexto'] se 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 unha táboa cos valores da propiedade.
	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' -- Se damos o valor latitude, lonxitude ou precisión será equivalente a dar p625
        else
            propiedad = opciones.propiedad -- No resto de casos lese o 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

    -- == Se só se desexa que devolva un valor ==
    --if opciones.uno == 'sí' then -- Para que devolva o valor de índice 1
    --    return formatoDeclaracion( valoresDeclaracion[1],opciones)
    --end
    --if (opciones.rangoMayor == 'sí') then -- Para que devolva os valores de maior rango
     --   valoresDeclaracion = filtrarDeclaracionPorRango(valoresDeclaracion)
    --end

--  Creamos unha táboa con cada categoría a partir de cada valor da declaración
    local categorias    = {}
    local hayCategorias

    if type(categoriaOpciones) == 'string' then
        local ModuloPaginas = require('Módulo:Páxinas')

        for indice, valor in pairs(valoresDeclaracion) do
            valorFormateado = 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[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 comproba se a páxina está ligada a  Wikidata
        en caso de estalo pasa o valor como argumento á función formatSnak()
     ========================================================================= `-- ]]

function formatoDeclaracion( declaracion, opciones)
    if not declaracion.type or declaracion.type ~= 'statement' then -- Compróbase que ten valor de tipo e que este sexa statement (declaración) o cal pasa sempre que existe a propiedade
        return formatoError( 'unknown-claim-type' ) -- Se non se cumpre devuelve erro
    end

    -- No caso de que haxa cualificador devólvese a dereita do valor da
    -- declaración entre parénteses.

    local calificativo = opciones.calificador

    if calificativo and declaracion.qualifiers then
    	-- De momento os cualificativos, normalmente anos, non se ligan
       local opcionesCalificativo = {['formatoTexto']='', enlace='no', ['formatoFecha']='año'} -- Pendente

       local wValorCalificativo
       local wValorCalificativoFormateado

       if type(calificativo) == 'function' then
       	  -- Utilizar a función recibida sobre todos os cualificativos
       	  wValorCalificativo           = declaracion.qualifiers
          wValorCalificativoFormateado = calificativo(wValorCalificativo, opcionesCalificativo)
       else
       	  -- Utilizar o primeiro valor do cualificativo da propiedade recibida
       	  wValorCalificativo = declaracion.qualifiers[mw.ustring.upper(calificativo)]

       	  if wValorCalificativo and wValorCalificativo[1] then
            wValorCalificativoFormateado = p.formatoDato(wValorCalificativo[1], opcionesCalificativo)
	      end
	    end

    	if wValorCalificativoFormateado then
    	   return p.formatoDato(declaracion.mainsnak, opciones) .. '&nbsp;<small>(' .. wValorCalificativoFormateado .. ')</small>'
    	end
    end

    -- Se non hai cualificativo.
    return p.formatoDato(seleccionDeclaracion(declaracion, opciones), opciones, declaracion.qualifiers)
end

 --[[ =========================================================================
        Función que comproba o tipo de dato (snaktype)
        se é value pasa o valor como argumento á función formatoValorDato()
     ========================================================================= `-- ]]

function p.formatoDato( dato, opciones, calificativos)
    if not dato or dato == '' then
        return ''
    end
    if dato.snaktype == 'somevalue' then
    	-- Data máis antiga
    	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/Data').FormateaFechaHora(calificativos['P1319'][1].datavalue.value, opcionesFecha)
            end
    	end

    	-- Se non ten un calificativo válido
        return avisos['somevalue'] -- Valor descoñecido
    elseif dato.snaktype == 'novalue' then
        return avisos['novalue'] -- Sen valor
    elseif dato.snaktype == 'value' then
        return formatoValorDato( dato.datavalue, opciones, calificativos) -- Se ten o tipo de dato pásase o valor á función formatDatavalue()
    else
        return formatoError( 'unknown-snak-type' ) -- Tipo de dato descoñecido
    end
end

 --[[ =========================================================================
       Función que establece o tipo de formato en función do tipo de valor
       (valorDato.type) e en caso de solicitarse un formato complementario asocia
       o módulo onde se establece o formato e a función deste que o establece
     ========================================================================= `-- ]]

function formatoValorDato( valorDato, opciones, calificativos)

	-- == Se se da o parámetro  valor-módulo e valor-función ==

	funcion = opciones['valor-función'] or opciones['value-function']
	if funcion and type(funcion) == 'function' then -- Uso desde LUA
	--  Ver un exemplo no módulo de Ficha de libro co ISBN.
	    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 funcion(valorDato.value, opcionesEntidad, marco, calificativos)
    elseif (opciones['valor-módulo'] and opciones['valor-módulo'] ~= "" ) or (opciones['value-function'] and opciones['valor-function'] ~= "" ) then
        if not opciones['valor-módulo'] or not opciones['valor-función'] then
            return formatoError( 'unknown-value-module' )
        end
        local formateado = require ('Módulo:' .. opciones['valor-módulo'])
        if not formateado then
            return formatoError( 'value-module-not-found' )
        end
        local fun = formateado[opciones['valor-función']]
        if not fun then
            return formatoError( 'value-function-not-found' )
        end
        return fun( valorDato.value, opciones, marco)
    end

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

--          * Para tipo coordenadas cando se da como valor de propiedade: latitude, lonxitude ou 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']

--           * Co resto de valores en propiedade

    elseif valorDato.type == 'wikibase-entityid' then    -- Tipo: Número de entidade que pode ser un ítem ou propiedade
	    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: Cadea 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: Data/hora
        local opcionesFecha={['formatoFecha']=opciones['formatoFecha'],enlace=opciones.enlace}

        if mw.ustring.find(opciones['formatoTexto'],'mayúscula', plain ) and primera then
	        opcionesFecha['mayúscula']='sí'
        end

        return require('Módulo:Wikidata/Data').FormateaFechaHora(valorDato.value, opcionesFecha, calificativos)
    elseif valorDato.type == 'monolingualtext' then       -- Tipo: monolingüe
    	if valorDato.value then
            return valorDato.value.text
        else
            return ''
        end
    elseif valorDato.type ==  'quantity' then            -- Tipo: Cantidade
    	cantidad = mw.ustring.gsub(valorDato.value['amount'], '+','')
    	unidad = mw.wikibase.label(mw.ustring.gsub(valorDato.value['unit'], '^.-/(Q%d+)$', '%1'))
    	if unidad and tonumber(cantidad) > 1 then
    		unidad = unidad..'s'
    	end

    	if not unidad or (opciones['formatoUnidad'] and opciones['formatoUnidad'] == 'número') then
    		return tonumber(cantidad)
    	else
    		return cantidad .. ' ' .. unidad
    	end
    elseif  valorDato.value['latitude']  and valorDato.value['longitude'] then -- Tipo: Coordenadas
    	local globo = require('Módulo:Wikidata/Globos')[valorDato.value.globe]

--Concatenamos os valores de latitude e lonxitude dentro do modelo 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' ) -- Se non é de ningún destos tipos devolverá erro de valor desconocido
    end
end

  --[[ =========================================================================
          Damos formato ás ligazons internas
       ========================================================================= `-- ]]

-- Opcións:
--     - ligazóns:		Valores posibles 'sí' ou 'non'
--     - maiúscula:		Valores posibles 'sí' ou 'non'
--     - cursivas:		Valores posibles 'sí' ou 'non'

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
    local valorWikidata = p.getPropiedad( frame.args , nil)
    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' and
            string.upper(args.propiedad) ~= 'P41' and string.upper(args.propiedad) ~= 'P94' and
            string.upper(args.propiedad) ~= 'P109' and string.upper(args.propiedad) ~= 'P94' and
            string.upper(args.propiedad) ~= 'P154') then
        if valorWikidata ~= '' and args.valor and args.valor ~= '' then
                categorias = '[[Categoría:Wikipedia:Artigos con datos locais]]'
        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:Artigos con datos por trasladar a Wikidata]]'
        end
    end

    if args.prioridad == 'sí' and valorWikidata  ~= '' then -- Se se da o valor si a prioridade, terá preferencia o 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 substitúe ó 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 -- Se o valor é nil salta unha excepcion ó concatenar
        return valorWikidata .. categorias
    else
    	return ''
  end
end

-- mw.wikibase.getLabelWithLang or getLabelByLang with a table of languages
local function getLabelByLangs(id, languages)
	local label
	local lang = languages[1]
	if lang == wiki.langcode then
		-- using getLabelWithLang when possible instead of getLabelByLang
		label, lang = mw.wikibase.getLabelWithLang(id)
	else
		for _, l in ipairs(languages) do
			label = mw.wikibase.getLabelByLang(id, l)
			lang = l
			if label then
				break
			end
		end
	end
	return label, lang
end

-- Is gender femenine? true or false
local function feminineGender(id)
	local entity = mw.wikibase.getEntityObject(id)
	local genderClaims = entity.claims["P21"] -- sex or gender
	if genderClaims then
		local genderId = getValueOfClaim(genderClaims[1], nil, {["formatting"]="raw"})
		if genderId == "Q6581072" or genderId == "Q1052281" or genderId == "Q43445" then -- female, transgender female, female organism
			return true
		end
	end
	return false
end

-- Fetch female form of label
local function feminineForm(id, lang)
	local feminine_claims = findClaims(mw.wikibase.getEntityObject(id), 'P2521') -- female form of label
	if feminine_claims then
		for _, feminine_claim in ipairs(feminine_claims) do
			local feminine_value = getValueOfClaim(feminine_claim, nil, {["formatting"]=lang, ["lang"]={lang}})
			if feminine_value then
				return feminine_value
			end
		end
	end
end

-- Gets a label in a given language (content language by default) or its fallbacks, optionnally linked.
function p.getLabel(frame)
	local args = frame.args
	local id = mw.text.trim(args[1] or "")
	if id == "" then return end
	local editicon = not (args.editicon == "false" or args.editicon == "no")
	local languages = findLang()
	-- temporary track
	if args.fixed then
		require('Módulo:utilidades').rastreig("Wikidata/fixed")
	end
	
	local pencil = ''
	local label, lang
	if languages[1] == wiki.langcode then
		label = require("Module:Wikidata/labels").infoboxLabelsFromId[id] -- exceptions or labels fixed
	end
	
	if label == nil then
		label, lang = getLabelByLangs(id, languages)
		if label then
			if args.itemgender and feminineGender(args.itemgender) then
				label = feminineForm(id, lang) or label
			end
			label = mw.language.new(lang):ucfirst(mw.text.nowiki(label)) -- sanitize
		end
		pencil = addEditIcon(id, lang, languages[1], editicon)
	end
	
	local linked = args.linked
	if linked and linked ~= "" and linked ~= "no" then
		local article = mw.wikibase.getSitelink(id) or ("d:" .. id)
		return "[[" .. article .. "|" .. (label or id) .. "]]" .. pencil
	else
		return (label or id) .. pencil
	end
end
return p