Aller au contenu

Module:Interface Wikidata2

Útá Wikipedia.

La documentation pour ce module peut être créée à Module:Interface Wikidata2/doc

-- Den ordning fallback language hämtas, om svensk label saknas. Engelska först, därefter bokmål, danska, etc...
local fallback = {'en', 'nb', 'da', 'nn', 'de', 'fr', 'es', 'it', 'pt'}
local fallbackprio = { ['sv'] = 20, ['en'] = 18, ['nb'] = 17, ['da'] = 16, ['nn'] = 15, ['de'] = 12, ['fr'] = 11, ['es'] = 10, ['it'] = 8, ['pt'] = 7}
local redundanta = {'viaf.org/viaf/', 'portal.dnb.de/', 'www.nndb.com/', 'catalogue.bnf.fr/ark'}
local formatera = require('Module:Math')
local i18n = {
	["errors"] = {
		["property-param-not-provided"] = "Property parameter not provided.",
		["entity-not-found"] = "Entity not found.",
		["unknown-claim-type"] = "Unknown claim type.",
		["unknown-snak-type"] = "Unknown snak type.",
		["unknown-datatype"] = "Unknown datatype.",
		["unknown-entity-type"] = "Unknown entity type.",
		["unknown-value-module"] = "You must set both value-module and value-function parameters.",
		["value-module-not-found"] = "The module pointed by value-module not found.",
		["value-function-not-found"] = "The function pointed by value-function not found.",
		["non-convertible unit"] = "Denna enhet går inte att konvertera till den önskade",
		["invalid-id"] = "Ogiltigt id",
		["no-label"] = "Etikett saknas"
	},
	["somevalue"] = "''unknown value''",
	["novalue"] = "''no value''"
}
local sortingproperties = {'P585','P571','P580','P569','P582','P570'}

function namefordate(options)
	local entity = options.entityId or mw.wikibase.getEntityIdForCurrentPage()
	if entity == nil then return nil end
	theobject = getEntityFromId(entity)
	if theobject == nil or theobject == '' or theobject.claims == nil then return nil end
	thetime = theobject.claims[options.labelfromnameproperty]
	if thetime == nil or thetime == '' then return nil end
	if thetime[1] == nil then return nil end
	if thetime[1].mainsnak.snaktype ~= 'value' then return nil end
    tiden = string.match(thetime[1].mainsnak.datavalue.value.time,'%d+%-%d+%-%d+')
	if theobject.claims[options.property] == nil then return nil end
	allnamesobject = nil
    for i,k in pairs(theobject["claims"][options.property]) do
		if theobject["claims"][options.property][i].rank~='deprecated' and theobject["claims"][options.property][i].mainsnak.snaktype == "value" then
			allnamesobject = getEntityFromId(theobject["claims"][options.property][i]["mainsnak"].datavalue.value.id)
		end
		if rank=='preferred' then
			break
		end
	end
    if allnamesobject == nil or allnamesobject == {} then return nil end
    if allnamesobject.claims == nil then return nil end
    allnames=allnamesobject.claims['P2561']
	if allnames == nil or allnames == '' then return nil end
	found = nil
	for i,k in pairs(allnames) do
		if k.qualifiers then
			fromdate = k.qualifiers['P580']
			if fromdate ~= nil then fromdate = string.match(fromdate[1].datavalue.value.time,'%d+%-%d+%-%d+') end
			todate = k.qualifiers['P582']
			if todate ~= nil then todate = string.match(todate[1].datavalue.value.time,'%d+%-%d+%-%d+') end
			if not ((fromdate and fromdate>tiden) or (todate and todate<tiden)) then found = k.mainsnak.datavalue.value.text end
	    end
	end
	return found
end 

function unithandle(unit, options)
	-- Kontrollerar om det finns någon förkortning för denna 'unit'
	local lab = options.label or formatStatements({property = 'P498', entityId = unit, enbarten = 'true', noref = 'true'})
	if not lab or lab == '' then
		lab = formatStatements({property = 'P558', entityId = unit, enbarten = 'true', langpref = options.langpref, noref = 'true'})
	end
	if lab and ( not options.nounitshort or options.nounitshort == '' ) then
		return formatEntityId( unit, {label = lab, nolink = (options.nounitlink or options.nolink) }).value
	else -- om det inte finns en förkortning
		return formatEntityId( unit, {nolink = options.nounitlink}).value
	end
end

function multiplikation(a, b, typ)
	local r = {}
	if typ == '*' then
		r.amount = tonumber(a.amount) * tonumber(b.amount)
		if tonumber(a.upperBound) and a.upperBound and b.upperBound then
			r.upperBound = tonumber(a.upperBound) * tonumber(b.upperBound)
		end
		if tonumber(a.lowerBound) and a.lowerBound and b.lowerBound then
			r.lowerBound = tonumber(a.lowerBound) * tonumber(b.lowerBound)
		end
	elseif typ == '/' then
		if tonumber(b.amount) and tonumber(b.amount) ~= 0 then
			r.amount = tonumber(a.amount) / tonumber(b.amount)
		end
		if tonumber(a.upperBound) and tonumber(b.lowerBound) and tonumber(b.lowerBound) ~= 0 then
			r.upperBound = tonumber(a.upperBound) / tonumber(b.lowerBound)
		end
		if tonumber(a.lowerBound) and tonumber(b.upperBound) and tonumber(b.upperBound) ~= 0 then
			r.lowerBound = tonumber(a.lowerBound) / tonumber(b.upperBound)
		end
	end
	if r.lowerBound and r.upperBound and r.lowerBound > r.upperBound then
		local slask = r.lowerBound
		r.lowerBound = r.upperBound
		r.upperBound = slask
	end
	return r
end	

function fallbackigen(options, alternativ)
	if alternativ and alternativ ~= '' then
		return alternativ
	end
	if options.entity and options.entity.labels then
		if options.entity.labels.sv then
			return options.entity.labels.sv.value
		else
			for k, v in pairs(fallback) do
				if options.entity.labels[v] then
					return options.entity.labels[v].value
				end
			end
		end
		for v, k in pairs(options.entity.labels) do
			return k.value
		end
	end
	return mw.title.getCurrentTitle().text
end	

function regionaux(entity)
	local w = formatStatements({property = 'P297', entity = entity, noref = 'true', raw = 'true', enbarten = 'true'})
	if w and #w > 0 then
		return w[1].value
	end
	w = formatStatements({property = 'P300', entity = entity, noref = 'true', raw = 'true', enbarten = 'true'})
	if w and #w > 0 then
		return w[1].value
	end
end

function regionaux2(entity)
	local w = formatStatements({property = 'P131', entity = entity, noref = 'true', raw = 'true', enbarten = 'true'})
	local w2 = formatStatements({property = 'P297', entity = entity, noref = 'true', raw = 'true', enbarten = 'true'})
	return w or w2
end

function regional(options, latitude)
	local i = 6
	local entity = options.entity
	local a = ''
	while i > 0 do
		local region = regionaux(entity)
		if region then
			return region
		end
		local v = regionaux2(entity)
		if v and #v > 0 then
			entity = mw.wikibase.getEntityObject( v[1].item )
		end
		i = i - 1
	end
	local w = formatStatements({property = 'P17', entity = options.entity, noref = 'true', raw = 'true', enbarten = true})
	if w and #w > 0 then
		w = formatStatements({property = 'P297', entityId = w[1].item, noref = 'true', raw = 'true', enbarten = true})
		if w and #w > 0 then
			return w[1].value
		end
	end
	if latitude and latitude < -65 then -- Antarktis
		return 'AQ'
	end
	return nil
