Modul:WikidataListe

Fra Wikipedia, den frie encyklopedi
Moduldokumentasjon

Formål

Å hente data fra Wikidata til infobokser når aktuelle data ikke er gitt lokalt.

Det er mulig å spesifisere at det ikke skal være noe i infoboksen selv om Wikidata skulle ha noe ved å oppgi verdi uten.

Bruk

Modulen brukes normalt ved å legge inn en rad i en infoboks ved:

{{#invoke:WikidataListe/test|rad|<diverse parametre>}}

eller for å hente og formattere en verdi fra Wikidata, enten for en infoboks eller for annen tekst ved:

{{#invoke:WikidataListe/test|verdi|<diverse parametre>}}
Parameter Utelatt Forklaring
qid Identitet til sidens tilkoblede wikidataelement Identiteten til et wikidataelement. Verdiene vil hentes fra dette elementet hvis parameteren har verdi.
pid Identitet til egenskapen på Wikidata som skal hentes. Verdiene som returneres kan være tom, enkeltverdi eller liste
param Navnet til en parameter til infoboksen som kan ha verdi som skal overstyre verdien fra Wikidata.
ref Skal verdiene referansebelegges? "nei" vil forhindre det, ellers blir det referanser.
tekst Verdi av param Tekst i venstrekolonnen for raden, hvis ikke det er det samme som verdien i param.
kollaps 5 Et tall som angir hvor mange verdier som skal vises før listen vises sammenslått. Hvis intet argument er gitt blir verdien 5 brukt.
kval Kvalifikatorer på Wikidata som skal vises. En kommaseparert liste med egenskapsidentifikatorer. Listes i den rekkefølge de skal vises, altså som «kval=Pxxx,Pyyy»
Pxxx Betingelser for enkeltkvalifikator. En kommaseparert liste, men foreløpig kun ett tilgjengelig valg «tittel». Hvis den ikke er gitt, vil etiketten til egenskapen brukes. Altså vil for verk (P1686) vises som «For verk: verksnavn/lenke» «P1686=tittel:verk» vil endre dette til «verk: verksnavn/lenke» mens «P1686=tittel:» vil gi kun verksnavn/lenke.

Eksempel

WikidataListe
Hammeren kraftstasjon
Slukeevne6 m³/s[1]
Effekt4,9 megawatt[1]
Årsproduksjon18 GWh[1]
norsknavn = {{{norsknavn|{{#invoke:WikidataListe/test|verdi|qid={{{qid|}}}|pid=P1843|ref=Y}}|}}}

for å hente verdi for norsk navn ut fra lokalt navn på takson (P1843). Eksempelvis vil

{{{norsknavn|{{#invoke:WikidataListe/test|verdi|qid=Q503989|pid=P1843|ref=Y}}|}}}

gi

sørgekåpe[2]
sørgjekåpe (nn)[2]
fiskesholb (se)[2]

som resultat.

Tilsvarende vil lokalt navn (P1705) for Tromsø (Q26087)

{{#invoke:WikidataListe/test|verdi|qid=Q26087|pid=P1705|ref=nei}}

gi

Tromsø kommune
Tromsø kommune (nn)
Romssa suohkan (se)

For kraftverk vil:

{{#invoke:WikidataListe/test|rad|pid=P2957 |qid= {{{qid|}}}|param=slukeevne|ref=Y}} {{#invoke:WikidataListe/test|rad|pid=P2109 |qid= {{{qid|}}}|param=effekt}} {{#invoke:WikidataListe/test|rad|pid=P4131 |qid= {{{qid|}}}|param=årsproduksjon}}

med qid= Q5645687 (Hammeren kraftstasjon (Q5645687)) gi verdiene i denne infoboksen


Referanser

  1. ^ a b c Hafslund Eco Vannkraft, «Hammeren», besøkt 4. oktober 2020[Hentet fra Wikidata]
  2. ^ a b c Artsdatabanken, Artsdatabanken takson-ID 46630, artsdatabanken.no, besøkt 13. september 2022[Hentet fra Wikidata]

local conf = mw.loadData( 'Module:WikidataListe/conf' )
local WikidataDato = require( 'Module:WikidataDato' )
local refs = require 'Module:Reference score'
local p = {}

local kvalUtelat = conf.kvalUtelat
local kvalProp = conf.kvalProp

-- The value given to the properties in the table are not significant, they just need to exist
local useReferences = {
	["P19"] = "fødested",		-- fødested
	["P20"] = "dødssted",		-- dødssted
	["P22"] = "far",			-- far
	["P25"] = "mor",			-- mor
	["P26"] = "ektefelle",		-- ektefelle
	["P40"] = "barn",			-- barn
	["P69"] = "utdannet ved",	-- utdannet ved
	["P84"] = "arkitekt",		-- arkitekt
	["P102"] = "medlem av politisk parti",	-- medlem av politisk parti
	["P106"] = "beskjeftigelse",	-- beskjeftigelse
	["P119"] = "gravsted",			-- gravsted
	["P161"] = "medvirkende",		-- medvirkende
	["P166"] = "utmerkelse",		-- utmerkelse
	["P3373"] = "søsken"			-- søsken
}

local useCountry = {
	["P19"] = "fødested",		-- fødested
	["P20"] = "dødssted"		-- dødssted
}	

local linktext = 'Rediger på Wikidata'
local linktarget = 'https://www.wikidata.org/wiki/%s?uselang=%s#%s'

local kollapsNum = 5

local kategori = nil
local kategorier = ""

local kvalSomLenke = true

function addKat(kat)
	kategorier = kategorier .. kat
end

-- filter(function, table)
function filter(func, tbl)
	local newtbl= {}
	for i, v in pairs(tbl) do
		if func(v) then
			table.insert(newtbl, v)
		end
	end
	return newtbl
 end

function makeLink(label,sitelink,first,link,langlab)
	if first and label then
		local lang = mw.language.getContentLanguage()
		label = lang:ucfirst( label )
	end

	if not link then
		-- Vi ønsker kun tekst, ikke wikilenke
		if label then
			return label
		end
		return ''
	end

	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		local ll = ""
		if langlab and langlab ~= "nb" then
			-- fjerner (for nå?) språk for etiketter som ikke er på bokmål.
			-- ll = " (" .. langlab .. ")"
			--addKat("[[Kategori:Wikidata testing]]")
		end
		return label .. ll
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end

	return ''
end
function kollaps(num)
	if kollapsNum>0 then
		if num>kollapsNum then
			return true
		end
	end
	return false
end

-- Returns an array of non-deprecated claims for the given property.
-- If there's no Wikidata entity or no claims, an empty array is returned.
function getBestStatements( property, qid )
	assert( property )

	local entity = mw.wikibase.getEntity(qid)
	if not entity then
		return {}
	end
	return entity:getBestStatements(property)

end

function getOkStatements(pid,qid)
	local entity = mw.wikibase.getEntity(qid)
	if not entity then
		return {}
	end
	local claims =  entity:getAllStatements(pid)
	local tbl = {}
	for i,claim in ipairs(claims) do
		if claim.rank == "normal" or claim.rank == "preferred" then
			table.insert(tbl,claim)
		end
	end
	return tbl
end

function hasQualifer( claim, qualifier )
	assert( claim )
	assert( qualifier )

	local qualifiers = claim.qualifiers or {}
	local snaks = qualifiers[qualifier] or {}
	
	return not not snaks[1]
end

function isStrange( snak )
	if not snak then
		return nil
	end

	return snak.snaktype == 'novalue'
		or snak.snaktype == 'somevalue'
		or nil
end

function getStrange( snak )
	return (snak.snaktype == 'novalue' and 'ingen')
		or (snak.snaktype == 'somevalue' and 'ukjent')
		or nil
end

function getQualifier( claim, qualifier, strip )
	if not claim.qualifiers then
		return nil
	end
	
	local qualifiers = claim.qualifiers or {}
	if not qualifiers[qualifier] then
		return nil
	end
	
	local snaks = qualifiers[qualifier] or {}
	if not snaks[1] then
		return nil
	end
	
	local snak = snaks[1] or {}
	if isStrange( snak ) then
		return getStrange( snak )
	end
	
	if not strip then
		return mw.wikibase.formatValue( snak )
	end
	
	-- this is to simple for more complex cases
	return tostring( mw.wikibase.formatValue( snak ) ):gsub("%b<>", "")
end

function formatYearQualifier(claim, qualifier)
	assert( claim )
	assert( qualifier )

	local snaks = ( claim.qualifiers or {} )[qualifier] or {}
	if not snaks[1] then
		return nil
	end

	local snak = snaks[1] or {}
	if isStrange( snak ) then
		return getStrange( snak )
	end

	return WikidataDato.aarFraClaim( snak )
end

-- Returns either "ingen", "ukjent", "" or "Qxxxxxx"
function getValue(claim)
	assert( claim )

	local mainsnak = claim.mainsnak or {}
	if isStrange( mainsnak ) then
		return getStrange( mainsnak )
	end

	-- check datatype
	if mainsnak.datatype ~= 'wikibase-item' then
		return nil
	end
	
	local datavalue = mainsnak.datavalue or {}
	if datavalue.type ~= 'wikibase-entityid' then
		return nil
	end
	
	local value = datavalue.value or {}
	if value['entity-type'] ~= 'item' then
		return nil
	end

	-- at this point there should be an ordinary value, but be safe
	return 'Q' .. ( value["numeric-id"] or 'xxxx')
end

function formatValue(value, first, link)
	assert( value )
	--assert( first )
	
	-- setter link til true som default hvis ingen verdi er angitt
	if type( link ) ~= 'boolean' then
		link = true
	end

	if string.sub(value, 1, 1) ~= "Q" then
		-- Verdien er enten "ukjent" eller "ingen"
		return string.format("''%s''", value)
	end

	local label = mw.wikibase.label( value )
	local sitelink = mw.wikibase.sitelink( value )
	if first and label then
		local lang = mw.language.getContentLanguage()
		label = lang:ucfirst( label )
	end

	if not link then
		-- Vi ønsker kun tekst, ikke wikilenke
		if label then
			return label
		end
		return ''
	end

	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		return label
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end

	return ''
end

function formatTimePeriod( claim, first, second )
	local startYear = formatYearQualifier(claim, first)  -- fra dato
			or formatYearQualifier(claim, 'P1319') -- tidligste dato
			or '' -- all fail
	--do return mw.dumpObject(claim.qualifiers['P1326']) end
	local startTitle = (hasQualifer(claim, first) and getQualifier(claim, first, true))
			or (hasQualifer(claim, 'P1319') and getQualifier(claim, 'P1319', true))
			or nil
	local endYear = formatYearQualifier(claim, second)  -- til dato
			or formatYearQualifier(claim, 'P1326') -- seneste dato
			or '' -- all fail
	local endTitle = (hasQualifer(claim, second) and getQualifier(claim, second, true))
			or (hasQualifer(claim, 'P1326') and getQualifier(claim, 'P1326', true))
			or nil
	local asterix = mw.html.create( 'sup' ):wikitext( '*' )
	if startTitle then
		local useFallback = (first == 'P1319') or not hasQualifer(claim, first)
		startYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( useFallback and 'P1319' or first ), startTitle ))
			:wikitext( startYear .. (useFallback and tostring( asterix ) or ''))
	end
	if endTitle then
		local useFallback = (second == 'P1326') or not hasQualifer(claim, second)
		endYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( useFallback and 'P1326' or second ), endTitle ))
			:wikitext( endYear .. (useFallback and tostring( asterix ) or ''))
	end
	return string.format("(%s–%s)", tostring(startYear), tostring(endYear))
end

function formatTimePoint( claim, prop )
	if prop == "P813" then -- P813 (besøksdato) skal inn i sjekkliste etter omskrivning av kallende funksjon
		addKat("[[Kategori:Wikidata testing]]")
	end
	local pointYear = formatYearQualifier(claim, prop)
			or '' -- all fail
	local pointTitle = (hasQualifer(claim, prop) and getQualifier(claim, prop, true))
			or nil
	if pointYear == "" then
		addKat("[[Kategori:Wikidata testing]]")
		pointYear = pointTitle
	end
	if pointTitle then
		pointYear = mw.html.create( 'span' )
			:attr( 'title', string.format("%s: %s", mw.wikibase.getLabel( prop ), pointTitle ))
			:wikitext( pointYear )
	end
	return string.format("(%s)", tostring(pointYear))
end

function formatEdit( qid, langCode, prop )
	if not qid then
		return ''
	end

	local link = mw.ustring.format( linktarget, qid, langCode, prop )

	local text = '[[File:OOjs UI icon edit-ltr-progressive.svg'
		.. '|frameless|text-top|10px'
		.. '|alt=' .. mw.text.nowiki( linktext )
		.. '|link=' .. mw.text.nowiki( link )
		.. '|' .. mw.text.nowiki( linktext )
		.. ']]'

	local html = mw.html.create( 'span' )
		:addClass( 'wb-edithandle' )
		-- @todo this must be adjusted
		-- :attr( 'data-bridge-edit-flow', 'single-best-value' )
		:wikitext( text )

	return tostring( html )
end

-- Returns all values from Wikidata for the given property
-- If no values are found, an empty string is returned.
function getFormattedValues(frame, prop, param, link,calcRefs,qid)
	local claims = getBestStatements(prop,qid)

	local i = 0
	local manglerOversettelse = false
	local formattedValues = {}
	
	for i, claim in ipairs(claims) do
		local value = getValue(claim)
		if value then
			local formattedValue = formatValue(value, i == 1, link)

			if formattedValue == '' then
				-- Målet har ikke en etikett på norsk bokmål, ei heller en artikkel på nowiki.
				-- Vi skriver ut en lenke til Wikidata for å gjøre det enkelt å legge til en etikett.
				-- For vanlige lesere kan det imidlertid være forvirrende med en Wikidata-lenke,
				-- så det er ikke helt optimalt. Vi marker derfor også at artikkelen skal legges til
				--  i en vedlikeholdskategori.
				manglerOversettelse = true
				formattedValue = "[[d:" .. value .. '|' .. value .. ']]'
			end
			
			if useCountry[prop] then
				if (hasQualifer(claim, 'P17') or hasQualifer(claim, 'P131')) then
				
					local country = getQualifier(claim,"P17")
					if not country or country == "" then
						country = getQualifier(claim,"P131")
					end
					if country and country ~= '' then
						formattedValue = formattedValue .. ', ' .. country
						.. "[[Kategori:Artikler hvor sted presiseres med kvalifikator fra Wikidata]]"
					end
				end
			end

			-- Dette er egentlig valg av en algoritme, dvs det burde skrives som et pattern
			if hasQualifer(claim, 'P523') or hasQualifer(claim, 'P524') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P523', 'P524' )
			elseif hasQualifer(claim, 'P580') or hasQualifer(claim, 'P582') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P580', 'P582' )
			elseif hasQualifer(claim, 'P729') or hasQualifer(claim, 'P730') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P729', 'P730' )
			elseif hasQualifer(claim, 'P2031') or hasQualifer(claim, 'P2032') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P2031', 'P2032' )
			elseif hasQualifer(claim, 'P3415') or hasQualifer(claim, 'P3416') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P3415', 'P3416' )
			elseif hasQualifer(claim, 'P575') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P575' )
			elseif hasQualifer(claim, 'P585') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P585' )
			elseif hasQualifer(claim, 'P606') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P606' )
			elseif hasQualifer(claim, 'P813') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P813' )
			elseif hasQualifer(claim, 'P1191') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1191' )
			elseif hasQualifer(claim, 'P1249') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1249' )
			elseif hasQualifer(claim, 'P3999') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P3999' )
			elseif hasQualifer(claim, 'P1319') or hasQualifer(claim, 'P1326') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P1319', 'P1326' )
			end

			if formattedValue ~= '' then
				local tmp = nil
				if  calcRefs == 'Y' and useReferences[prop]
				then
					tmp = refs.render(frame, claim.references)
				end
				table.insert(formattedValues, formattedValue..(tmp or ''))
			end
			
		end
	end

	local resultat = table.concat(formattedValues, ", ")

	local qid = mw.wikibase.getEntityIdForCurrentPage()
	local langCode = mw.language.getContentLanguage():getCode()

	if #formattedValues > 0 then
		resultat = resultat .. formatEdit( qid, langCode, prop )
	end

	-- use of # to get count will fail in the future
	if kollaps(#formattedValues) then
		resultat = string.format([[
			<div class="mw-collapsible mw-collapsed">
				<div class="sentrert">%s oppføringer</div>
				<div class="mw-collapsible-content">%s</div>
			</div>
		]], #formattedValues, resultat)
	end

	if manglerOversettelse then
		resultat = resultat .. "[[Kategori:Artikler hvor " .. param .. " mangler oversettelse]]"
	end

	return resultat
end

function getFrameValue(frame, params)
	local args = frame.args
	if args[1] == nil then
		local pFrame = frame:getParent();
		args = pFrame.args;
		for k,v in pairs( frame.args ) do
			args[k] = v;
		end
	end
	
	-- params kan være én enkelt verdi eller flere verdier adskilt med komma.
	-- F.eks. vil "religion,livssyn" sjekke både "religion" og "livssyn".
	for param in mw.text.gsplit( params, ',', true ) do
		 if args[param] then
			return mw.text.trim( args[param] )
		 end
	end
	return ""
end

function _strip( str )
	return string.sub( str, 2 , string.len( str )-1 )
end

function strip( str )
	local lang = mw.language.getContentLanguage()
	-- Fjern mest mulig formatering fra den lokale verdien
	local stripped = str:gsub("<span[^>]-wb%-edithandle[^>]*>.-</span>", "")
			:gsub("%[%[([^%[%]%{%}%|]+)%|([^%[%]%{%}%|]+)%]%]", "%2")
	stripped = stripped:gsub("%b<>", "")
	local last = nil
	repeat
		last = stripped
		stripped = stripped:gsub( "(%b[])", _strip )
				:gsub( "(%b{})", _strip ) -- not sure if this should be escaped
				:gsub( "(%b())", _strip )
	until ( last == stripped )
	stripped = stripped:gsub("''+", "")
			:gsub("^%s+", "")
			:gsub("%s+$", "")
			:gsub("(%s)%s+", "%1")
	stripped = lang:uc(stripped)
	return stripped
end

function velg(frame, prop, param, link, qid)
	local verdiFraFrame = getFrameValue(frame, param)
	if verdiFraFrame == "uten" then
		-- Hvis malargumentet er satt til "uten" betyr det at det ikke er ønskelig
		-- at feltet vises, selv om det finnes data på Wikidata.
		return "[[Kategori:Artikler hvor " .. param .. " spesifisert som uten]]"
	end
    local calcRefs = 'Y'	
	if verdiFraFrame ~= '' then
		-- Hvis malargumentet er satt til en lokal verdi betyr det at det ikke er ønskelig
		-- at feltet vises med lokal data, selv om det finnes data på Wikidata.
		-- Ikke beregn referanser for at de ikke skal komme med i referanselisten
		-- Lag Wikidata resultatene slik at det kan sammenlignes og lages vedlikeholdkategorier
		calcRefs = 'N'
	end

	local verdiFraWikidata = getFormattedValues(frame, prop, param, link,calcRefs,qid)
	if verdiFraWikidata == "" then
		-- No value at Wikidata.
		if verdiFraFrame == "" then
			return ""
		end
		return verdiFraFrame .. "[[Kategori:Artikler hvor " .. param .. " mangler på Wikidata]]"
	end

	if verdiFraFrame == "" then
		if verdiFraWikidata == "" then
			return ""
		end
		return verdiFraWikidata .. "[[Kategori:Artikler hvor " .. param .. " hentes fra Wikidata]]"
	end

	if strip(verdiFraFrame) == strip(verdiFraWikidata) then
		-- Den lokale verdien er helt lik Wikidata-verdien
		return verdiFraWikidata -- .. "[[Kategori:Artikler hvor " .. param .. " samme som på Wikidata]]"
	end

	-- Den lokale verdien er ikke *helt* lik Wikidata-verdien, men vi vet ikke om det er
	-- snakk om betydningsforskjeller.
	return verdiFraFrame .. "[[Kategori:Artikler hvor " .. param .. " forskjellig fra Wikidata]]"
end

function rad( frame, prop, param, link, displayName, qid )
	assert( frame )
	local lang = mw.language.getContentLanguage()
	local verdiFraFrame = getFrameValue( frame, param )
	local value = velg( frame, prop, param, link, qid )
	displayName = displayName or lang:ucfirst(param)
	if verdiFraFrame == "uten" then
		-- I dette tilfellet har velg() returnert en kategori av typen
		-- [[Kategori:Artikler hvor {param} spesifisert som uten]].
		-- Vi sender denne videre.
		return value
	end
	if value == "" then
		return ""
	end
	return string.format([[
		<tr class="rad" valign="top">
			<th colspan="2" class="nowrap">%s</th>
			<td colspan="2">%s</td>
		</tr>
	]], displayName, value)
end

function p.radOld(frame)
	assert( frame )
	if frame.args['ref'] then
		useReferences[frame.args['wdp']] = "frame.args['param']"
	end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    
	return rad(frame, frame.args['wdp'], frame.args['param'], nil, frame.args['tekst'], qid)
end
function p.values(frame)
	assert( frame )
	if frame.args['ref'] then
		useReferences[frame.args['wdp']] = "frame.args['param']"
	end
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end

	return velg(frame, frame.args['wdp'], frame.args['param'], true, qid)
end


-- nye metoder


local ucfirst = "1"
local present = "1"

local sprakNb = {
	["nb"] = "bokmål",
}
local sprakNo = {
	["nb"] = "",     -- bokmål
	["nn"] = " ([[nynorsk|nn]])",
	["se"] = " ([[nordsamisk|se]])",
}

-- todo - spesialhåndtering av varighet. Slik som for P2415
-- todo - Kategorier? for mangler 
function fmtValue(snak)
	local res = nil
	if snak.snaktype == "value" and snak.datatype == "quantity" then
		local value = snak.datavalue.value or nil
		local q = string.match( value.unit, "Q[0-9]*")
		local prop = getBestStatements("P5061",q)
		prop = filtrerClaims(prop,sprakNo)
		--return "<pre>" .. mw.text.jsonEncode(prop, mw.text.JSON_PRETTY) .. "</pre>"
		if prop and prop[1] then
			local label = prop[1].mainsnak.datavalue.value.text
			local sitelink = mw.wikibase.sitelink( q )
			local txt =  makeLink(label,sitelink,false,true)
			return tostring(tonumber(value.amount)) .. " " .. txt
		end
--		res = mw.wikibase.label(q)
	end
	return res
end

function formatUrl(url)
	local urltext = url
	local j1 = string.find(urltext,'//',1,true)
	if j1 then urltext = string.sub(urltext,j1+2,string.len(urltext)) else urltext = '' end
	if urltext ~= '' then
		local i1 = string.find(urltext,'/',1,true)
		if i1 then urltext = string.sub(urltext,1,i1-1) end
	else
		urltext = url
	end
	return "[" .. url .. " " .. urltext .. "]"
end


function formatAsLabel(qid)
	return mw.wikibase.label(qid) 
end

function formatAsLink(qid)
	local sitelink = mw.wikibase.sitelink( qid )
	local label = mw.wikibase.label( qid ) 
	return makeLink( label, sitelink, false, true )
end

function formatUrl(url)
	local urltext = url
	local j1 = string.find(urltext,'//',1,true)
	if j1 then urltext = string.sub(urltext,j1+2,string.len(urltext)) else urltext = '' end
	if urltext ~= '' then
		local i1 = string.find(urltext,'/',1,true)
		if i1 then urltext = string.sub(urltext,1,i1-1) end
	else
		urltext = url
	end
	return "[" .. url .. " " .. urltext .. "]"
end

function p.formatLenke(sitelink,label)
	if label and sitelink then
		return '[[' .. sitelink .. '|' .. label .. ']]'
	end
	if label and not sitelink then
		return label
	end
	if sitelink and not label then
		return '[[' .. sitelink .. ']]'
	end
	return ''
end

--  Todo: Skriv om
function formatTime(claim)
			-- Dette er egentlig valg av en algoritme, dvs det burde skrives som et pattern
			local formattedValue = ""
			if hasQualifer(claim, 'P523') or hasQualifer(claim, 'P524') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P523', 'P524' )
			elseif hasQualifer(claim, 'P580') or hasQualifer(claim, 'P582') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P580', 'P582' )
			elseif hasQualifer(claim, 'P729') or hasQualifer(claim, 'P730') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P729', 'P730' )
			elseif hasQualifer(claim, 'P2031') or hasQualifer(claim, 'P2032') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P2031', 'P2032' )
			elseif hasQualifer(claim, 'P3415') or hasQualifer(claim, 'P3416') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P3415', 'P3416' )
			elseif hasQualifer(claim, 'P575') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P575' )
			elseif hasQualifer(claim, 'P585') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P585' )
			elseif hasQualifer(claim, 'P606') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P606' )
			elseif hasQualifer(claim, 'P813') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P813' )
			elseif hasQualifer(claim, 'P1191') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1191' )
			elseif hasQualifer(claim, 'P1249') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P1249' )
			elseif hasQualifer(claim, 'P3999') then
				formattedValue = formattedValue .. ' ' .. formatTimePoint( claim, 'P3999' )
			elseif hasQualifer(claim, 'P1319') or hasQualifer(claim, 'P1326') then
				formattedValue = formattedValue .. ' ' .. formatTimePeriod( claim, 'P1319', 'P1326' )
			end
	return formattedValue
end

function fSpraak(spraakid,propid)
	local prop = getBestStatements(propid,spraakid) 
	if prop then
		if not prop[1] then
			return nil
		end
		local mainsnak = prop[1].mainsnak
		if not mainsnak or mainsnak.snaktype ~= "value" then
			return nil
		end
		local kortnavn = mainsnak.datavalue.value or nil
		local sitelink = mw.wikibase.sitelink( spraakid )
		return p.formatLenke(sitelink,kortnavn)
	end	
	return nil
end

function p.formatSpraak(snak)
	assert( snak )
	
	local spraakid = snak.datavalue.value.id or nil
	if not spraakid then
		return nil
	end
	local props = {"P218","P220"}
	for ix,prop in ipairs(props) do
		local res = fSpraak(spraakid,prop)
		if res then
			return res
		end
	end
	local lab = mw.wikibase.label(spraakid)

	return lab
end

function formatQualifierSnak(snak,pval,sep)
	if true then
		--return dump(snak)
	end
	if snak and snak.snaktype == "value" then
		if pval == "P407" then
			return p.formatSpraak(snak)
		end
		if snak.datatype == "wikibase-item" then
			local q = snak.datavalue.value.id
			if kvalSomLenke then
				return formatAsLink( q )
			end
			return formatAsLabel(q)
		end
		if snak.datatype == "time" then
			return ""
		end
		return "" --mw.wikibase.formatValues(qv)
	end
end
function formatQualifierProp(quals,pval,sep,props)
	local txt = ""
	if quals and pval and not kvalUtelat[pval] then
		local qv = quals[pval]
		if qv then
			local proplab,lang = mw.wikibase.getLabelWithLang(pval)
			local pq = kvalProp[pval]
			if ( props and props[pval] ) then
				pq = props[pval]
			end
			if pq then
				if pq["tittel"] then
					proplab = pq["tittel"]
				end
			end
			if proplab and proplab ~= "" then
				sep = sep .. proplab .. ": "
			end
			for ix,snak in ipairs(qv) do
				local qualTxt = formatQualifierSnak(snak,pval,sep)
				if qualTxt and qualTxt ~= "" then
					txt = txt .. sep .. qualTxt
					sep = ", "
				end
			end
		end
	end
	return txt
end
function formatQualifiers(quals,props)
	if not quals then
		return ""
	end
	local txt = ""
	local kat = ""
	if kategori then
		kat = "[[Kategori:Artikler hvor kvalifikator hentes fra Wikidata]]"
	end
	local sep = " ("
	if not props or #props == 0 then
		for prop, qual in pairs(quals) do
			local qualTxt = formatQualifierProp(quals,prop,sep)
			if qualTxt and qualTxt ~= "" then
				txt = txt ..  qualTxt 
					if not kvalProp[prop] then
						addKat(kat)
						txt = txt .. kat
					end
				sep = ", "
			end
		end
	else
		--txt = txt .. dump(props)
		for ix,prop in ipairs(props) do
			local qualTxt = formatQualifierProp(quals,prop,sep,props)
			if qualTxt and qualTxt ~= "" then
				txt = txt .. qualTxt
				sep = ", "
			end
		end
	end
	if txt ~= "" then
		txt = txt .. ")"
	end
	return txt
end

function filtrerMonolingualtext(claim,lang)
	local snak = claim.mainsnak
	if lang[snak.datavalue.value.language] then
		return claim
	end
	return nil
end

function filtrerClaim(claim)
	local snak = claim.mainsnak
	if snak.snaktype ~= "value" then
		return nil
	end
	local datatype = snak.datatype 
	if datatype == 'monolingualtext' then
		return filtrerMonolingualtext(claim,sprakNo)
	end
	return claim
end

function filtrerClaims(claims)
	local resultat = {}
	for i, claim in ipairs(claims) do
		local filtrert = filtrerClaim(claim)
		if filtrert then
			table.insert(resultat, filtrert)
		end
	end
	return resultat
end
function sorterClaims(claims)
	local resultat = {}
	for i, claim in ipairs(claims) do
		table.insert(resultat, claim)
	end
	return resultat
end
function dump(item)
	return "<pre>" .. mw.text.jsonEncode(item, mw.text.JSON_PRETTY) .. "</pre>"
end
function formaterClaim(claim,claims,qualifierProps,uc)
	local snak = claim.mainsnak
	local qu = claim.qualifiers
	local rf = claim.references
	local pr = snak.property
	local lang = mw.language.getContentLanguage()

	local fmtClaim = mw.wikibase.formatValue(snak)
	local doFmtQual = true
	if snak.snaktype ~= "value" then
			--	refValue = datatype .. ": Ingen verdi"
	else
		
		local datatype = snak.datatype 
		if datatype == 'url' then
		 	fmtClaim = formatUrl(snak.datavalue.value)
		 	local qt = formatQualifiers(qu,{"P407"})
			if qt and qt ~= "" then
				fmtClaim = fmtClaim .. qt
			end
			doFmtQual = false
		elseif datatype == 'time' then
			fmtClaim = WikidataDato.norskDatoFraClaim(snak)
		elseif datatype == 'monolingualtext' then
			local txt = sprakNo[snak.datavalue.value.language]
			if txt then
				fmtClaim = fmtClaim .. txt
			end
		elseif datatype == 'quantity' then
			local val = fmtValue(snak)
			if val then
				fmtClaim = val
			end
		elseif datatype == 'wikibase-item' then
			local q = snak.datavalue.value.id
			local label,lang = mw.wikibase.getLabelWithLang(q)
			local sitelink = mw.wikibase.sitelink( q )
			if label and label ~= "" then
				fmtClaim =  makeLink(label,sitelink,uc,true,lang)
			end

			--refValue = formatItem(property)
		end
	end
	local formatertKval = ""
	if doFmtQual then
		formatertKval = formatQualifiers(qu,qualifierProps)
	end
	local formatertTid = formatTime(claim)
	fmtClaim = fmtClaim .. formatertTid .. formatertKval

	return fmtClaim
end

function formaterClaims(claims,qualifierProps)
	if not claims then
		return ""
	end
	local formattedValues = {}
	local uc = true
	-- ucfirst: 1 : ingen uc; 2 : uc for første claim; 3 : uc for alle
	if ucfirst == "1" then
		uc = false
	end
	for i, claim in ipairs(claims) do
		local resultat = formaterClaim(claim,claims,qualifierProps,uc)
		if resultat then
			if useReferences[claim.mainsnak.property] then
				local ref = refs.render(mw.getCurrentFrame(), claim.references)
				resultat = resultat .. ref
			end
			table.insert(formattedValues, resultat)
			if ucfirst == "2" then
				uc = false
			end
		end
	end	return formattedValues
end

function getWikidataVerdi(qid,pid,qualifierProps,vis)
	local verdiListe = ""
	local claims = nil
	if vis and vis == "beste" then
		claims = getBestStatements(pid,qid)
	else
		claims = getOkStatements(pid,qid)
	end


	local i = 0
	local manglerOversettelse = false
	local filtrerteClaims = filtrerClaims(claims)
	local sorterteClaims = sorterClaims(filtrerteClaims)
	local formattedValues = formaterClaims(sorterteClaims,qualifierProps)
	
	if present == "løpende tekst" and #formattedValues > 2 then
		verdiListe = " "
		local sep = ""
		for i,val in ipairs(formattedValues) do
			if i == #formattedValues then
				sep = " og "
			end
			verdiListe = verdiListe .. sep .. val
			sep = ", "
		end
		return verdiListe
	end

	local sep = "<br/>"
	if kollaps(#formattedValues) then
		sep = "<br/>"
	end
	
	verdiListe = table.concat(formattedValues, sep)
	
	if kollaps(#formattedValues) then
		verdiListe = string.format([[
			<div class="mw-collapsible mw-collapsed">
				<div class="sentrert">%s oppføringer</div>
				<div class="mw-collapsible-content">%s</div>
			</div>
		]], #formattedValues, verdiListe)
	end

	return verdiListe
end

function p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	local verdi = getFrameValue(frame, param)
	if verdi == "uten" then
		-- Hvis malargumentet er satt til "uten" betyr det at det ikke er ønskelig
		-- at feltet vises, selv om det finnes data på Wikidata.
		addKat("[[Kategori:Artikler hvor parameter spesifisert som uten]]")
		return ""
	end
	if verdi ~= '' then
		return verdi .. ""
	end
	if not pid or pid=="" then
		return ""
	end
	useReferences[pid] = "ja"
	if ref and ref == 'nei' then
		useReferences[pid] = nil
	end
	verdi = getWikidataVerdi(qid,pid,qualifierProps,vis)
 	return verdi
end

function p._rad2(frame,qid,pid,param,ref,sprak,displayName,qualifierProps,vis)
	local verdi = p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	if not verdi then
		return ""
	end
	if verdi == '' then
		return verdi .. ""
	end
 	return '<tr class="rad" valign="top">' ..
			'<th colspan="2" class="nowrap">' ..  displayName .. '</th>' ..
			'<td colspan="2">' .. verdi .. '</td>' ..
		'</tr>' -- lagRad(verdi,displayName)

end

function qualpropargs(qp,txt)
	if not txt or txt == "" then
		return
	end
	local xxx = mw.text.split(txt, ',', true )
	for j,pkval in ipairs(xxx) do
		local pk = mw.text.split(pkval, ':', true )
		
		qp[pk[1]] = pk[2]
	end
end	
function qualargs(qual,args)
	if not qual or qual == "" then
		return nil
	end
	local qp = mw.text.split(qual, ',', true )
	for i,prop in ipairs(qp) do
		if args[prop] then
			qp[prop] = {} --args[prop]
			if true then
				qualpropargs(qp[prop],args[prop])
			else
			local ap = args[prop] or ""
			for j,pkval in mw.text.split(ap, ',', true ) do
				local pk = mw.text.split(pkval, ':', true )
				qp[prop][pk[1]] = pk[2]
			end
			end
		end
	end
	return qp
end

function p.verdi(frame)
	assert( frame )
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    local pid = frame.args['pid'] or frame.args['wdp'] or nil
    local ref = frame.args['ref'] or nil
    ucfirst = frame.args['ucfirst'] or "1"
    local param = frame.args['param'] or "xxx"
    local sprak = frame.args['språk'] or nil
    local vis = frame.args['vis'] or nil
    present = frame.args['presenter'] or "1"
	local argsp = frame.args
	local qualifierProps = qualargs(argsp['kval'],argsp )
    local resultat = p._verdi(frame,qid,pid,param,ref,sprak,qualifierProps,vis)
	return resultat
end

function p.rad(frame)
	assert( frame )
	if frame.args['kollaps'] then
    	kollapsNum = tonumber(frame.args['kollaps'])
    end
    local qid = nil
	if frame.args['qid'] and frame.args['qid'] ~= "" then
		qid = frame.args['qid']
	end
    local pid = frame.args['pid'] or frame.args['wdp'] or nil
    local ref = frame.args['ref'] or nil
    ucfirst = frame.args['ucfirst'] or "1"
    local param = frame.args['param'] or "xxx"
    local sprak = frame.args['språk'] or nil
    local vis = frame.args['vis'] or nil
    kategori = frame.args['kat'] or nil
	local lang = mw.language.getContentLanguage()
	local displayName = frame.args['tekst'] or lang:ucfirst(param)
	local argsp = frame.args
	local qualifierProps = qualargs(argsp['kval'],argsp )
    local resultat = p._rad2(frame,qid,pid,param,ref,sprak,displayName,qualifierProps,vis) --{"P1686","P1706","P1552"})
    --resultat = dump(qp)
	return resultat .. kategorier
end


return p