Modul:Wikidata2

Från Wikipedia
Hoppa till navigering Hoppa till sök

Template-info.png Dokumentation [visa] [redigera] [historik] [rensa sidcachen]


Modulen används för att hämta formaterad data från Wikidata.

Huvudfunktion

Anrop

{{#invoke:Wikidata2|formatStatements|property=p17}}

Parametrar

  • property = Nödvändig parameter som beskriver vilken property som ska hämtas. Exempel: property = P625.
    • om property anges som Pxxx/Pyyy/.../Pzzz traverseras alla P där alla utom det sista måste ge ett wikidataobjekt. Observera att endast det första påståendet på varje "nivå" beaktas.
  • entityId = Det id-nummer den artikel har som du vill hämta property från.
  • entity = Istället för att förse modulen med ett qid-nummer, kan man förse den med hela objektet. Denna parameter vill ha en tabell, varför den bara fungerar inom Lua.
  • enbarten = När bara ett värde ska hämtas. Tex för att hämta bild på heraldiskt vapen, och då inte få tillbaka alla objekt.
  • claimindex = Ger också bara ett värde, men det X:e i raden av befintliga värden.
  • numberofclaims = Om parametern ges ett värde returneras enbart antalet värden.
  • separator = När något annat än "," ska separera en lista på objekt. Tex separator=<br/> Se även conjunction
  • conjunction = Som ovan, men påverkar bara den sista separatorn i en lista av objekt. Default är och.
  • label = När man själv vill välja hur länken ska formateras. Tex [[Blekinge läns vapen|vapen]] fås av att ange label=vapen Den här parametern påverkar även enheter
    • koordlabel = När koordinater ligger i en qualifier, så styrs labeln för länken genom koordlabel-parametern.
  • kortnamn = ger P1813 (kort namn) som label i de fall där det finns
  • labelformatter = ändrar label efter vad som anges i Modul:Wikidata2/Aux2. labelformatter = demonym ändrar tex USA till amerikan
  • labelgender = väljer label efter ett värde i det anropade objektet.
  • labelgenderproperty = vilken property som det ska sökas i (default = P1549)
  • labelgenderlangpref = vilket språk man ska föredra (default = sv)
  • labelgenderqualifier = vilken qualifier man ska söka i (default = P518)
  • pattern = När man vill hämta en sträng och passa in den i ett mönster, exempelvis för att lägga in en kod av något slag istället för $1 i https://viaf.org/viaf/$1/.
    • pattern = auktoritetsdata är ett specialfall av ovanstående. Det "pattern" som används, är då det som är angivet i P1630 (format för URL) för den berörda propertyn.
    • pattern = auktoritetsdata2 kompletterar ovanstående och skapar en länk av typen [https://viaf.org/viaf/$1/ $1]
  • rank = Bestämmer vilken typ av Claims som ska släppas igenom.
    • rank = all släpper igenom alla claims
    • rank = valid släpper igenom preferred och normal, men inte deprecated
    • rank = best (default) släpper igenom preferred, men om det inte finns släpps normal igenom
    • rank = preferred/normal/deprecated släpper igenom angiven rank, men ingen annan
  • avoidqualifier = Sorterar bort värden som är associerade med en viss property i sin qualifier. Exempelvis avoidqualifier=P518 (berörd del) om man vill ha folkmängden för hela orten, inte bara de som är kvinnor eller den andel som bor i Haninge kommun.
  • avoidstringpattern = Sorterar bort värden av typen "string" som innehåller ett visst "pattern". Se Lua reference manual för detaljer om "pattern".
  • nolink = Något värde tar bort länkar, även länkar till enheter görs olänkade.
    • nounitlink = samma som ovan, men påverkar bara enheter.
  • noshortunit = enheter förkortas inte med ett värde i denna parameter, d.v.s kilometer förkortas inte till km, vilket annars är standard.
  • sortbytime = sorterar claims efter datum i qualifiers, detta system används med fördel tillsammans med parameter enbarten ovan
    • sortbytime = chronological sorterar claims i kronologisk ordning i qualifiers
    • sortbytime = inverted sorterar claims i omvänd kronologisk ordning i qualifiers
  • sortnotimeas = möjliggör sortering av tidsvärden som saknas. För närvarande stöds endast parametervärdet maxtime.
  • sortbyvalue = sorterar claims efter värde i qualifiers, detta system används med fördel tillsammans med parameter enbarten ovan
    • sortbyvalue = ascending sorterar claims i stigande ordning i qualifiers
    • sortbyvalue = descending sorterar claims i fallande ordning i qualifiers
  • sortingproperty = Ange vilken property som ska stödas. Det går att lägga in en tabell i denna parameter, men då bara från en annan modul. Default är: 'P585','P571','P580','P569','P582','P570' i given ordning. Hittills stöds properties med datatype = time eller med datatype = value där värdet går att konvertera till ett tal.
  • sortbyarbitrary = sorterar claims efter datum de objekt som länkas i de olika statementen, exempelvis födelsedag för en rad av "barn". Tillåtna värden är 'chronological' eller 'inverted'. Vilken property som ska sökas anges med parameter 'sortingproperty ovan'.
  • langpref = I denna modul finns det ett filter som prioriterar claims som har qualifiern "språk = svenska". Ett värde på parameter langpref inaktiverar detta filter
  • noref = Ange ett värde i denna parameter om du inte är intresserad av att ta med själva källhänvisningen, utan bara datan.
    • noref = noimport Gör att källor av typen "importerad från (P143)" inte visas.
  • sources = basic lägger in ett krav att det ska finnas källor för att ett påstående ska kunna användas
    • sources = required diskvalificerar källor av typen "importerad från (P143)"
  • sourcelimit = N Tillåter max N antal källhänvisningar till ett påstående. Default är 3
  • norefrank = true En funktion som väljer bort "sämre" källor framför bättre är aktiv per default. Användandet av norefrank stänger av denna funktion.
  • versalisering = För att ange vilken versalisering utdatan ska ha. Tillåtna värden är: lc/uc/lcfirst/ucfirst
    • firstversalisering = Samma som ovan, men påverkar bara det första i raden av värden
  • modifytime = fixar med datumformat
    • modifytime = longdate skriver datum på formatet "22 september 2019", dvs ner till datumnivå när så tillåts
    • modifytime = longdatelink, som longdate men med länkning av datum (eller månad) och år, alltså "22 september 2019", "september 2019 eller "2019".
    • modifytime = Y skriver datum på formatet "2019", dvs endast årtal.
    • modifytime = Ylink, som Y men med wikilänkning av årtalet, alltså "2019".
  • modifyqualifiertime = Som ovan, men påverkar bara qualifiers
  • withdate = lägger till (22 september 2019) till det källbelagda värdet. Hämtas från Propertyn för tidpunkt.
  • dateonly = ger enbart tidpunkten för ett claim, inte själva värdet.
  • withintervall = lägger till (22 september 2019-29 september 2019) till det källbelagda värdet. Hämtas från Propertyn för startdatum och Propertyn för slutdatum.
    • withintervall = gift ger att intervallet skrivs ut med ett g. framför.
  • withintervallformat = Y ger att endast årtalen för startdatum och slutdatum visas.
  • withmandatperiod = lägger till mandatperiod om den är angiven. Hämtas från Propertyn för mandatperiod.
  • lowesttimeprecision = skapar ett filter så att tider som är angivna med en timePrecision i Wikidata som under stiger värdet på denna parameter ignoreras. Kan till exempel användas om man inte vill visa datum med precisionen "århundrade" eller sämre där det är problem med hur sådana värden ska tolkas.
  • getsimpleproperty = För att hämta information från det länkade objektet. Denna funktion tillåter ingen iteration, utan går bara en nivå.
    • getproperty = Här anger du vilken property du ska hämta med getsimpleproperty
    • getenbarten = Här anger du om en eller alla statements ska hämtas med getsimpleproperty
    • getmodifytime = Här anger du vilket tidsformat getsimpleproperty ska hämta
    • getraw = Som "raw" nedan
  • raw = är en parameter som kan användas från andra moduler. Den resulterar i att utdatan kommer i en tabell.
  • novalue = En parameter som styr hur "novalue" på Wikidata ska presenteras här. Tomt värde ger 'nil' som resultat
  • somevalue = Som "novalue" ovan
  • relevans = Objekt som saknar en sitelink till svwiki inte kommer att inkluderas.
  • prefix = Text läggs in före svaret
  • suffix = Text läggs in efter svaret
  • getonly = Ett Qid. Hämtar bara objekt som uppfyller vissa krav. P31 = Q127448 för Sverige kommuner. Flera värden är möjliga, såsom Q127448,Q193556 för att få både svenska kommuner och landskap.
  • getonlyproperty = Om en annan property än P31 efterfrågas
  • preferqualifier = Ett Pid. Hämtar endast claims som använder Pid som qualifier.
  • preferqualifiervalue = Specificerar vilket värde som passar till ovanstående. Stöder idag endast Qid.
  • typen = För parameter "type:" för anropet till GeoHack i koordinater. Default värde är landmark
    • koordtypen = dito, men för när koordinaterna ligger i en qualifier.
  • region = för parameter "region:" i anropet till Geohack i samma mall. Om parametern inte används, försöker modulen själv hitta en lämplig region med hjälp av Wikidata.
  • grav = Lägger in qualifiers för gravid och koordinater till gravplatsen. grav=coordonly väljer att skriva ut bara koordinaterna.
  • wdlink = Lägger in en länk efter påståendet till det objekt där påståendet är angivet. Funktionen är inte tillgänglig i kombination med parametern raw
    • wdlink = sup Formaterar länken som WD
    • wdlink = sub Formaterar länken som WD
    • wdlink = small Formaterar länken som WD
  • wdlinklabel = väljer vilken text som ska skrivas ut i länken. Default är: WD
  • primary = väljer om en koordinat ska vara av typen "primary" enl mw:Extension:GeoData eller inte. Vilket ord som helst annat än primary = primary ger en secondary koordinat.
    • koordprimary = dito, men för qualifiers.
  • nogeodataparser = väljer bort mw:Extension:GeoData helt och hållet. Kan vara lämpligt i en test eller projektsida.
  • convertunit = Ger matematisk konvertering av en enhet till en annan (exv cm -> km). Ange ett qid för den data du vill konvertera till! Data som inte går att konvertera hamnar i Wikidata:Påståenden som inte går att konvertera.
  • vardesiffror = När det saknas uppgift om precision i datan från WD, görs konverteringen med detta antal värdesiffror. Default = 3.
  • withoutunit = Skriver inte ut enheten. Fungerar både med och utan konvertering.
  • noformatera = Ger ingen formatering av siffrorna. De kommer ut råa, utan tusenavgränsare och med decimalpunkt isf komma.
  • norounding = Skippa avrundning av värden även om de har upperBound och lowerBound som annars medför avrundning.

Övriga funktioner

  • getEntityIdForCurrentPage - returnerar "id" (Q-numret) för den sida som anropet sker från.
  • getcoord - returnerar latitud eller longitud för angivet objekts (qid) geografiska koordinater (P625).
    Anrop: {{#invoke:Wikidata2|getcoord|qid=<qid>|what=<lat|long>}}
  • getcoordfromproperty - returnerar longitud eller latitud för en qualifier geografiska koordinater (P625) för en property för ett angivet objekt.
    Anrop: {{#invoke:Wikidata2|getcoordfromproperty|qid=<qid>|property=<property>|what=<lat|long>}}
  • averagepropertyvalue> - returnerar medelvärdet av property Pzzz för alla objekt Pyyy där Pyyy nås via en kedja av properties från huvudobjektet <qid> via Pwww, Pxxx och så vidare där endast det första värdet/objektet på varje nivå beaktas. Ingen hänsyn tas till påståendenas rang.
    Anrop: {{#invoke:Wikidata2|averagepropertyvalue|qid=<qid>|property=<Pwww/Pxxx/.../Pyyy/Pzzz>|avoidqualifier=<avoidqualifier>|what=<lat|long>}}. Parametern avoidqualifier kan användas för att utesluta värden på Pzzz med angiven qualifier. Pzzz måste ha datatypen "quantity" eller "globe-coordinate". Parametern what används endast om Pzzz har typen "globe-coordinate".
-- 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('Modul: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 or options.avoidqualifierand then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if not statement.qualifiers then
					table.insert( claims2, statement)
				else
					local avoid= false
					if options.avoidqualifier then
						local ptoavoid = mw.text.split(options.avoidqualifier:upper():gsub(' ',''),',')
						for i, p in pairs(ptoavoid) do
							if statement.qualifiers[p] then
								avoid=true
							end
						end
					end
					local avoidand = false
					if options.avoidqualifierand then
						avoidand = true
						local ptoavoid = mw.text.split(options.avoidqualifierand:upper():gsub(' ',''),',')
						for i,p in pairs(ptoavoid) do
							if not statement.qualifiers[p] then
								avoidand = false	
							end
						end
					end	
					if not (avoid or avoidand) then
						table.insert( claims2, statement)	
					end
				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
				local bd = stat.berorddel
				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 bd and options.withbd then
						s = s .. ' ' .. mw.text.tag('small', {}, '<br />('.. bd ..')')
					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 statement.qualifiers.P518 then
				s.berorddel = formatStatements({property = "P518", 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