end

function planeter(t)
	local px = {
		Q2 = 'earth',
		Q308 = 'mercury',
		Q313 = 'venus',
		Q405 = 'moon',
		Q111 = 'mars',
		Q7547 = 'phobos',
		Q7548 = 'deimos',
		Q596 = 'ceres',
		Q3030 = 'vesta',
		Q3169 = 'ganymede',
		Q3134 = 'callisto',
		Q3123 = 'io',
		Q3143 = 'europa',
		Q15034 = 'mimas',
		Q3303 = 'enceladus',
		Q15047 = 'tethys',
		Q15040 = 'dione',
		Q15050 = 'rhea',
		Q2565 = 'titan',
		Q15037 = 'hyperion',
		Q17958 = 'iapetus',
		Q17975 = 'phoebe',
		Q3352 = 'miranda',
		Q3343 = 'ariel',
		Q3338 = 'umbriel',
		Q3322 = 'titania',
		Q3332 = 'oberon',
		Q3359 = 'triton',
		Q339 = 'pluto',
	}
	return px[t] or 'earth'
end

function inlist(needle, haystack)
	-- Checks if an item is present amongst the values of a list
	for _, v in pairs(haystack) do
		if v == needle then
			return true
		end
  	return false
  	end
end

function koorder(data, options)
	if not data then
		return nil
	end
	local s = {}
	local planet = planeter(data.globe:match('Q%d+'))
	s.lat_dec = math.abs(data.latitude)
	s.long_dec = math.abs(data.longitude)
	if data.latitude > 0 then
		s.lat_NS = 'N'
	else
		s.lat_NS = 'S'
	end
	if data.longitude > 0 then
		s.long_EW = 'E'
	else
		s.long_EW = 'W'
	end
	local frac = 0
	if data.precision == nil then
		s.lat_g = math.abs(data.latitude)
		s.long_g = math.abs(data.longitude)
	elseif inlist(data.precision, {1, 0.1, 0.01, 0.001, 0.0001}) then
		s.lat_g, frac = math.modf(math.abs(data.latitude) / data.precision + 0.5) * data.precision
		s.long_g, frac = math.modf(math.abs(data.longitude) / data.precision + 0.5) * data.precision
	elseif data.precision > 0.0166 and data.precision < 0.0167 then
		s.lat_g, frac = math.modf(math.abs(data.latitude))
		s.lat_m, frac = math.modf(frac * 60 + 0.5)
		s.long_g, frac = math.modf(math.abs(data.longitude))
		s.long_m, frac = math.modf(frac * 60 + 0.5)
	elseif data.precision > 0.000277 and data.precision < 0.000278 then
		s.lat_g, frac = math.modf(math.abs(data.latitude))
		s.lat_m, frac = math.modf(frac * 60)
		s.lat_s, frac = math.modf(frac * 60 + 0.5)
		s.long_g, frac = math.modf(math.abs(data.longitude))
		s.long_m, frac = math.modf(frac * 60)
		s.long_s, frac = math.modf(frac * 60 + 0.5)
	elseif data.precision > 0.0000277 and data.precision < 0.0000278 then
		s.lat_g, frac = math.modf(math.abs(data.latitude))
		s.lat_m, frac = math.modf(frac * 60)
		s.lat_s, frac = math.modf(frac * 600 + 0.5)/10
		s.long_g, frac = math.modf(math.abs(data.longitude))
		s.long_m, frac = math.modf(frac * 60)
		s.long_s, frac = math.modf(frac * 600 + 0.5)/10
	elseif data.precision > 0.00000277 and data.precision < 0.00000278 then
		s.lat_g, frac = math.modf(math.abs(data.latitude))
		s.lat_m, frac = math.modf(frac * 60)
		s.lat_s, frac = math.modf(frac * 6000 + 0.5)/100
		s.long_g, frac = math.modf(math.abs(data.longitude))
		s.long_m, frac = math.modf(frac * 60)
		s.long_s, frac = math.modf(frac * 6000 + 0.5)/100
	else
		s.lat_g = math.abs(data.latitude)
		s.long_g = math.abs(data.longitude)
	end
	local params = s.lat_dec .. '_' .. s.lat_NS .. '_' .. s.long_dec .. '_' .. s.long_EW
	local typen = options.typen or 'landmark'
	local region = options.region
	local pagename = fallbackigen(options, options.pagename)

	if not region and planet == 'earth' then
		region = regional(options, data.latitude)
	end
	local magic = ''
	if not options.nogeodataparser or options.nogeodataparser == '' then
		local args = { data.latitude, data.longitude, globe = planet, type = typen, region = region, name = pagename }
		local primary = options.num == 1
		if options.primary and options.primary ~= '' then
			primary = options.primary == 'primary'
		end
		if primary then
			table.insert( args, 1, 'primary' )
		end
		magic = mw.getCurrentFrame():callParserFunction{
			name = '#coordinates',
			args = args
		}
	end
	if options.geodataparseronly and options.geodataparseronly ~= '' then
		return magic
	end
	pagename = string.gsub (pagename, "([^%w ])",
    	function (c) return string.format ("%%%02X", string.byte(c)) end) 
    pagename = string.gsub (pagename, " ", "+")
	local nn = '&title=' .. pagename
	if region then
		planet = planet .. '_region:' .. region
	end
	if not options.label then
		local a = s.lat_g .. '°'
		if s.lat_m then
			a = a .. s.lat_m .. '′'
		end
		if s.lat_s then
			a = a .. s.lat_s .. '″'
		end
		a = a .. s.lat_NS
		a = a .. ',' .. s.long_g .. '°'
		if s.long_m then
			a = a .. s.long_m .. '′'
		end
		if s.long_s then
			a = a .. s.long_s .. '″'
		end
		a = a .. s.long_EW
		return magic .. '[https://tools.wmflabs.org/geohack/geohack.php?language=sv' .. nn .. '&params=' .. params .. '_globe:' .. planet .. '_type:' .. typen .. ' ' .. a .. ']'
	end
	if options.label ~= '' then
		return magic .. '[https://tools.wmflabs.org/geohack/geohack.php?language=sv' .. nn .. '&params=' .. params .. '_globe:' .. planet .. '_type:' .. typen .. ' ' .. options.label .. ']'
	else
		return magic .. '[https://tools.wmflabs.org/geohack/geohack.php?language=sv' .. nn .. '&params=' .. params .. '_globe:' .. planet .. '_type:' .. typen .. ']'
	end
end

function getonly(claims, options)
	local claims2 = {}
	for i, j in pairs(claims) do

		if j.mainsnak and j.mainsnak.snaktype == 'value' and j.mainsnak.datavalue and j.mainsnak.datavalue.value and j.mainsnak.datavalue.value.id then
			local t = j.mainsnak.datavalue.value.id
			local traff = false
			local t2 = formatStatements( {property = (options.getonlyproperty or "P31"), entityId = t, noref = 'true', raw = 'true' })
			if t2 and #t2 > 0 then
				for k, state in pairs( t2 ) do
					for j2, only in pairs(mw.text.split(options.getonly,',')) do
						if state.item == only then
							traff = true
						end
					end
				end
			end
			if traff then
				table.insert(claims2, j)
			end
		end
	end
	return claims2
