Modul:External links

Fra Wikisida.no
Sideversjon per 10. apr. 2016 kl. 21:53 av nb>Stigmj (fix for missing langcodes from wikidata)
Hopp til navigering Hopp til søk

Modulen "External links" inneholder følgende metoder som er ment brukt via maler

getLinks
Henter eksterne lenker fra Wikidata i henhold til en konfigurasjonsfil
Funksjonen har noen få felles standard-parametre som kan benyttes
conf
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=...}}
Den vil da returnere en rekke formaterte lenker til eksterne sider i henhold til en konfigurasjon som ligger som undersider av denne modulen.
Følgende konfigurasjoner er tilgjengelige
  • Arter - Artslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Arter}}. Se {{Artslenker}} for eksempel på bruk.
  • Astronomi - Astronomi, Kalles opp slik: {{#invoke:External links|getLinks|conf=Astronomi}}. Se {{Astronomilenker}} for eksempel på bruk.
  • Autoritetsdata - Autoritetsdata, Kalles opp slik: {{#invoke:External links|getLinks|conf=Autoritetsdata}}. Se {{Autoritetsdata}} for eksempel på bruk.
  • Bryggeri - Bryggerilenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Bryggeri}}. Se {{Bryggerilenker}} for eksempel på bruk.
  • Film - Filmlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Film}}. Se {{Filmlenker}} for eksempel på bruk.
  • Filmperson - Filmpersonlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Filmperson}}. Se {{Filmperson}} for eksempel på bruk.
  • Musikk - Musikklenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Musikk}}. Se {{Musikklenker}} for eksempel på bruk.
  • Offisielle lenker - Offisielle lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Offisielle lenker}}. Se {{Offisielle lenker}} for eksempel på bruk.
  • Politiker - Politiker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Politiker}}. Se {{Politiker}} for eksempel på bruk.
  • Some - Sosiale medie-lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Some}}. Se {{Somelenker}} for eksempel på bruk.
  • Spill - Spill-lenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Spill}}. Se {{Spill-lenker}} for eksempel på bruk.
  • Sport - Sportslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Sport}}. Se {{Sportslenker}} for eksempel på bruk.
  • Skip - Skipslenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Skip}}. Se {{Skipslenker}} for eksempel på bruk.
  • Forsker - Forskerlenker, Kalles opp slik: {{#invoke:External links|getLinks|conf=Forsker}}. Se {{Forskerlenker}} for eksempel på bruk.
  • Test - For testing av nye typer og utvikling, Kalles opp slik: {{#invoke:External links|getLinks|conf=Test}}. Skal ikke benyttes i produksjon.
tittel
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|tittel=...}}
Denne parameteren kan overstyre artikkelnavnet som benyttes videre i modulen. Hvis dette ikke er satt, vil den som standard bruke sidenavnet til artikkelen.
maxlink
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|maxlink=...}}
Denne parameteren setter maksimum antall lenker som vises frem. Standardverdien er satt til 10.
prop
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|prop=<egenskap>,<egenskap2>,...}}
Denne parameteren setter en begrensning på hvilke egenskaper som skal vises frem. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom egenskapen starter med et minus-tegn (-), f.eks. -P345, så vil alle egenskaper, unntatt den som er angitt forsøkes vist frem. Det er mulig å legge inn flere av disse.
kort
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|kort=1}}
Denne parameteren bestemmer om kort-versjonen av lenkene skal benyttes.
inline
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|inline=1}}
Denne parameteren bestemmer om lenkene skal legges på en linje med en separator i mellom seg. Linjen vil ikke prefikses med noen bullet eller lignenden. Se definisjonen av separatoren i Module:External links/conf under ['msg-inline-separator']. Denne funksjonaliteten er ment brukt i tilfeller hvor man ønsker å benytte lenkene i referanser eller lignende.
språk
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|språk=<langcode1>,<langcode2>...}}
Denne parameteren setter en begrensning på hvilke språk som skal vises frem. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom språkkoden starter med et minus-tegn (-), f.eks. -fr, så vil alle språkkoder, unntatt den vises frem. Det er mulig å legge inn flere av disse. Spesial-verdien alle overstyrer og tillater alle språk.
track
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|track=<egenskap1>,<egenskap2>...}}
Denne parameteren styrer individuelle sporingskategorier for hver egenskap. De skilles av med et komma, mellomrom, semikolon eller kolon. Dersom egenskapen starter med et minus-tegn (-), f.eks. -P345, så vil den ikke spores (i tilfelle den er konfigurert til å spores i felleskonfigurasjonen). Det er mulig å legge inn flere av disse, og spesial-koden alle vil slå på sporing på alle.
<egenskapsnavn>
Funksjonen kalles opp slik: {{#invoke:External links|getLinks|conf=<konfigurasjon ihht. ovenfor>|<egenskapsnavn>=<verdi>}}
Dette er en generell måte å sette verdien til en egenskap manuelt fra artikler/maler. Dette er ment brukt for tilfeller hvor man bruker en lokalt definert egenskap og trenger å gi den en verdi fra artikkelen. F.eks. bbfc=46443 vil gi ID-en til Blue Thunder i BBFc sin database, og den manuelle definisjonen av bbfc i Module:External links/conf/Film vil da benyttes sammen med den ID-en for å bygge den eksterne lenken.

Se også


require('Module:No globals')
local genitiv = require('Modul:Genitiv')._genitiv
local contLang = mw.language.getContentLanguage()

local cmodule = {}
local conf = require 'Module:External links/conf'(contLang:getCode())

local p = {}

local function getLabel(entity, use_genitiv, pagetitle)
	local label = (pagetitle and pagetitle ~= '') and pagetitle or nil
	if not label and not entity then
		label = mw.title.getCurrentTitle().text
	elseif not label then
		label = mw.wikibase.label(entity.id) or mw.title.getCurrentTitle().text
	end
	return use_genitiv and genitiv(label) or label
end

-- @todo cleanup, this is in production, use the console
local function dump(obj)
	return "<pre>" .. mw.dumpObject(obj) .. "</pre>"
end


local function stringFormatter( datavalue )
	if datavalue == nil or datavalue['type'] ~= 'string' then
		return nil
	end
	return datavalue.value
end

local qual = {}
qual.P1793 = {
	types = {
		snaktype = 'value',
		datatype = 'string',
	},
}
local pval = {}

qual.P407 = { -- language of work or name
	types = {
		snaktype = 'value',
		datatype = 'wikibase-item',
		datavalue = {
			type = 'wikibase-entityid', 
		}
	},
}

pval.P364 = { -- original language of work 
	types = {
		snaktype = 'value',
		datatype = 'wikibase-item',
		datavalue = {
			type = 'wikibase-entityid', 
		}
	},
}

pval.P218 = { -- ISO 639-1 language 
	types = {
		snaktype = 'value',
		datatype = 'external-id',
		datavalue = {
			type = 'string', 
		}
	},
}

pval.P305 = { -- IETF language tag
	types = {
		snaktype = 'value',
		datatype = 'string',
		datavalue = {
			type = 'string', 
		}
	},
}


local qorder = {'P1793'}

-- This is a really makeshift crappy converter, but it'll do some basic
-- conversion from PCRE to Lua-style patterns (note that this only work
-- in very few cases)
local function regexConverter( regex )
	local output = regex
	output = string.gsub(output, "\\d{2}", "%%d%%d")
	output = string.gsub(output, "\\d{3}", "%%d%%d%%d")
	output = string.gsub(output, "\\d{4}", "%%d%%d%%d%%d")
	output = string.gsub(output, "\\d{5}", "%%d%%d%%d%%d%%d")
	output = string.gsub(output, "\\d{6}", "%%d%%d%%d%%d%%d%%d")
	output = string.gsub(output, "\\d{7}", "%%d%%d%%d%%d%%d%%d%%d")
	output = string.gsub(output, "\\d{8}", "%%d%%d%%d%%d%%d%%d%%d%%d")
	output = string.gsub(output, "\\d", "%%d")
	
	return output
end


local function getFormatterUrl( prop, value )
	local head = ""
	local tail = ""
	local entity = mw.wikibase.getEntity(prop)
	-- to avoid deep tests
	if not entity or not entity.claims then
		return head
	end
	-- get the claims for this entity
	local statements = entity.claims['P1630']
	-- to avoid deep tests
	if not statements then
		return head
	end
	local formatters = {}
	-- let's go through the claims
	for _, claim in ipairs( statements ) do
		-- to avoid deep tests
		if not claim then
			claim = {}
		end
		local valid = claim['type'] == 'statement'
			and claim['rank'] ~= 'deprecated'
		if valid then
			local mainsnak = claim.mainsnak or {}
			local preferred = claim['rank'] == 'preferred'
			-- get any qualifiers for this claim (we are interested in P1793 for
			-- indication of which claim is correct) 
			local qualifiers = claim.qualifiers or {}
			-- now go through the qualifiers we are interested in (defined in
			-- the array qorder above this function)
			for _, qualid in ipairs( qorder ) do
				-- if the claim has this qualifier
				if qualifiers[qualid] then
					-- it's here, let's check it out!
					local items = {}
					-- traverse all snaks in this qualifier
					for _, qualsnak in ipairs( qualifiers[qualid] ) do
						if qualsnak and qual[qualid] and qualid == 'P1793' then
							--mw.log("qualsnak = " .. dump(qualsnak))
							-- check if the snak is of the correct snaktype and datatype
							local valid = qualsnak.snaktype == qual[qualid].types.snaktype
								and qualsnak.datatype == qual[qualid].types.datatype
							if valid then
								-- we'll have to convert the regex to Lua-style
								local regex = regexConverter(qualsnak.datavalue.value)
								local test = string.match( value, '^'..regex..'$' )
								if test then
									-- it matched, this is correct and overrides any other.
									if preferred then
										head = mainsnak.datavalue.value
									else
										tail = mainsnak.datavalue.value
									end
								end
							end
						end
					end
				else
					-- we don't have any qualifier, is it preferred?
					if (head == '' and preferred) or (tail == '' and not preferred) then
						-- if we don't have any other, use this one
						if preferred and head == '' then
							head = mainsnak.datavalue.value
						elseif not preferred and tail == '' then
							tail = mainsnak.datavalue.value
						end
					end
				end
			end
		end
	end
	return head ~= '' and head or tail

end



local function getLanguageData(prop, qid)
	local head = {}
	local tail = {}
	--mw.log("getLanguageData, prop="..dump(prop).." qid="..dump(qid))
	-- get the entity we are checking
	local entity = mw.wikibase.getEntityObject(qid)
	-- to avoid deep tests
	if not entity then
		return nil
	end
	if not entity.claims then
		return {}
	end
	-- get the claims for this entity
	local statements = entity.claims[prop]
	-- to avoid deep tests
	if not statements then
		return {}
	end
	--mw.log("getLanguageData going through claims="..dump(statements))
	-- let's go through the claims
	for _, claim in ipairs( statements ) do
		-- to avoid deep tests
		if not claim then
			claim = {}
		end
		local valid = claim['type'] == 'statement'
			and claim['rank'] ~= 'deprecated'
		if valid then
			local mainsnak = claim.mainsnak or {}
			local preferred = claim['rank'] == 'preferred'
			-- verify the item is what we expect
			local valid = mainsnak.snaktype == pval[prop].types.snaktype
				and mainsnak.datatype == pval[prop].types.datatype
				and mainsnak.datavalue.type == pval[prop].types.datavalue.type
			if valid then
				--mw.log("getLanguageData claim is valid="..dump(claim))
				-- if this is the correct P-value, dive into it and get P218 (ISO 639-1)
				if mainsnak.property == 'P364' then
					if preferred then
						head[#head+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator'))
					else
						tail[#tail+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator'))
					end
				elseif mainsnak.property == 'P218' or mainsnak.property == 'P305' then
					if preferred then
						head[#head+1] = stringFormatter(mainsnak.datavalue)
					else
						tail[#tail+1] = stringFormatter(mainsnak.datavalue)
					end
				end
			end
		end
	end
	--mw.log("getLanguageData returning head="..dump(head).." tail="..dump(tail))
	return #head>0 and head or tail
end


local function getValuesFromWikidata(props)
	local head = {}
	local tail = {}
	--mw.log("getValuesFromWikidata, props="..dump(props))
	-- get the entity we are checking
	local entity = mw.wikibase.getEntityObject()
	-- to avoid deep tests
	if not entity then
		--mw.log("getValuesFromWikidata no entity")
		return nil
	end
	if not entity.claims or not props or not props.prop or props.prop == '' then
		--mw.log("getValuesFromWikidata no claims or no props")
		return {}
	end
	-- get the claims for this entity
	local statements = entity.claims[props.prop]
	-- to avoid deep tests
	if not statements then
		return {}
	end
	-- let's go through the claims
	for _, claim in ipairs( statements ) do
		-- to avoid deep tests
		if not claim then
			claim = {}
		end
		local valid = claim['type'] == 'statement'
			and claim['rank'] ~= 'deprecated'
		if valid then
			--mw.log("getValuesFromWikidata valid claim="..dump(claim))
			local mainsnak = claim.mainsnak or {}
			local preferred = claim['rank'] == 'preferred'
			-- get the content of the claim (the identifier)
			local langcode = props.langcode
			local checklangcode = nil
			if props.langcode and props.langcode ~= '' then
				checklangcode = string.find(langcode, "([pP]%d+)")
			end
			if checklangcode and checklangcode ~= "" then
				-- this is a P-value for language-code, so we'll check qualifiers for languagedata
				-- first get any qualifiers
				local qualifiers = claim.qualifiers or {}
				local qualid = 'P407'
				-- if the claim has this qualifier
				if qualifiers[qualid] then
					-- it's here, let's check it out!
					local items = {}
					-- traverse all snaks in this qualifier
					for _, qualsnak in ipairs( qualifiers[qualid] ) do
						if qualsnak and qual[qualid] and qualid == 'P407' then
							--mw.log("qualsnak = " .. dump(qualsnak))
							-- check if the snak is of the correct snaktype and datatype
							local valid = qualsnak.snaktype == qual[qualid].types.snaktype
								and qualsnak.datatype == qual[qualid].types.datatype
							if valid then
								-- now get the actual data
								langcode = table.concat(getLanguageData('P305', 'Q'..qualsnak.datavalue.value['numeric-id']), '')
							end
						end
					end
				else
					-- we don't have any qualifier, we default to "en"
					langcode = nil
				end
				--mw.log("langcode is now="..dump(langcode))
			end
			if preferred then
				head[#head+1] = { value=stringFormatter(mainsnak.datavalue) }
				if langcode and langcode ~= '' then
					head[#head]['langcode'] = langcode
				end
			else
				tail[#tail+1] = { value=stringFormatter(mainsnak.datavalue) }
				if langcode and langcode ~= '' then
					tail[#tail]['langcode'] = langcode
				end
			end
		end
	end
	--mw.log("getValuesFromWikidata returning head="..dump(head).." tail="..dump(tail))
	return #head>0 and head or tail
end

local function findMainLinksOnWikidata(props, pagetitle, short_links)
	local output = {}
	local pid = nil
	-- get the entity we are checking
	local entity = mw.wikibase.getEntityObject()
	-- to avoid deep tests
	if not entity then
		return nil
	end
	local values = getValuesFromWikidata(props)
	for _, value in ipairs( values ) do
		local verified_value = nil
		if props.regex then
			-- we have a local defined regex, so this will have to pass first
			-- maybe we'll have to convert the regex to Lua-style
			local regex = regexConverter(props.regex)
			local test = string.match( value.value, '^'..regex..'$' )
			--mw.log("testing with "..regex.. " and test="..dump(test).." and value="..id)
			if test then
				-- it matched, this is correct and overrides any other.
				verified_value = value.value
			end
		else
			verified_value = value.value
		end
		if verified_value then
			local url = ''
			output[#output+1] = {}
			output[#output].langcode = value.langcode
			output[#output].category = {}
			if props.url_f then
				-- we have a local defined url-formatter function, use it as first priority
				url = props.url_f(verified_value)
				if props.track and not string.find(props.langcode, "([pP]%d+)") then 
					output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()
				elseif props.track then 
					output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()
				end
			elseif props.url then
				-- we have a local defined url-formatter string, use it as second priority
				url = mw.message.newRawMessage(props.url, verified_value):plain()
				if props.track and not string.find(props.langcode, "([pP]%d+)") then 
					output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain()
				elseif props.track then 
					output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()
				end
			else
				-- get the formatvalue from the property, if it exists
				local formatterUrl = getFormatterUrl(props.prop, verified_value)
				if formatterUrl ~= '' then
					url = mw.message.newRawMessage(formatterUrl, verified_value):plain()
					if props.track then 
						output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain()
					end
				end
			end
			if url ~= '' then
				local langlink = (value.langcode and value.langcode ~= '') and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode) or ""
				if short_links and props.short then
					output[#output].text =
						mw.message.newRawMessage(props.short,
							getLabel(entity, props.genitiv, pagetitle),
							url,
							langlink)
						:plain()
				else
					output[#output].text =
						mw.message.newRawMessage(props.message,
							getLabel(entity, props.genitiv, pagetitle),
							url,
							langlink)
						:plain()
				end
			end
		end
	end
	--mw.log("findMainLinksOnWikidata returning="..dump(output))
	return output
end


local function findMainLinksLocal(props, pagetitle, short_links, local_value)
	local output = {}
	-- to avoid deep tests
	if not props.prop then
		return nil
	end
	if not (local_value or local_value == '') then
		-- bail out if no value is present
		return output
	end
	-- get the formatvalue from the property
	local verified_value = local_value
	if props.regex and props.regex ~= '' then
		-- let's verify the id
		-- maybe we'll have to convert the regex to Lua-style
		local regex = regexConverter(props.regex)
		local test = string.match( local_value, '^'..regex..'$' )
		if test then
			-- it matched, this is correct
			verified_value = local_value
		else
			verified_value = nil
		end
		
	end
	if not verified_value then
		return output
	end
	local wikidata_property = string.find(props.prop, "([pP]%d+)")
	local wikidata_values = {}
	if wikidata_property then
		-- get any wikidata values to see if they are equal to local values
		wikidata_values = getValuesFromWikidata(props)
	end
	if wikidata_property or (props.url and props.url ~= '') or (props.url_f) then
		output[#output+1] = {}
		output[#output].langcode = props.langcode
		output[#output].category = {}
		local url = ''
		if props.track and wikidata_property and wikidata_values and #wikidata_values then
			local local_value_in_wikidata = false
			for _,value in ipairs( wikidata_values ) do
				if value.value == verified_value then
					local_value_in_wikidata = true
				end
			end
			output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), props.prop):plain()
		end
		if props.url_f then
			-- we have a local defined url-formatter function, use it as first priority
			url = props.url_f(verified_value)
			if props.track then 
				output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()
			end
		elseif props.url then
			-- we have a local defined url-formatter string, use it as second priority
			url = mw.message.newRawMessage(props.url, verified_value):plain()
			if props.track then 
				output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain()
			end
		elseif wikidata_property then
			-- get the formatvalue from the property, if it exists
			local formatterUrl = getFormatterUrl(props.prop, verified_value)
			if formatterUrl ~= '' then
				url = mw.message.newRawMessage(formatterUrl, verified_value):plain()
				if props.track then 
					output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-local'), props.prop):plain()
				end
			end
		else
			-- no other choice, bail out
			return {}
		end
		if short_links and props.short then
			output[#output].text =
				mw.message.newRawMessage(props.short,
					getLabel(nil, props.genitiv, pagetitle),
					url)
				:plain()
		else
			local langlink = mw.message.newRawMessage(conf:g('msg-langcode'), props.langcode)
			output[#output].text =
				mw.message.newRawMessage(props.message,
					getLabel(nil, props.genitiv, pagetitle),
					url,
					langlink)
				:plain()
		end
	end
	--mw.log("findMainLinksLocal returning="..dump(output))
	return output
end


local function addLinkback(str, property)
	local id = mw.wikibase.getEntityObject()
	if not id then
		return str
	end
	if type(id) == 'table' then
		id = id.id
	end
	
	local class = ''
	local url = ''
	if property then
		class = 'wd_' .. string.lower(property)
		url = mw.uri.fullUrl('d:' .. id .. '#' .. property)
		url.fragment = property
	else
		url = mw.uri.fullUrl('d:' .. id )
	end
	
	local title = conf:g('wikidata-linkback-edit')
	local icon = '[%s [[File:Blue pencil.svg|%s|10px|baseline|link=]] ]'
	url = tostring(url)
	local v = mw.html.create('span')
		:addClass(class)
		:wikitext(str)
		:tag('span')
			:addClass('noprint plainlinks wikidata-linkback')
			:css('padding-left', '.5em')
			:wikitext(icon:format(url, title))
		:allDone()
	return tostring(v)
end


local function getArgument(frame, argument)
	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
	if args[argument] then
		return args[argument]
	end
	return nil
end


local function removeEntry(conf_claims, identifier, property)
	for i, props in ipairs(conf_claims) do
		if props[identifier] == property then
			table.remove(conf_claims, i)
		end
	end
	return conf_claims
end

function p.getLinks(frame)
	local configured_conf = getArgument(frame, conf:a('arg-conf'))
	if configured_conf then
		cmodule = require ('Module:External_links/conf/'..configured_conf)
	else
		error(mw.message.newRawMessage(conf:g('missing-conf'), configured_conf):plain())
	end
	local output = {}
	local category = {}
	local conf_claims = cmodule:getConfiguredClaims(contLang:getCode())
	local limits = cmodule:getLimits()
	assert(limits, mw.message.newRawMessage(conf:g('missing-limits'), configured_conf):plain())
	local links_shown = getArgument(frame, conf:a('arg-maxlink'))
	local pagetitle = getArgument(frame, conf:a('arg-title'))
	-- get a list of tracked properties from the article itself
	local requested_tracking = getArgument(frame, conf:a('arg-track'))
	if requested_tracking and requested_tracking ~= '' then
		-- the properties should be written as P1234, P2345 and other 
		-- version corresponding to the applicable property-identifiers in the config
		for track_prop in string.gmatch(requested_tracking,"([^ ,;:]+)") do
			-- get the requested properties and be able to access them
			-- like req_prop['P345'] to verify if it was requested
			local remove_track = string.match(track_prop, "^\-(.*)")
			for i,claim in ipairs ( conf_claims )  do
				if remove_track == claim.prop or remove_track == conf:a('mod-filter-all') then
					-- if a property starts with "-", then we'll simply remove that 
					-- property from the conf_claims
					conf_claims[i]['track'] = false
				elseif track_prop == claim.prop or track_prop == conf:a('mod-filter-all') then
					conf_claims[i]['track'] = true
				end
			end
		end
	end
	-- get a list of "approved" properties from the article itself
	local requested_properties = getArgument(frame, conf:a('arg-properties'))
	-- assume all properties are allowed
	local req_prop = {}
	local no_req_prop = false  -- we'll allow properties to be filtered for now 
	if requested_properties and requested_properties ~= '' then
		-- the properties should be written as P1234, P2345 and other 
		-- version corresponding to the applicable property-identifiers in the config
		for i in string.gmatch(requested_properties,"([^ ,;:]+)") do
			-- get the requested properties and be able to access them
			-- like req_prop['P345'] to verify if it was requested
			if i == conf:a('mod-filter-all') then
				-- this is a special modifier, saying we should ignore 
				-- all previous and future positive filters and remove the
				-- filter (with exception of negative filters)
				req_prop = {}
				no_req_prop = true
			end
			local remove_prop = string.match(i, "^\-(.*)")
			if remove_prop then
				-- if a property starts with "-", then we'll simply remove that 
				-- property from the conf_claims
				conf_claims = removeEntry(conf_claims, 'prop', remove_prop)
			elseif not no_req_prop then -- only if we are allowing properties to be filtered 
				req_prop[i] = 1
				-- cheat to make #req_prop indicate populated table
				req_prop[1] = 1
			end
		end
	end
	local requested_langs = getArgument(frame, conf:a('arg-languages'))
	--mw.log("requested_langs="..dump(requested_langs))
	-- assume all languages are allowed
	local req_lang = {}
	local no_req_lang = false  -- we'll allow languages to be filtered for now
	--mw.log("req_lang="..dump(req_lang))
	if requested_langs and requested_langs ~= '' then
		-- the languages should be written as langcodes as used in the conf_claims
		for i in string.gmatch(requested_langs,"([^ ,;:]+)") do
			-- get the requested languages and be able to access them
			if i == conf:a('mod-filter-all') then
				-- this is a special modifier, saying we should ignore 
				-- all previous and future positive filters and remove the
				-- filter (with exception of negative filters)
				req_lang = {}
				no_req_lang = true
			end
			-- like req_lang['en'] to verify if it was requested
			local remove_lang = string.match(i, "^\-(.*)")
			if remove_lang then
				-- if a language starts with "-", then we'll simply remove that 
				-- language from the conf_claims
				conf_claims = removeEntry(conf_claims, 'langcode', remove_lang)
			elseif not no_req_lang then -- only if we are allowing languages to be filtered 
				req_lang[i] = 1
				-- cheat to make #req_lang indicate populated table
				req_lang[1] = 1
			end
		end
	end
	local short_links = getArgument(frame, conf:a('arg-short'))
	if short_links and short_links ~= '' then
		short_links = true
	else
		short_links = false
	end
	local showinline = getArgument(frame, conf:a('arg-inline'))
	if showinline and showinline ~= '' then
		showinline = true
	else
		showinline = false
	end
	if not links_shown or links_shown == '' then
		links_shown = limits['links-shown'] and limits['links-shown'] or 10
	else
		links_shown = tonumber(links_shown)
	end
	local somedataonwikidata = (short_links and false or true)
	local hasdatafromwikidata = false
	local hasdatafromlocal = false
	local haswikidatalink = true -- we assume it's connected
	--mw.log("conf_claims="..dump(conf_claims))
	--mw.log("req_prop="..dump(req_prop))
	--mw.log("req_lang="..dump(req_lang))
	--mw.log("short_links="..dump(short_links))
	for _, props in ipairs(conf_claims) do
		-- if we're called with a list of approved properties or languages, check if this one is "approved"
		if (#req_prop==0 or req_prop[props.prop]) and (#req_lang==0 or req_lang[props.langcode] or string.find(props.langcode, "([pP]%d+)")) then
			local links = {}
			local checkedonwikidata = false
			-- get the any local overriding value from the call
			local wikivalue = getArgument(frame, props.prop)
			--mw.log("wikivalue="..dump(wikivalue))
			if not wikivalue or wikivalue == "" and string.find(props.prop, "([pP]%d+)") then
				-- the property is a Pnnn type, and therefore on Wikidata
				links = findMainLinksOnWikidata(props, pagetitle, short_links)
				if links == nil then
					-- a nil-value indicated no wikidata-link
					haswikidatalink = false
					links = {}
				else
					checkedonwikidata = true
				end
			elseif wikivalue and wikivalue ~= '' then
				-- the property is of another annotation, and therefore a local construct
				links = findMainLinksLocal(props, pagetitle, short_links, wikivalue)
			end
			--mw.log("links="..dump(links))
			for _,v in ipairs(links) do
				-- we'll have to check langcodes again as they may have come from wikidata
				if (#req_lang==0 or req_lang[v.langcode]) then
					if checkedonwikidata and not hasdatafromwikidata then
						-- add a general tracking category for articles with data from wikidata
						hasdatafromwikidata = true
						category[#category+1] = cmodule:getMessage(contLang:getCode(), 'with-data-cat')
					elseif not checkedonwikidata and not hasdatafromlocal then
						-- add a general tracking category for articles with data from template-calls in local articles
						hasdatafromlocal = true
						category[#category+1] = cmodule:getMessage(contLang:getCode(), 'with-local-cat')
					end
					if short_links and props.short and v.text and v.text ~= '' then
						-- if short links were requested, and a short definition exists for this property, let's use it
						if #output==0 then
							output[#output+1] = v.text
						else
							output[#output] = output[#output] .. cmodule:getMessage(contLang:getCode(),'short-list-separator') .. v.text
						end
						somedataonwikidata = true
					elseif not short_links and not showinline and v.text and v.text ~= '' then
						-- only if short links were not requested
						-- output[#output+1] = (#output==0 and "" or conf:g('msg-ul-prepend')) .. (checkedonwikidata and addLinkback(v.text, props.prop) or v.text)
						output[#output+1] = conf:g('msg-ul-prepend') .. (checkedonwikidata and addLinkback(v.text, props.prop) or v.text)
					elseif not short_links and showinline and v.text and v.text ~= '' then
						-- only if short links were not requested
						output[#output+1] = v.text
					end
					if props.track and v.category and #v.category then
						-- add category if tracking is on for this property and a category exists in the link-result.
						for _,cats in ipairs( v.category ) do
							category[#category+1] = cats
						end
					end
					if links_shown>0 then
						links_shown = links_shown - 1
					else
						break
					end
				end
			end
			if links_shown==0 then
				break
			end
		end
	end
	local outtext = "" 
	if short_links and #output>0 then
		-- if these are short links, output the whole thing with linkback to wikidata
		--mw.log("somedataonwikidata="..dump(somedataonwikidata).." and output="..dump(output).." and #output="..dump(#output))
		outtext = (somedataonwikidata 
			and addLinkback(table.concat(output,cmodule:getMessage(contLang:getCode(),'short-list-separator')), nil)
			or table.concat(output,cmodule:getMessage(contLang:getCode(),'short-list-separator')))
	elseif not short_links and not showinline and #output>0 then
		outtext = table.concat(output,"\n")
	elseif not short_links and showinline and #output>0 then
		outtext = table.concat(output,conf:g('msg-inline-separator'))
	end
	if not hasdatafromwikidata then
		category[#category+1] = cmodule:getMessage(contLang:getCode(), 'no-data-cat')
		if not hasdatafromlocal and not short_links then
			outtext = (showinline and '' or conf:g('msg-ul-prepend')) .. cmodule:getMessage(contLang:getCode(), 'no-data-text')
			--outtext = cmodule:getMessage(contLang:getCode(), 'no-data-text')
		end
	end
	if not haswikidatalink then
		category[#category+1] = cmodule:getMessage(contLang:getCode(), 'no-wikilink-cat')
		if not hasdatafromlocal and not short_links then
			outtext = (showinline and '' or conf:g('msg-ul-prepend')) .. cmodule:getMessage(contLang:getCode(), 'no-wikilink')
			--outtext = cmodule:getMessage(contLang:getCode(), 'no-wikilink')
		end
	end
	local nocategory = getArgument(frame, conf:a('arg-no-categories'))
	category = #category>0 and "\n" .. table.concat(category,"\n") or ""
	outtext = outtext .. (nocategory and '' or category) 
	--mw.log("nocategory="..dump(nocategory).." and outtext="..dump(outtext).." and category="..dump(category))
	return outtext
end

function p.getLanguageCode(frame)
	local prop = getArgument(frame, conf:a('arg-properties'))
	local output = getLanguageData(prop)
	return table.concat(output, conf:a('mod-filter-separator'))
end

return p