end

function claimindex(claims, options)
	local claims2 = {}
	for j, index in pairs(mw.text.split(options.claimindex,',')) do
		if tonumber(index) and #claims >= tonumber(index) then
			table.insert(claims2, claims[tonumber(index)])
		end
	end
	return claims2
end

function preferqualifier(claims, options)
	local claims2 = {}
	for i, statement in pairs( claims ) do
		if statement.qualifiers and statement.qualifiers[options.preferqualifier:upper()] then
			if options.preferqualifiervalue and options.preferqualifiervalue ~= '' then
				local active = false
				for k, t in pairs(mw.text.split(options.preferqualifiervalue,',')) do
					for j, value in pairs(formatStatements({property=options.preferqualifier:upper(), raw = 'true'}, statement.qualifiers)) do
						if value.item == t and not active then
							table.insert( claims2, statement)
							active = true
						end
					end
				end
			else
				table.insert( claims2, statement)
			end
		end
	end
	return claims2
end

function versalisering(label, options)
	local versalisering = options.versalisering
	if options.firstversalisering and options.num == 1 then
		versalisering = options.firstversalisering
	end
	if not versalisering or versalisering == '' then
		return label
	end
	if versalisering == 'lcfirst' then
		return mw.getCurrentFrame():preprocess("{{lcfirst: " .. label .. " }}")
	elseif versalisering == 'ucfirst' then
		return mw.language.getContentLanguage():ucfirst( label )
	elseif versalisering == 'lc' then
		return mw.getCurrentFrame():preprocess("{{lc: " .. label .. " }}")
	elseif versalisering == 'uc' then
		return mw.getCurrentFrame():preprocess("{{uc: " .. label .. " }}")
	end
	return label
end
function getqualifierbysortingproperty(claim, sortingproperty)
	for k, v in pairs(sortingproperty) do
		if claim.qualifiers and claim.qualifiers[v] and claim.qualifiers[v][1].snaktype == 'value' then
			if claim.qualifiers[v][1].datavalue.value.time then
				return claim.qualifiers[v][1].datavalue.value.time
			else
				return claim.qualifiers[v][1].datavalue.value
			end
		end
	end
	return nil
end

function getDate(claim, options)
	local sortingproperty = sortingproperties
	if type(options.sortingproperty) == 'table' then
		sortingproperty = options.sortingproperty
	elseif type(options.sortingproperty) == 'string' then
		sortingproperty = {options.sortingproperty}
	end
	return getqualifierbysortingproperty(claim, sortingproperty)
end

function getDateArb(claim, options)
	local sortingproperty = options.sortingproperty or 'P569'
	if claim.mainsnak.snaktype == 'value' then
		local item = getEntityIdFromValue( claim.mainsnak.datavalue.value )
		return formatStatements({property = sortingproperty, entityId = item, enbarten = 'ja', sortbytime = 'chronological', noref = 'ja'})
	end
end

function comparedates(a, b, options)
	if a==nil and (options.sortnotimeas == 'maxtime') then a = '+9999-12-31T23:59:59Z' end
	if b==nil and (options.sortnotimeas == 'maxtime') then b = '+9999-12-31T23:59:59Z' end
	if a and b then
		return a > b
	elseif a then
		return true
	end
end

function getValue(claim, options)
	local sortingproperty = sortingproperties
	if type(options.sortingproperty) == 'table' then
		sortingproperty = options.sortingproperty
	elseif type(options.sortingproperty) == 'string' then
		sortingproperty = {options.sortingproperty}
	end
	return getqualifierbysortingproperty(claim, sortingproperty)
end

function comparevalues(a,b)
	if a and b then
		return a > b
	elseif a then
		return true
	end
end

function sortbyqualifier(claims, options)
	if options.sortbytime then
	table.sort(claims, function(a, b)
		local timeA = getDate(a, options)
		local timeB = getDate(b, options)
		if options.sortbytime == 'inverted' then
			return comparedates(timeB, timeA, options)
		else
			return comparedates(timeA, timeB, options)
		end
	end)
	elseif options.sortbyvalue then
	table.sort(claims, function(a, b)
		local valueA = tonumber(getValue(a, options))
		local valueB = tonumber(getValue(b, options))
		if options.sortbyvalue == 'ascending' then
			return comparevalues(valueB, valueA)
		else
			return comparevalues(valueA, valueB)
		end
	end)
	end
	return claims
end

function getPrio(claim, options)
	local a = fallbackprio[claim.mainsnak.datavalue.value.language]
	if not a then
		return 0
	end
	return a
end

function sortbylanguage(claims, options)
	if claims[1].mainsnak.datatype ~= 'monolingualtext' then
		return claims
	end
	table.sort(claims, function(a, b)
		local prioA = getPrio(a, options)
		local prioB = getPrio(b, options)
		if options.sortbytime == 'inverted' then
			return comparedates(prioB, prioB, options)
		else
			return comparedates(prioA, prioB, options)
		end
	end)
	return claims
end

function sortbyarb(claims, options)
	table.sort(claims, function(a,b)
		local timeA = getDateArb(a, options)
		local timeB = getDateArb(b, options)
		if options.sortbyarbitrary == 'inverted' then
			return comparedates(timeB, timeA, options)
		else
			return comparedates(timeA, timeB, options)
		end
	end)
	return claims
end

function getLabelFromFallBack( id )
	local entity = {}
	if type(id) == 'table' then
		entity = id
		id = entity.id
	else
		entity = getEntityFromId( id )
	end
	if not entity.labels then
		return {value = '[[d:' .. id .. '|' .. id .. ']][[Kategori:Wikidatabaserade länkar som leder till sidor utan label]]', language = ''}
	end
	for k, v in pairs(fallback) do
		if entity.labels[v] then
			return {value = entity.labels[v].value, language = entity.labels[v].language}
		end
	end
	-- Om inget fallback-språk finns av de i variabeln ovan, så används det först definierade i objektet
	if entity.labels then
		for v, k in pairs(entity.labels) do
			return {value = k.value, language = k.language}
		end
	end
	return {value = '-', language = ''}
end

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

function getEntityIdFromValue( value )
	if value['entity-type'] == 'item' then
		return 'Q' .. value['numeric-id']
	elseif value['entity-type'] == 'property' then
		return 'P' .. value['numeric-id']
	else
		return formatError( 'unknown-entity-type' )
	end
end

function formatError( key )
	return '<span class="error">' .. i18n.errors[key] .. '</span>'
end

function formatStatements( options, ref )
	local formattedStatements = {}
	local claims = {}
	if not options.property then
		return formatError( 'property-param-not-provided' )
	end

	if type(ref) == 'table' then -- för de fall där funktionen anropas och alla claims redan finns i en tabell
		claims = ref[options.property] or {}
	else
		--Get entity
		local entity = nil
		
		if options.entity and type( options.entity ) == "table" then
			entity = options.entity
		else
			entity = getEntityFromId( options.entityId )
			options.entity = entity
		end

		if not entity then
			return '' --TODO error?
		end

	--	if property is given as Pxxx/Pyyy/..../Pzzz then 
	--  climb the property path and change entity successively for all P... except the last one.
	--  only the first claim for each P... is considered
		local props = mw.text.split(options.property:upper(),'/')
		for i,prop in ipairs(props) do
			if i<#props then
				if entity.claims[prop] == nil then
					return ''
				end
				options.entityId=entity.claims[prop][1]['mainsnak'].datavalue.value.id
				if options.entityId == nil then
					return ''
				end
				entity = getEntityFromId( options.entityId )
			else
				options.property=prop:upper()
	    	end
		end

		if not entity.claims or not entity.claims[options.property:upper()] then
			return '' --TODO error?
		end

		--Format statement and concat them cleanly
		if options.rank == 'best' or not options.rank then
			claims = entity:getBestStatements( options.property:upper() )
		elseif options.rank == 'valid' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				if statement.rank == 'preferred' then
					table.insert( claims, statement )
				end
			end
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				if statement.rank == 'normal' then
					table.insert( claims, statement )
				end
			end
		elseif options.rank == 'all' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				table.insert( claims, statement )
			end
		else
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				if statement.rank == options.rank then
					table.insert( claims, statement )
				end
			end
		end
		if options.avoidqualifier then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if not statement.qualifiers or not statement.qualifiers[options.avoidqualifier:upper()] then
					table.insert( claims2, statement)
				end
			end
			claims = claims2
		end
		if options.preferqualifier and options.preferqualifier ~= '' then
			claims = preferqualifier(claims, options)
		end
		
		if options.avoidstringpattern and options.avoidstringpattern ~= '' then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if statement.mainsnak.datavalue and statement.mainsnak.datavalue.type == 'string' then
					if not (string.find(statement.mainsnak.datavalue.value,options.avoidstringpattern)) then
						table.insert(claims2, statement)
					end
				else
					table.insert(claims2, statement)
				end
			end
			claims = claims2
		end

		--om det finns vissa statements som har en qualifier som säger "språk = svenska", ta bara med dessa
		--alternativt om det finns statements som har en qualifier som säger "skriptsystem == latinska alfabetet"
		if not options.langpref or options.langpref == '' then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if statement.qualifiers and statement.qualifiers.P407 then
					for k, v in pairs( statement.qualifiers.P407 ) do
						if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 9027 then -- Q9027 = 'svenska'
							table.insert( claims2, statement )
						end
					end
				elseif statement.qualifiers and statement.qualifiers.P282 then
					for k, v in pairs( statement.qualifiers.P282 ) do
						if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 8229 then -- Q8229 = 'latinska alfabetet'
							table.insert( claims2, statement )
						end
					end
				end
			end
			if #claims2 > 0 then
				claims = claims2
			end
		end
		if #claims > 1 then 
			claims = sortbylanguage(claims, options)
		end
		if options.sortbytime == 'chronological' or options.sortbytime == 'inverted' or options.sortbyvalue == 'ascending' or options.sortbyvalue == 'descending' then
			claims = sortbyqualifier(claims, options)
		elseif options.sortbyarbitrary == 'chronological' or options.sortbyarbitrary == 'inverted' then
			claims = sortbyarb(claims, options)
		end
		if options.getonly and options.getonly ~= '' then
			claims = getonly(claims, options)
		end
	end

	if options.claimindex and #claims > 0 then
		claims = claimindex(claims, options)
	end
	if options.enbarten and options.enbarten ~= '' and #claims > 1 then
		claims = {claims[1]}
	end
	local statementsraw = {}
	if claims then
		for i, statement in pairs( claims ) do
			options.num = i
			local stat = formatStatement( statement, options )
			if stat then
				local s = stat.value
				local spostref = ''
				local d = stat.datum
				local tf = stat.tifr
				local pr = stat.pr
				local utgivort = stat.utgivort
				local m = stat.mandatperiod
				if s == '' then s = nil end
				if s then
					if m and options.withmandatperiod and options.withmandatperiod ~= '' then
						s = s .. mw.text.tag('br') .. mw.text.tag('small', {}, m)
					end 
					if d and options.withdate and options.withdate ~= '' then
						s = s .. mw.text.tag('small', {}, ' (' .. d .. ')')
					end
					if d and options.dateonly and options.dateonly ~= '' then
						s = d
					end
					if d == nil and options.dateonly and options.dateonly ~= '' then
						s = '-'	
					end
					if tf and options.withintervall and options.withintervall ~= '' then
						if options.withintervallformat == 'Y' then	
							for i in mw.ustring.gmatch(tf,'">([^<]*)<',false) do
								j = mw.ustring.gsub(mw.ustring.gsub(i,'"',''),'%-','%%-')
								tf = mw.ustring.gsub(tf,j,mw.ustring.sub(j,1,4))
							end
						end
						if options.withintervall == 'gift' then
							s = s .. mw.text.tag('br') .. mw.text.tag('small', {}, '(g. ' .. tf .. ')')
						else
							s = s .. mw.text.tag('small', {}, ' (' .. tf .. ')')
						end
					end
					if utgivort and options.withutgivort and options.withutgivort ~= '' then
						if options.withutgivort == 'parantes och small' then
							s = s .. ' ' .. mw.text.tag('small', {}, ' (' .. utgivort .. ')')
						else
							s = s .. ' ' .. utgivort
						end
					end
					if options.getsimpleproperty == 'född' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('small', {}, '(f. ' .. pr .. ')')
					end
					if options.getsimpleproperty == 'parentes' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('span', {}, '(' .. pr .. ')')
					end
					if options.getsimpleproperty == 'avnågon' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('span', {}, ' av ' .. pr .. '')
					end
					if options.getsimpleproperty == '15px' and pr and pr ~= '' then
						s = '[[File:' .. pr .. '|15px]]&nbsp;' .. s
					end
					if options.grav and options.grav ~= '' then
						if options.grav == 'coordonly' then
							if stat.koord then
								spostref = '<br/>' .. stat.koord
							end
						else
							if stat.gravid then
								spostref = '<br/>' .. stat.gravid
							end
							if stat.koord then
								spostref = spostref .. '<br/>' .. stat.koord
							end
						end
					end
					if options.som and options.som ~= '' then
						if stat.som then
							if options.som == 'smallparentes' then
								s = s .. ' ' ..  mw.text.tag('small', {}, '(som ' .. stat.som .. ')')
							elseif options.som == 'parentes' then
								s = s .. ' (som ' .. stat.som .. ')'
							else
								s = s .. ' som ' .. stat.som
							end
						end
					end
					if type(ref) == 'table' then --Inte leta efter referenser om själva anropet görs från en referens
						table.insert( formattedStatements, s .. spostref )
					else
						local t = formatReferencesNew( statement, options)
						if t.flag then
							table.insert( formattedStatements, s .. t.value .. spostref)
							stat.ref = t.value
							stat.refraw = t.refraw
							stat.refquality = t.refquality
						else
							stat = nil
						end
					end
				end
				if stat then
					table.insert(statementsraw, stat)
				end
			end
		end
	end
	
		
	local tot = mw.text.listToText( formattedStatements, options.separator, options.conjunction )
	if tot == '' then tot = nil end
	if options.wdlink and options.wdlink ~= '' then
		local dlink = ''
		local wdlabel = 'WD'
		if options.wdlinklabel and options.wdlinklabel ~= '' then
			wdlabel = options.wdlinklabel
		end
		if options.entityId then
			dlink = options.entityId .. '#' .. options.property
		else
			dlink = 'Special:ItemByTitle/svwiki/' .. mw.getCurrentFrame():getParent():getTitle() .. '#' .. options.property
		end
		if options.wdlink == 'sub' then
			tot = tot .. ' ' .. mw.text.tag('sub', {}, '[[d:' .. dlink .. '|' .. wdlabel .. ']]')
		elseif options.wdlink == 'sup' then
			tot = tot .. ' ' .. mw.text.tag('sup', {}, '[[d:' .. dlink .. '|' .. wdlabel .. ']]')
		elseif options.wdlink == 'small' then
			tot = tot .. ' ' .. mw.text.tag('small', {}, '[[d:' .. dlink .. '|' .. wdlabel .. ']]')
		else
			tot = tot .. ' [[d:' .. dlink .. '|'.. wdlabel ..']][[Kategori:Wikidatatest4]]'
		end
	end
	if options.raw and options.raw ~= '' then
		return statementsraw
	end
	if options.numberofclaims and options.numberofclaims ~= '' then
		return #formattedStatements
	end
	return tot
end

function formatReferencesNew( statement, options)
	local limit = tonumber(options.sourcelimit) or 3
	local reference = {}
	local references = {}
	local quality = 0 -- ingen källa alls
	local flagga = false
	local limitcounter = 0
	local qualmax = 0
	local qual2 = 0
	if statement.references then
		local cite = require('Modul:Cite')
		for i, ref in pairs(statement.references) do
			local items, s = {}, nil
			qual2 = 100
			if ref.snaks then
				if ref.snaks.P248 then
					for j, prop in pairs(ref.snaks.P248) do
						if prop.snaktype=='value' then
							table.insert(items, getEntityIdFromValue( prop.datavalue.value ))
						end
					end
				end
				if quality < 10 and (ref.snaks.P143 or ref.snaks.P4656) then
					quality = 10 -- kvalite (importerad från)
				end
				if quality < 100 and not (ref.snaks.P143 or ref.snaks.P4656) then
					quality = 100 -- källa finns och den är (förhoppningsvis) bättre än "importerad från".
				end
				if (options.noref and options.noref ~= '' and options.noref ~= 'noimport') or (options.noref == 'noimport' and (ref.snaks.P143 or ref.snaks.P4656)) then
					--
				else
					s = cite.citeitem( items, ref.snaks, options )
					if s == '' or not s then
						s = 'Källangivelsen på Wikidata använder egenskaper (properties) som inte känns igen av Modul:Cite'
						qual2 = 10
					end
					if (ref.snaks.P143 or ref.snaks.P4656) then
						qual2 = 25 -- importerad från
					end
					if s then
						for j, rr in pairs(redundanta) do
							if s:match(rr) then
								qual2 = 50
							end
						end
					end
				end
			end
			if s and s ~= '' then
-- ta bort unika koder med oklart syfte, 
-- de gjorde att det blev Referensfel: Taggen <ref> är ogiltig; namnet "..." definieras flera gånger med olika innehåll				
				s=s:gsub('\"\`UNIQ.-QINU`\"','')
				table.insert(reference, {value = s, name = ref.hash, qq = qual2})
			end
			if qual2 > qualmax then
				qualmax = qual2
			end
		end
		if (options.sources == 'required' and quality > 99) or  (options.sources == 'basic' and quality > 9) or (not options.sources or options.sources == '') then
			for i, ref in pairs(reference) do
				if limitcounter < limit then
					if options.norefrank and options.norefrank ~= '' then
						table.insert(references, mw.getCurrentFrame():extensionTag( 'ref', ref.value, {name = ref.name}))
						limitcounter = limitcounter + 1
					else
						if ref.qq >= qualmax then
							table.insert(references, mw.getCurrentFrame():extensionTag( 'ref', ref.value, {name = ref.name}))
							limitcounter = limitcounter + 1
						end
					end
				end
			end
			flagga = true
		else
			flagga = false
		end
	else
		if not options.sources or options.sources == '' then
			flagga = true
		end
	end
	return {value = table.concat(references), refquality = quality, refraw = reference, flag = flagga}
end

function formatStatement( statement, options )
	if statement.type == 'statement' then
		local s = formatSnak( statement.mainsnak, options )
		if s and statement.qualifiers then
			if statement.qualifiers.P574 then
				s.dateoftaxpub = formatStatements({property = "P574", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers)
			end
			if statement.qualifiers.P585 then
				s.datum = formatStatements({property = "P585", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers)
			end
			if statement.qualifiers.P625 then
				if s.item then
					local opt = options
					opt.entity = mw.wikibase.getEntityObject( s.item )
					local region = regional(opt)
					s.koord = formatStatements({property = "P625", enbarten = 'true', noref = 'true', label = options.koordlabel, typen = options.koordtypen, primary = options.koordprimary, pagename=options.koordpagename, geodataparseronly = options.geodataparseronly, region = region}, statement.qualifiers)
				else
					s.koord = formatStatements({property = "P625", enbarten = 'true', noref = 'true', label = options.koordlabel, typen = options.koordtypen, primary = options.koordprimary, pagename=options.koordpagename, geodataparseronly = options.geodataparseronly}, statement.qualifiers)
				end
			end
			if statement.qualifiers.P794 then
				s.som = formatStatements({property = "P794", enbarten = 'true', noref = 'true'}, statement.qualifiers)
			end
			if statement.qualifiers.P965 then
				s.gravid = formatStatements({property = "P965", noref = 'true'}, statement.qualifiers)
			end
			if statement.qualifiers.P405 then
				local auktorer = {}
				for i, j in pairs(statement.qualifiers.P405) do
					if j.snaktype == 'value' then
						local item = getEntityIdFromValue( j.datavalue.value )
						local auktorsnamn = formatStatements({property = "P428", entityId = item, noref = 'ja', enbarten = 'ja'})
						if auktorsnamn and auktorsnamn ~= '' then
							table.insert(auktorer, formatEntityId(item, {label = auktorsnamn}).value)
						else
							table.insert(auktorer, formatEntityId(item, {}).value)
						end
					end
				end
				s.auktor = mw.text.listToText(auktorer, ', ', ' & ')
			end
			if s and (statement.qualifiers.P580 or statement.qualifiers.P582) then
				local f = formatStatements({property = "P580", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers) or ''
				local t = formatStatements({property = "P582", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers) or ''
				s.tifr = f .. '–' .. t
			end
			if statement.qualifiers.P291 then
				s.utgivort = formatStatements({property = "P291", noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
			end
			if statement.qualifiers.P2096 then
				s.bildtext = formatStatements({property = "P2096", noref = 'true', langpref = (options.langpref or 'sv')}, statement.qualifiers)
			end
			if statement.qualifiers.P180 then
				s.motiv = formatStatements({property = "P180", noref = 'true'}, statement.qualifiers)
			end
			if statement.qualifiers.P2937 then
				s.mandatperiod = formatStatements({property = "P2937", noref = 'true'}, statement.qualifiers)
			end
			if s then
				if options.qual1 and options.qual1 ~= '' and statement.qualifiers[options.qual1] then
					s.qp1 = formatStatements({property = options.qual1, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual2 and options.qual2 ~= '' and statement.qualifiers[options.qual2] then
					s.qp2 = formatStatements({property = options.qual2, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual3 and options.qual3 ~= '' and statement.qualifiers[options.qual3] then
					s.qp3 = formatStatements({property = options.qual3, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual4 and options.qual4 ~= '' and statement.qualifiers[options.qual4] then
					s.qp4 = formatStatements({property = options.qual4, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual5 and options.qual5 ~= '' and statement.qualifiers[options.qual5] then
					s.qp5 = formatStatements({property = options.qual5, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
			end
		end
		return s
	elseif not statement.type then
		return formatSnak( statement, options )
	end
	return {value = formatError( 'unknown-claim-type' )}
end

function formatSnak( snak, options )
	if snak.snaktype == 'somevalue' then
		if options.somevalue then
			if options.somevalue == '' then
				return nil
			else
				return {value = options.somevalue}
			end
		end
		return {value = i18n['somevalue']}
	elseif snak.snaktype == 'novalue' then
		if options.novalue then
			if options.novalue == '' then
				return nil
			else
				return {value = options.novalue}
			end
		end
		return {value = i18n['novalue']}
	elseif snak.snaktype == 'value' then
		local s = formatDatavalue( snak.datavalue, options, snak.datatype )
		if s and options.prefix and options.prefix ~= '' then
			s.value = options.prefix .. s.value
		end
		if s and options.suffix and options.suffix ~= '' then
			s.value = s.value .. options.suffix
		end
		if s and s.item and options.getsimpleproperty and options.getsimpleproperty ~= '' and options.getproperty and options.getproperty ~= '' then
			local pr = formatStatements({property = options.getproperty, entityId = s.item, enbarten = options.getenbarten, noref = 'ja', modifytime = options.getmodifytime, raw = options.getraw})
			if pr then s.pr = pr end
		end
		return s
	else
		return {value = formatError( 'unknown-snak-type' )}
	end
end

function formatDatavalue( datavalue, options, datatype )
	--Use the customize handler if provided
	if options['value-module'] or options['value-function'] then
		if not options['value-module'] or not options['value-function'] then
			return {value = formatError( 'unknown-value-module' )}
		end
		local formatter = require ('Module:' .. options['value-module'])
		if not formatter then
			return {value = formatError( 'value-module-not-found' )}
		end
		local fun = formatter[options['value-function']]
		if not fun then
			return {value = formatError( 'value-function-not-found' )}
		end
		return {value = fun( datavalue.value, options )}
	end

	--Default formatters
	if datatype == 'wikibase-item' then
		local s = formatEntityId( getEntityIdFromValue( datavalue.value ), options )
		s.item = getEntityIdFromValue( datavalue.value )
		if options.relevans and options.relevans ~= '' then
			if not mw.wikibase.sitelink( s.item ) then
				return nil
			end
		end
		return s

	elseif datatype == 'string' or datatype == 'commonsMedia' or datatype == 'external-id' then
		if options.pattern and options.pattern ~= '' then
			local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
			if options.pattern == "auktoritetsdata" and patter and patter ~= '' then
				return {value = formatFromPattern( datavalue.value, {pattern = patter} )}
			elseif options.pattern == "auktoritetsdata2" and patter and patter ~= '' then
				return {value = '[' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ' ' .. datavalue.value .. ']' }
			else
				if (options.pattern == "auktoritetsdata2") then  
	-- options.pattern blir sönderskriven(?) av funktionen getMost() i Modul:Cite
	-- återställer till ett defaultvärde i detta fall när P1630 saknas för property och formatFromPattern annars kör i diket
					options.pattern = '$1'
				end
				return {value = formatFromPattern( versalisering(datavalue.value, options), options )}
			end
		else
			return {value = versalisering(datavalue.value, options), label = datavalue.value}
		end

	elseif datatype == 'time' then
		local Time = require 'Module:Time'
		local tid = Time.newFromWikidataValue( datavalue.value ):toHtml()
		if options.modifytime == 'longdate' then
			local mall = ''
			if datavalue.value.precision >= 11 then
				mall = '{{#time:j F Y|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			elseif datavalue.value.precision == 10 then
				mall = '{{#time:F Y|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			elseif datavalue.value.precision == 9 then
				mall = '{{#time:Y|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			end
		elseif options.modifytime == 'longdatelink' then
			local mall = ''
			if datavalue.value.precision >= 11 then
				mall = '{{#time:[[j F]] [[Y]]|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			elseif datavalue.value.precision == 10 then
				mall = '{{#time:[[F]] [[Y]]|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = string.gsub(mw.getCurrentFrame():preprocess(mall),'mars','mars (månad)|mars')
			elseif datavalue.value.precision == 9 then
				mall = '{{#time:[[Y]]|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			end
		elseif options.modifytime == 'Y' then
			local mall = ''
			local thetime = datavalue.value.time 
			if string.sub(datavalue.value.time,1,1) == '-' then
				thetime = string.sub(thetime,2) 
	   			mall = '{{#time:Y|' .. string.gsub(thetime,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)..' f.Kr.'
			else
				mall = '{{#time:Y|' .. string.gsub(thetime,'-00','-01') .. '}}'
				tid = mw.getCurrentFrame():preprocess(mall)
			end
		elseif options.modifytime == 'Ylink' then
			local mall = '{{#time:[[Y]]|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
			tid = mw.getCurrentFrame():preprocess(mall)
		end
-- do not display time value if the precision is lower than lowesttimeprecision
		if options.lowesttimeprecision and options.lowesttimeprecision ~= '' and datavalue.value.precision<tonumber(options.lowesttimeprecision) then
			tid = '' 
	   	end
		return {value = tid}

	elseif datatype == 'globe-coordinate' then
		return {value = koorder(datavalue.value, options), latitude = datavalue.value.latitude, longitude = datavalue.value.longitude, precision = datavalue.value.precision, globe = datavalue.value.globe:match('Q%d+')}

	elseif datatype == 'quantity' then
		local amount, unit = datavalue.value.amount, datavalue.value.unit
		local amountR = formatera.newFromWikidataValueR(datavalue.value)
		local orginal = datavalue.value

		local amountsi, unitsi, unitrawsi, numbersi, valuesi= nil, nil, nil, nil, nil
		local amountsiupperBound, amountsilowerBound = nil, nil
		local amountconv, numberconv, unitconv, unitrawconv, valueconv = nil, nil, nil, nil, nil
		
		if unit then
			unit = unit:match('Q%d+')
		end
		local number = nil
		datavalue.value.norounding = options.norounding
		if options.noformatera and options.noformatera ~= '' then
			number = formatera.newFromWikidataValueR(datavalue.value)
		else
			number = formatera.newFromWikidataValue(datavalue.value)
		end

		local unitraw = unit -- enheten som Qid
		if unit then
			unit = unithandle(unit, options)	-- skickar tillbaka enheten i hanterbart format		
			if not options.antiloop and options.convertunit and options.convertunit ~= '' and options.convertunit ~= unitraw then 
				-- Av eknomiska skäl görs detta bara om konvertering efterfrågas och om den efterfrågade enheten inte är den som redan existerar
				local a = formatStatements({property = 'P2370', entityId = unitraw, enbarten = 'true', noref = 'true', raw = 'true', antiloop = 'true'})
				local b = formatStatements({property = 'P2370', entityId = options.convertunit, enbarten = 'true', noref = 'true', raw = 'true', antiloop = 'true'})
				if a and b and #a > 0 and b and #b > 0 then 
					local orginalsi = multiplikation(datavalue.value, a[1], '*') -- multiplicera orginalet för att få fram SI-enheten
					local orginalcv = multiplikation(orginalsi, b[1], '/') -- Dividera för att få fram den efterfrågade enheten
					amountsi = orginalsi.amount
					amountsiR = formatera.newFromWikidataValueR(orginalsi)
					if options.noformatera and options.noformatera ~= '' then
						numbersi = amountsi
					else
						local lang = mw.language.new( 'sv' )
						numbersi = lang:formatNum(tonumber(amountsi))
					end
					unitsi = a[1].unit
					unitrawsi = a[1].unitraw
					valuesi = numbersi .. ' ' .. (unitsi or '')
					amountconv = orginalcv.amount
					amountconvR = formatera.newFromWikidataValueR(orginalcv)
					if options.noformatera and options.noformatera ~= '' then
						numberconv = formatera.newFromWikidataValueR(orginalcv)
					else
						numberconv = formatera.newFromWikidataValue(orginalcv)
					end
					unitrawconv = options.convertunit
					unitconv = unithandle(options.convertunit, options)
					upperBoundconv, lowerBoundconv = orginalcv.upperBound, orginalcv.lowerBound
					if options.withoutunit and options.withoutunit ~= '' then
						valueconv = numberconv
					else
						valueconv = numberconv .. ' ' .. (unitconv or '')
					end
					return {value = valueconv, amount = amountconv, amountR = amountconvR, upperBound = upperBoundconv, lowerBound = lowerBoundconv, unit = unitconv, unitraw = unitrawconv, valuesi = valuesi, amountsi = amountsi, amountsiR = amountsiR, unitrawsi = unitrawsi, unitsi = unitsi}
				else
					return {value = number .. ' ' .. (unit or '') .. ' ' .. formatError( 'non-convertible unit') .. '[[Kategori:Wikidata:Påståenden som inte går att konvertera]]', amount = amount, amountR = amountR, upperBound = datavalue.value.upperBound, lowerBound = datavalue.value.lowerBound, unit = unit, unitraw = unitraw, cat = cat, valuesi = valuesi, amountsi = amountsi, amountsiR = amountsiR, unitrawsi = unitrawsi, unitsi = unitsi}	
				end
			end
		end
		if options.withoutunit and options.withoutunit ~= '' then
			return {value = number, amount = amount, amountR = amountR, upperBound = datavalue.value.upperBound, lowerBound = datavalue.value.lowerBound, unit = unit, unitraw = unitraw, valuesi = valuesi, amountsi = amountsi, unitrawsi = unitrawsi, unitsi = unitsi}
		else
			return {value = number .. ' ' .. (unit or ''), amount = amount, amountR = amountR, upperBound = datavalue.value.upperBound, lowerBound = datavalue.value.lowerBound, unit = unit, unitraw = unitraw, valuesi = valuesi, amountsi = amountsi, unitrawsi = unitrawsi, unitsi = unitsi}
		end

	elseif datatype == 'url' then
		if options.label and options.label ~= '' then
			return {value = '[' .. datavalue.value .. ' ' .. options.label .. ']'}
		else
			return {value = datavalue.value}
		end

	elseif datatype == 'monolingualtext' then
		local texten = versalisering(datavalue.value.text, options)
		if not options.langpref or options.langpref == '' then
			return {value = mw.text.tag('span', {title = mw.language.fetchLanguageName(datavalue.value.language, 'sv')}, texten), text = texten}
		else
			if options.langpref == datavalue.value.language then
				return {value = texten, text = texten}
			end
		end
	elseif datatype == 'geo-shape' and datavalue and datavalue.type and datavalue.type == "string" then
		return { value = datavalue.value }
	else
		return {value = formatError( 'unknown-datatype' )}
	end
end

function formatEntityId( entityId, options )
	local label = options.label or mw.wikibase.label( entityId )
	if label == '' then
		label = mw.wikibase.label( entityId ) or nil
	end
	if options.labelformatter and options.labelformatter ~= '' then
		local formatter = require ('Module:Wikidata2/Aux2')
		local fun = formatter[options.labelformatter]
		if fun then
			label = fun(label, options)
		end
	end
	if options.labelgender and options.labelgender ~= '' then
		local labelgenus  = formatStatements({property=(options.labelgenderproperty or 'P1549'), entityId=entityId, langpref = (options.labelgenderlangpref or 'sv'), preferqualifier = (options.labelgenderqualifier or 'P518'), preferqualifiervalue = options.labelgender, noref='true', versalisering = options.versalisering, firstversalisering = options.firstversalisering})
		if labelgenus and labelgenus ~= '' then
			label = labelgenus
		end
	end
	if options.kortnamn and options.kortnamn ~= '' then
		local kortnamn = formatStatements({property='P1813', entityId = entityId, enbarten = 'ja', noref = 'ja'})
		if kortnamn and kortnamn ~= '' then
			label = kortnamn
		end
	end
	
	if options.labelfromnameproperty and options.labelfromnameproperty ~= '' then
		local newlabel = namefordate(options)
		if newlabel and newlabel ~= '' then label = newlabel end
	end
	
	local link = mw.wikibase.sitelink( entityId )

	if link and (not options.nolink or options.nolink == '') then
		if label and label ~= '' then
			return {value = '[[:' .. link .. '|' .. versalisering(label, options) .. ']]', label = label }
		else
			return {value = '[[:' .. versalisering(link, options) .. ']]', label = link }
		end
	else
		if label then
			return {value = versalisering(label, options), label = label}
		else
			local s = getLabelFromFallBack( entityId )
			local l = mw.language.fetchLanguageName(s.language, 'sv')
			if not l or l == '' then
				l = 'okänt språk'
			end
			if s then
				return {value = mw.text.tag('span', {title = l, ['data-q'] = entityId, class='modulwikidata2_missingswedishlabel'}, versalisering(s.value, options) ), cat = 'Wikidataetiketter på ' .. l, label = s.value }
			end
		end
		return {value = entityId, cat = 'som har labels med Qid', label = entityId}
	end
end

function formatFromPattern( str, options )
	-- Escape any % in str with another % before using it as replacement in gsub
	str = string.gsub( str, '%%', '%%%%' )
	return mw.ustring.gsub( options.pattern, '$1',  str) .. '' --Hack to get only the first result of the function
end

local p = {}

function p.formatEntityId( entityId, options )
	return formatEntityId( entityId, (options or {}) )
end

function p.formatStatements( frame, key )
	local args = frame.args

	--If a value if already set, use it
	if args.value and args.value ~= '' then
		return args.value
	end
	return formatStatements( frame.args, key )
end

function p.formatStatementsFromLua( options, key )
	--If a value if already set, use it
	if options.value and options.value ~= '' then
		return options.value
	end
	local s = formatStatements( options, key )
	if s == '' then
		s = nil
	end
	return s
end

-- Return the site link (for the current site) for a given data item.
function p.getSiteLink( frame )
	if frame.args[1] == nil then
		entity = mw.wikibase.getEntityObject()
		if not entity then
			entity = mw.wikibase.getEntityObject(frame.args[1])
		end
		id = entity.id
	else
		id = frame.args[1]
	end

	return mw.wikibase.sitelink( id )
end

local function defaultLabel(entity, lang, displayformat) -- label when no label is available
	if entity and displayformat == 'id' then
		return entity.id
	end
	return formatError('no-label')
end

function p._getLabel(entity, lang, default)
	if not entity then
		return nil
	end
	if type(entity) ~= 'table' then
		entity = p.getEntity(entity)
	end
	if entity and entity.labels then
		if entity.labels[lang] then 
			return entity.labels[lang].value 
		end
		if entity.labels["sv"] then 
			return entity.labels["sv"].value 
			else
				for i, lg in pairs(fallback) do
				if entity.labels[lg] then
					return entity.labels[lg].value
				end
			end	
		end
	end
	return defaultLabel(entity, lang, default)
end

function p.getEntity( val )
	if type(val) == 'table' then
		return val
	end
	return mw.wikibase.getEntityObject(val)
end

-- Simple for simple templates like {{Q|}}}
function p.getLabel(frame) 
	local args = frame.args
	local entity = args.entity
	local lang = args.lang
	if lang == '' then
		lang = defaultlang
	end

	if string.sub(entity, 1, 10) == 'Property:P' then
		entity = string.sub(entity, 10)
	elseif (string.sub(entity, 1, 1) ~= 'P' and string.sub(entity, 1, 1) ~= 'Q') or (not tonumber(string.sub(entity, 2))) then
		return formatError('invalid-id')
	end

	if not args.link or args.link == '' then -- by default: no link
		args.link = '-'
	end
	if args.link == '-' then
		return p._getLabel(entity, lang) or formatError('invalid-id')
	else
		return p.formatEntity(entity, args)
	end
end

-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
-- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm
-- uses the newer mw.wikibase calls instead of directly using the snaks
-- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string
p.getTAValue = function(frame)
	local ent = mw.wikibase.getEntityObject()
	local props = ent:formatPropertyValues('P1323')
	local out = {}
	local t = {}
	for k, v in pairs(props) do
		if k == 'value' then
			t = mw.text.split( v, ", ")
			for k2, v2 in pairs(t) do
				out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]"
			end
		end
	end
	ret = table.concat(out, "<br> ")
	if #ret == 0 then
		ret = "Invalid TA"
	end
	return ret
end

p.commonscat_WD = function(frame)  -- används av mallen commonscat_WD
	local res = ''
	local item = mw.wikibase.getEntityObject()
	local qid = frame:getParent().args[1]
	if qid then item = mw.wikibase.getEntityObject(qid) end
	if item and p.formatStatementsFromLua({property="p373",noref="ja",entityId=item.id}) then 
		res = '* [[Fil:Commons-logo.svg|15px|länk=]] Wikimedia Commons har media som rör ' .. p.formatStatementsFromLua({property="p373",noref="ja",pattern="[[:Commons:Category:$1|$1]]",entityId=item.id})..'.'
    end
    return res
end

p.getEntityIdForCurrentPage = function(frame)
	return mw.wikibase.getEntityIdForCurrentPage()
end

p.getcoord = function(frame)
    local qid = frame.args['qid'] or ''
    local what = frame.args['what'] or ''
    local item = mw.wikibase.getEntityObject(qid)
    local claims = item:getBestStatements( 'P625' )
    if what == 'lat' then 
    	return claims[1].mainsnak.datavalue.value.latitude
    end
    if what == 'long' then 
    	return claims[1].mainsnak.datavalue.value.longitude
	end
	return ''
end

p.getcoordfromproperty = function(frame)
	local qid = frame.args['qid'] or mw.wikibase.getEntityIdForCurrentPage() or ''
	if qid == '' then
		return ''
    end
	local what = frame.args['what'] or ''
	local property = frame.args['property'] or ''
	local item = mw.wikibase.getEntityObject(qid)
	if item['claims'] and item['claims'][property] and item['claims'][property][1]['qualifiers'] and item['claims'][property][1]['qualifiers']['P625']then
		if what=='lat' then return  item['claims'][property][1]['qualifiers']['P625'][1].datavalue.value.latitude end
		if what=='long' then return  item['claims'][property][1]['qualifiers']['P625'][1].datavalue.value.longitude end
		return ''
	else
		return ''
	end
end
	
p.averagepropertyvalue = function(frame)
	--	property is given as Pwww/Pxxx/..../Pyyy/Pzzz (at least two parts)
	--  all properties except the last one should return wikibase items
	--  climb the property path and change entity successively for all P... except the last two.
	--  only the first claim for each P... is considered
    --  finally get the values for the last property (Pzzz) for all values (objects) of Pyyy and return the average value
	--  ranks are not considered
	--  claims with a qualifier corresponding to the argument 'avoidqalifier' is not included in the average
	local options = frame.args
	local what = frame.args['what']
	local avoidqualifier = frame.args['avoidqualifier']
	local entityId = frame.args['qid'] or mw.wikibase.getEntityIdForCurrentPage() or ''
	if entityId == '' then return '' end
	entity = getEntityFromId( entityId )
	local property = frame.args['property']
	if property == nil then return '' end
    local props = mw.text.split(property:upper(),'/')
	for i,prop in ipairs(props) do
		if i<#props-1 then
			if entity.claims[prop] == nil then return '' end
			entityId=entity.claims[prop][1]['mainsnak'].datavalue.value.id
			if entityId == nil then	return '' end
			entity = getEntityFromId( entityId )
		end
		if i == #props-1 then theobjects = prop	end  -- the second last property
		if i == #props then theprop = prop end       -- the very last property
	end
	local summa = 0 
	local n = 0
	res = ''
	if entity.claims[theobjects] == nil then return '' end
	for i,v in ipairs(entity.claims[theobjects]) do
		if v['mainsnak'].datatype ~= 'wikibase-item' then return '' end
		if v['qualifiers'] == nil or v['qualifiers'] and v['qualifiers'][avoidqualifier] == nil then
			entityterm = getEntityFromId(v['mainsnak'].datavalue.value.id)
			if entityterm.claims[theprop] == nil then return '' end
			if entityterm.claims[theprop][1].mainsnak.datatype == 'quantity' then
				n = n + 1 
				summa = summa + tonumber(entityterm.claims[theprop][1].mainsnak.datavalue.value.amount)
				res = summa/n
			elseif entityterm.claims[theprop][1].mainsnak.datatype == 'globe-coordinate' then
				if what=='lat' then 
					n = n + 1
					summa = summa + entityterm.claims[theprop][1].mainsnak.datavalue.value.latitude
					res = summa/n
				elseif what=='long' then
					n = n + 1
					summa = summa + entityterm.claims[theprop][1].mainsnak.datavalue.value.longitude
					res = summa/n
				else
					return ''
				end
			else
				--TODO, not yet implemented
				return ''
			end
		end
	end
	return res
end

return p