Pojdi na vsebino

Modul:Authority control

Iz Wikipedije, proste enciklopedije
Documentation icon Dokumentacija modula[predogled] [uredi] [zgodovina] [osveži]

Ta modul vsebuje kodo za predlogo {{Normativna kontrola}}. Glej njeno dokumentacijo.

Parametri, lastnosti Wikipodatkov in sledilne kategorije

Parameter Poglavje Se pojavi kot Wikidata property Sledilne kategorije in števci strani
Članki Uporabniške strani Razne strani Napačni IDji
AAG Umetnostne galerije in muzeji Auckland Auckland Art Gallery artist ID (P3372) 111 0 0 1
ACM-DL Znanstvene podatkovne baze Association for Computing Machinery ACM Digital Library author ID (P864) 47 0 0 1
ADB Biografski slovarji Avstralija Australian Dictionary of Biography ID (P1907) 176 0 0 1
AGSA Umetnostne galerije in muzeji Južna Avstralija Art Gallery of South Australia creator ID (P6804) 86 0 0 1
autores.uy Biografski slovarji Uruguay autores.uy ID (P2558) 9 0 0 1
AWR Biografski slovarji Australian Women's Register Australian Women's Register ID (P4186) 61 0 0 1
BIBSYS Narodne knjižnice Norveška BIBSYS (P1015) 8.068 0 0 1
Bildindex Inštituti za umetnostno raziskovanje Bildindex (Nemčija) (Depreciated) Bildindex der Kunst und Architektur ID (P2092) 168 0 0 1
BNC Narodne knjižnice Čile CCAB ID (P1890) 1.616 0 0 1
BNE Narodne knjižnice Španija BNE (P950) 11.009 0 0 1
BNF Narodne knjižnice Francija (data) BNF (P268) 26.643 0 0 1
Botanist Znanstvene podatkovne baze International Plant Names Index okrajšava botaničnega avtorja (P428) 153 0 0 1
BPN Biografski slovarji Nizozemska Biografisch Portaal van Nederland ID (P651) 526 0 0 1
CANTIC Narodne knjižnice Katalonija CANTIC (P1273) 22 0 0 1
CINII Znanstvene podatkovne baze CiNii (Japonska) NACSIS-CAT author ID (P271) 6.739 0 0 2
CWGC Drugo Commonwealth War Graves Commission CWGC person ID (P1908) 133 0 0 1
DAAO Inštituti za umetnostno raziskovanje Australian Artists Design & Art Australia Online ID (P1707) 14 0 0 1
DBLP Znanstvene podatkovne baze DBLP (computer science) DBLP author ID (P2456) 242 0 0 1
DIB Biografski slovarji Irska Dictionary of Irish Biography ID (P6829) 143 0 0 1
DSI Inštituti za umetnostno raziskovanje Scientific illustrators Identifikator Stuttgartske podatkovne zbirke znanstvenih ilustracij (P2349) 183 0 0 1
FAST Drugo Faceted Application of Subject Terminology FAST (P2163) 17.053 0 0 1
FNZA Inštituti za umetnostno raziskovanje New Zealand Artists Find NZ Artists ID (P6792) 4 0 0 1
GND Splošno Integrated Authority File (Nemčija) GND (P227) 41.933 0 0 1
HDS Drugo Zgodovinski leksikon Švice HDS (P902) 1.627 0 0 1
IAAF Drugo World Athletics World Athletics ID (P1146) 1.510 0 0 1
ICCU Narodne knjižnice Italija SBN (P396) 6.424 0 0 1
ICIA Inštituti za umetnostno raziskovanje ICIA (Izrael) Information Center for Israeli Art artist ID (P1736) 3 0 0 1
IEU Drugo Internet Encyclopedia of Ukraine Internet Encyclopedia of Ukraine ID (P9070) 250 0 0 1
ISNI Splošno ISNI ISNI (P213) 24.519 0 0 1
Joconde Inštituti za umetnostno raziskovanje Joconde (Francija) Joconde work ID (P347) 81 0 0 1
KULTURNAV Inštituti za umetnostno raziskovanje KulturNav (Norveška) oznaka KulturNav (P1248) 1.551 0 0 1
LCCN Narodne knjižnice ZDA LCCN (P244) 42.048 0 0 1
LIR Drugo Lexicon Istoric Retic (Švica) Lexicon istoric retic ID (P886) 30 0 0 1
LNB Narodne knjižnice Latvija LNB (P1368) 7.164 0 0 1
Léonore Drugo Léonore (Francija) Léonore ID (P640) 0 0 0 0
MA Drugo Microsoft Academic oznaka Microsoft Academic (P6366) 0 0 0 0
MBA Drugo MusicBrainz artist izvajalec MusicBrainz (P434) 5.397 0 0 1
MBAREA Drugo MusicBrainz area področje na MusicBrainz (P982) 4.320 0 0 1
MBI Drugo MusicBrainz instrument oznaka glasbila MusicBrainz (P1330) 125 0 0 1
MBL Drugo MusicBrainz label oznaka založbe MusicBrainz (P966) 138 0 0 1
MBP Drugo MusicBrainz place oznaka kraja MusicBrainz (P1004) 552 0 0 1
MBRG Drugo MusicBrainz release group oznaka skupine izdaj MusicBrainz (P436) 1.336 0 0 1
MBS Drugo MusicBrainz series oznaka serije MusicBrainz (P1407) 135 0 0 1
MBW Drugo MusicBrainz work oznaka dela MusicBrainz (P435) 694 0 0 1
MGP Znanstvene podatkovne baze Mathematics Genealogy Project Mathematics Genealogy Project (P549) 1.138 0 0 1
NARA Drugo National Archives (ZDA) oznaka NARA (P1225) 4.015 0 0 1
NCL Narodne knjižnice Tajvan NCL ID (P1048) 139 0 0 1
NDL Narodne knjižnice Japonska NDL (P349) 9.747 0 0 1
NGV Umetnostne galerije in muzeji Viktorija National Gallery of Victoria artist ID (P2041) 200 0 0 1
NKC Narodne knjižnice Češka republika NKČR (P691) 27.036 0 0 1
NLA Narodne knjižnice Avstralija NLA (P409) 6.290 0 0 1
NLG Narodne knjižnice Grčija Narodna knjižnica Grčije (P3348) 3.867 0 0 1
NLI Narodne knjižnice Izrael NLI (Izrael) (P949) 0 0 0 0
NLK Narodne knjižnice Koreja oznaka Nacionalne knjižnice Koreje (P5034) 3.341 0 0 162
NLP Narodne knjižnice Poljska NLP ID (old) (P1695) 0 0 0 41
NLR Narodne knjižnice Romunija BNR (Romunija) (P1003) 108 0 0 1
NSK Narodne knjižnice Hrvaška NSK (P1375) 5.780 0 0 1
NTA Narodne knjižnice Nizozemska NTA (P1006) 11.614 0 0 1
ORCID Splošno ORCID ORCID (P496) 399 0 0 1
PIC Inštituti za umetnostno raziskovanje Photographers' Identities Photographers’ Identities Catalog (P2750) 283 0 0 1
PLWABN Narodne knjižnice Poljska oznaka PLWABN (P7293) 11.516 0 0 1
Publons Znanstvene podatkovne baze Publons (researchers) Publons author ID (P3829) 27 0 0 1
RID Znanstvene podatkovne baze ResearcherID oznaka ResearcherID (P1053) 51 0 0 1
RISM Drugo RISM (Francija) RISM ID (P5504) 1.493 0 0 1
RERO Drugo RERO (Švica) RERO ID (legacy) (P3065) 6.756 0 0 1
RKDartists Inštituti za umetnostno raziskovanje RKD Artists (Nizozemska) oznaka RKDartists (P650) 1.311 0 0 1
RKDID Inštituti za umetnostno raziskovanje RKD ID (Nizozemska) oznaka RKDimages (P350) 222 0 0 1
RSL Narodne knjižnice Rusija RSL (P947) 399 0 0 1
SELIBR Narodne knjižnice Švedska SELIBR (P906) 5.416 0 0 1
SIKART Inštituti za umetnostno raziskovanje SIKART (Švica) SIKART person ID (P781) 31 0 0 1
SNAC-ID Drugo Social Networks and Archival Context SNAC ARK ID (P3430) 6.861 0 0 1
SUDOC Drugo SUDOC (Francija) oznaka IdRef (P269) 19.926 0 0 1
S2AuthorId Znanstvene podatkovne baze Semantic Scholar oznaka avtorja Semantic Scholar (P4012) 0 0 0 0
TA98 Znanstvene podatkovne baze Terminologia Anatomica oznaka TA98 (P1323) 345 0 0 1
TDVİA Drugo Encyclopedia of Islam TDV Encyclopedia of Islam ID (P7314) 961 0 0 1
TePapa Umetnostne galerije in muzeji Te Papa (Nova Zelandija) Te Papa agent ID (P3544) 636 0 0 1
TLS Drugo Theaterlexikon (Švica) Theaterlexikon der Schweiz ID (P1362) 26 0 0 1
Trove Drugo Trove (Avstralija) NLA Trove (P1315) 6.306 0 0 1
UKPARL Drugo UK Parliament UK Parliament ID (P6213) 296 0 0 1
ULAN Inštituti za umetnostno raziskovanje Artist Names (Getty) ULAN (P245) 2.622 0 0 1
USCongress Drugo US Congress US Congress Bio ID (P1157) 137 0 0 1
VcBA Narodne knjižnice Vatikan identifikator Vatikanske knjižnice VcBA (P8034) 6.423 0 0 1
VIAF Splošno VIAF VIAF (P214) 47.472 0 0 1
WORLDCATID Splošno WorldCat (P7859) 0 0 0 1
CONOR.SI Splošno CONOR (Slovenija) CONOR.SI (P1280) 17.090 0 0 0
SICRIS Znanstvene podatkovne baze SICRIS (Slovenija) šifra raziskovalca (SICRIS) (P6556) 2.119 0 0 0
SBI Biografski slovarji SBI (Slovenija) Slovenska biografija (P1254) 4.878 0 0 0
OSP Biografski slovarji OSP (Slovenija) Obrazi slovenskih pokrajin (P9163) 3.223 0 0 0
SIGIC Drugo SIGIC (Slovenija) SIGIC (avtor) (P2164) 527 0 0 0
Splošno WorldCat (via Library of Congress) 257
Splošno WorldCat (via VIAF) 47.472

Dodatne sledilne kategorije

Ta modul polni sledeče skrite sledilne kategorije:

Število identifikatorjev

Glej tudi

require('Modul:No globals')

local p = {}
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = (string.sub(title.subpageText,1,9) == 'testniprimeri')

--[[==========================================================================]]
--[[                            Category functions                            ]]
--[[==========================================================================]]

function p.getCatForId( id )
	local catName = ''
	if namespace == 0 then
		catName = 'Wikipedijini članki z identifikatorji '..id..''
	elseif namespace == 2 and not title.isSubpage then
		catName = 'Uporabniške strani z identifikatorji '..id..''
	else
		catName = 'Razne strani z identifikatorji '..id..''
	end
	return '[[Kategorija:'..catName..']]'..p.redCatLink(catName)
end

function p.redCatLink( catName ) --catName == 'Blah' (not 'Kategorija:Blah', not '[[Kategorija:Blah]]')
	if catName and catName ~= '' and
	   testcases == false and
	   mw.title.new(catName, 14).exists == false
	then
		return '[[Kategorija:Strani z rdeče-povezanimi kategorijami normativne kontrole]]'
	end
	return ''
end

function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix)
	local catName = 'Wikipedijini članki z okvarjenimi identifikatorji '..(specialCat or id)..''
	if links then -- all links[] use withUid = false; no check needed
		local row = ''
		if prefix then 
			row = row .. '*' .. prefix
		end
		for i, l in ipairs( links ) do
			if i == 1 and not prefix then row = row..'*'
			else           row = row..'\n**' end
			if l then
				row = row..'<span class="uid">'..l..'</span>'
			else
				row = row..'<span class="error">'..id..' id '..rawValues[i]..' ni veljaven.</span>[[Kategorija:'..catName..']]'..p.redCatLink(catName)
			end
		end
		return row..'\n'
	elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed
		if withUid then
			return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n'
		end
		return '*<span class="nowrap">'..link..'</span>\n'
	end
	
	return '* <span class="error">'..id..' id '..rawValues..' ni veljaven.</span>[[Kategorija:'..catName..']]'..p.redCatLink(catName)..'\n'
end

--[[==========================================================================]]
--[[                      Property formatting functions                       ]]
--[[==========================================================================]]

-- If a link has a suitable entry in the global inter-wiki prefix table at [[:m:Interwiki_map]], please consider routing through this prefix rather than as external link URL. This will ease future maintenance as necessary updates to the link can be centrally carried out there rather than by updating this module. The "external link" icon would disappear for such entries.

function p.aagLink( id, label)
	--P3372's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..(label or 'Auckland')..']'..p.getCatForId( 'AAG' )
end

function p.acmLink( id, label )
	--P864's format regex: \d{11} (e.g. 12345678901)
	if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://dl.acm.org/profile/'..id..' '..(label or 'Association for Computing Machinery')..']'..p.getCatForId( 'ACM-DL' )
end

function p.adbLink( id, label )
	--P1907's format regex: [a-z][-a-z]+-([1-3]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71)
	if not id:match( '^[a-z][-a-z]+-[1-3]%d%d?%d?%d?$' ) and
	   not id:match( '^[a-z][-a-z]+-[1-9]%d?%d?%d?$' ) then
		return false
	end
	return '[http://adb.anu.edu.au/biography/'..id..' '..(label or 'Avstralija')..']'..p.getCatForId( 'ADB' )
end

function p.agsaLink( id, label )
	--P6804's format regex: [1-9]\d* (e.g. 3625)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.agsa.sa.gov.au/collection-publications/collection/creators/_/'..id..'/ '..(label or 'Južna Avstralija')..']'..p.getCatForId( 'AGSA' )
end

function p.autoresuyLink( id, label )
	--P2558's format regex: [1-9]\d{0,4} (e.g. 12345)
	if not id:match( '^[1-9]%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://autores.uy/autor/'..id..' '..(label or 'Uruguay')..']'..p.getCatForId( 'autores.uy' )
end

function p.awrLink( id, label )
	--P4186's format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b)
	if not id:match( '^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$' ) and
	   not id:match( '^[A-Z][A-Z]%d%d%d%d%d[a-z]$' ) then
		return false
	end
	return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..(label or 'Australian Women\'s Register')..']'..p.getCatForId( 'AWR' )
end

function p.bibsysLink( id, label )
	--P1015's format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123)
	--TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) and
	   not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..(label or 'Norveška')..']'..p.getCatForId( 'BIBSYS' )
end

function p.bildLink( id, label )
	--P2092's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.bildindex.de/document/obj'..id..' '..(label or 'Bildindex (Nemčija)')..']'..p.getCatForId( 'Bildindex' )
end

function p.bncLink( id, label )
	--P1890's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://www.bncatalogo.cl/F?func=direct&local_base=red10&doc_number='..id..' '..(label or 'Čile')..']'..p.getCatForId( 'BNC' )
end

function p.bneLink( id, label )
	--P950's format regex: (XX|FF|a)\d{4,7}|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d{10} (e.g. XX1234567)
	if not id:match( '^[XF][XF]%d%d%d%d%d?%d?%d?$' ) and
	   not id:match( '^a%d%d%d%d%d?%d?%d?$' ) and
	   not id:match( '^bi[mcsv][aoei]%d%d%d%d%d%d%d%d%d%d$' ) and
	   not id:match( '^Mi[sm][eoa]%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id='..id..' '..(label or 'Španija')..']'..p.getCatForId( 'BNE' ) --no https as of 9/2019
end

function p.bnfLink( id, label )
	--P268's format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789)
	if not id:match( '^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$' ) then
		return false
	end
	--Add cb prefix if it has been removed
	if not id:match( '^cb.+$' ) then
		id = 'cb'..id
	end
	return '[https://catalogue.bnf.fr/ark:/12148/'..id..' ' .. (label or 'Francija')..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' )
end

function p.botanistLink( id, label )
	--P428's format regex: ('t )?(d')?(de )?(la )?(van (der )?)?(Ma?c)?(De)?(Di)?\p{Lu}?C?['\p{Ll}]*([-'. ]*(van )?(y )?(d[ae][nr]?[- ])?(Ma?c)?[\p{Lu}bht]?C?['\p{Ll}]*)*\.? ?f?\.? (e.g. L.)
	--not easily/meaningfully implementable in Lua's regex since "(this)?" is not allowed...
	if not mw.ustring.match( id, "^[%u%l%d%. '-]+$" ) then --better than nothing
		return false
	end
	id = id:gsub(' +', '%%20')
	return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id..' '..(label or 'International Plant Names Index')..']'..p.getCatForId( 'Botanist' )
end

function p.bpnLink( id, label )
	--P651's format regex: \d{6,8} (e.g. 00123456)
	if not id:match( '^%d%d%d%d%d%d%d%d$' ) and --original format regex, changed 8/2019 to
	   not id:match( '^0?%d%d%d%d%d%d%d$' ) and --allow 1-2 leading 0s, allowed by the website
	   not id:match( '^0?0?%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://www.biografischportaal.nl/en/persoon/'..id..' '..(label or 'Nizozemska')..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019
end

function p.canticLink( id, label )
	--P1273's format regex: a\d{7}[0-9x] (e.g. a10640745)
	if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then
		return false
	end
	return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..(label or 'Katalonija')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019
end

function p.ciniiLink( id, label )
	--P271's format regex: DA\d{7}[\dX] (e.g. DA12345678)
	if not id:match( '^DA%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[https://ci.nii.ac.jp/author/'..id..'?l=en '..(label or 'CiNii (Japonska)')..']'..p.getCatForId( 'CINII' )
end

function p.cwgcLink( id, label )
	--P1908's format regex: [1-9]\d* (e.g. 75228351)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.cwgc.org/find-war-dead/casualty/'..id..'/ '..(label or 'Commonwealth War Graves Commission')..']'..p.getCatForId( 'CWGC' )
end

function p.daaoLink( id, label )
	--P1707's format regex: [a-z\-]+\d* (e.g. rolf-harris)
	if not id:match( '^[a-z%-]+%d*$' ) then
		return false
	end
	return '[https://www.daao.org.au/bio/'..id..' '..(label or 'Australian Artists')..']'..p.getCatForId( 'DAAO' )
end

function p.dblpLink( id, label )
	--P2456's format regex: \d{2,3} /\d+(-\d+)?|[a-z] /[a-zA-Z][0-9A-Za-z]*(-\d+)? (e.g. 123/123)
	if not id:match( '^%d%d%d?/%d+$' ) and
	   not id:match( '^%d%d%d?/%d+%-%d+$' ) and
	   not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*$' ) and
	   not id:match( '^[a-z]/[a-zA-Z][0-9A-Za-z]*%-%d+$' ) then
		return false
	end
	return '[https://dblp.org/pid/'..id..' '..(label or 'DBLP (computer science)')..']'..p.getCatForId( 'DBLP' )
end

function p.dibLink( id, label )
	--P6829's format regex: a\d{4}\d?(-[A-D])? (e.g. a1953)
	if not id:match( '^a%d%d%d%d%d?%-?[A-D]?$' ) then
		return false
	end
	return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'Irska')..']'..p.getCatForId( 'DIB' )
end

function p.dsiLink( id, label )
	--P2349's format regex: [1-9]\d* (e.g. 1538)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[http://www.uni-stuttgart.de/hi/gnt/dsi2/index.php?table_name=dsi&function=details&where_field=id&where_value='..id..' '..(label or 'Scientific illustrators')..']'..p.getCatForId( 'DSI' )
end

function p.fastLink( id, label )
	--P2163's format regex: [1-9]\d{0,7} (e.g. 1916996)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[http://id.worldcat.org/fast/'..id..'/ '..(label or 'Faceted Application of Subject Terminology')..']'..p.getCatForId( 'FAST' )
end


function p.fnzaLink( id, label )
	--P6792's format regex: [1-9]\d* (e.g. 9785)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://findnzartists.org.nz/artist/'..id..'/ '..(label or 'New Zealand Artists')..']'..p.getCatForId( 'FNZA' )
end

function p.gndLink( id, label )
	--P227's format regex: 1[012]?\d{7}[0-9X]|[47]\d{6}-\d|[1-9]\d{0,7}-[0-9X]|3\d{7}[0-9X] (e.g. 4079154-3)
	if not id:match( '^1[012]?%d%d%d%d%d%d%d[0-9X]$' ) and
	   not id:match( '^[47]%d%d%d%d%d%d%-%d$' ) and
	   not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%-[0-9X]$' ) and
	   not id:match( '^3%d%d%d%d%d%d%d[0-9X]$' ) then
		return false
	end
	return '[https://d-nb.info/gnd/'..id..' '..(label or 'Integrated Authority File (Nemčija)')..']'..p.getCatForId( 'GND' )
end

function p.hdsLink( id, label )
	--P902's format regex: \d{6} (e.g. 050123)
	if not id:match( '^%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://hls-dhs-dss.ch/fr/articles/'..id..' '..(label or 'Zgodovinski leksikon Švice')..']'..p.getCatForId( 'HDS' )
end

function p.iaafLink( id, label )
	--P1146's format regex: [0-9][0-9]* (e.g. 012)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.iaaf.org/athletes/_/'..id..' '..(label or 'World Athletics')..']'..p.getCatForId( 'IAAF' )
end


function p.iccuLink( id, label )
	--P396's format regex: IT\\ICCU\\(\d{10}|\D\D[\D\d]\D\\\d{6}) (e.g. IT\ICCU\CFIV\000163)
	if not id:match( '^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$' ) and
	   not id:match( '^IT\\ICCU\\%u%u[%u%d]%u\\%d%d%d%d%d%d$' ) then --legacy: %u used here instead of %D (but the faulty ID cat is empty, out of ~12k uses)
		return false
	end
	return '[https://opac.sbn.it/opacsbn/opac/iccu/scheda_authority.jsp?bid='..id..' '..(label or 'Italija')..']'..p.getCatForId( 'ICCU' )
end
function p.iciaLink( id, label )
	--P1736's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..(label or 'ICIA (Izrael)')..']'..p.getCatForId( 'ICIA' )
end

function p.ieuLink( id, label )
	--P9070's format regex: [A-Z]\\[A-Z]\\[A-Za-z0-9]+ (e.g. K\Y\Kyiv)
	if not id:match( '^[A-Z]\\[A-Z]\\%w+$' ) then
		return false
	end
	return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..(label or 'Internet Encyclopedia of Ukraine')..']'..p.getCatForId( 'IEU' )
end

function p.isniLink( id, label )
	id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145
	if not id then
		return false
	end
	return '[https://isni.org/isni/'..id..' '..(label or 'ISNI')..']'..p.getCatForId( 'ISNI' )
end

function p.jocondeLink( id, label )
	--P347's format regex: [\-0-9A-Za-z]{11} (e.g. 12345678901)
	local regex = '^'..string.rep('[%-0-9A-Za-z]', 11)..'$'
	if not id:match( regex ) then
		return false
	end
	return '[https://www.pop.culture.gouv.fr/notice/joconde/'..id..' '..(label or 'Joconde (Francija)')..']'..p.getCatForId( 'Joconde' )
end

function p.kulturnavLink( id, label )
	--P1248's format regex: [0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[http://kulturnav.org/'..id..' '..(label or 'KulturNav (Norveška)')..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019
end

function p.lccnLink( id, label )
	local parts = p.splitLccn( id ) --e.g. n78039510
	if not parts then
		return false
	end
	local lccnType = parts[1] ~= 'sh' and 'names' or 'subjects'
	id = parts[1] .. parts[2] .. p.append( parts[3], '0', 6 )
	return '[https://id.loc.gov/authorities/'..lccnType..'/'..id..' '..(label or 'ZDA')..']'..p.getCatForId( 'LCCN' )
end

function p.lirLink( id, label )
	--P886's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[http://www.e-lir.ch/e-LIR___Lexicon.'..id..'.450.0.html '..(label or 'Lexicon Istoric Retic (Švica)')..']'..p.getCatForId( 'LIR' ) --no https as of 9/2019
end

function p.lnbLink( id, label )
	--P1368's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://kopkatalogs.lv/F?func=direct&local_base=lnc10&doc_number='..id..'&P_CON_LNG=ENG '..(label or 'Latvija')..']'..p.getCatForId( 'LNB' )
end

function p.leonoreLink( id, label )
	--P640's format regex: LH/\d{1,4}/\d{1,3}|19800035/\d{1,4}/\d{1,5}(Bis)?|C/0/\d{1,2} (e.g. LH/2064/18)
	if not id:match( '^LH/%d%d?%d?%d?/%d%d?%d?$' ) and             --IDs from       LH/1/1 to         LH/2794/54 (legionaries)
	   not id:match( '^19800035/%d%d?%d?%d?/%d%d?%d?%d?%d?$' ) and --IDs from 19800035/1/1 to 19800035/385/51670 (legionnaires who died 1954-1977 & some who died < 1954)
	   not id:match( '^C/0/%d%d?$' ) then                          --IDs from        C/0/1 to             C/0/84 (84 famous legionaries)
		return false
	end
	return '[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&FIELD_1=COTE&VALUE_1='..id..' '..(label or 'Léonore (Francija)')..']'..p.getCatForId( 'Léonore' ) --no https as of 9/2019
end

function p.maLink( id, label )
	--P6366's format regex: [1-9]\d{3,9} (e.g. 1498221862)
	if not id:match( '^[1-9]%d%d%d%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://academic.microsoft.com/v2/detail/'..id..' '..(label or 'Microsoft Academic')..']'..p.getCatForId( 'MA' )
end

function p.mbaLink( id, label )
	--P434's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/artist/'..id
	local cat = p.getCatForId( 'MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBA (identifikator)|MusicBrainz]] [' .. url .. ' artist]' .. cat
	end
end

function p.mbareaLink( id, label )
	--P982's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/area/'..id
	local cat = p.getCatForId( 'MusicBrainz area' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBAREA (identifikator)|MusicBrainz]] [' .. url .. ' area]' .. cat
	end
end

function p.mbiLink( id, label )
	--P1330's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/instrument/'..id
	local cat = p.getCatForId( 'MusicBrainz instrument' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBI (identifikator)|MusicBrainz]] [' .. url .. ' instrument]' .. cat
	end
end

function p.mblLink( id, label )
	--P966's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/label/'..id
	local cat = p.getCatForId( 'MusicBrainz label' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBL (identifikator)|MusicBrainz]] [' .. url .. ' label]' .. cat
	end
end

function p.mbpLink( id, label )
	--P1004's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/place/'..id
	local cat = p.getCatForId( 'MusicBrainz place' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBP (identifikator)|MusicBrainz]] [' .. url .. ' place]' .. cat
	end
end

function p.mbrgLink( id, label )
	--P436's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/release-group/'..id
	local cat = p.getCatForId( 'MusicBrainz release group' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBRG (identifikator)|MusicBrainz]] [' .. url .. ' release group]' .. cat
	end
end

function p.mbsLink( id, label )
	--P1407's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	local url = 'https://musicbrainz.org/series/'..id
	local cat = p.getCatForId( 'MusicBrainz series' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBS (identifikator)|MusicBrainz]] [' .. url .. ' series]' .. cat
	end
end

function p.mbwLink( id, label )
	--P435's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	
	local url = 'https://musicbrainz.org/work/'..id
	local cat = p.getCatForId( 'MusicBrainz work' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBW (identifikator)|MusicBrainz]] [' .. url .. ' work]' .. cat
	end
end

function p.mgpLink( id, label )
	--P549's format regex: \d{1,6} (e.g. 123456)
	if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://genealogy.math.ndsu.nodak.edu/id.php?id='..id..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' )
end

function p.naraLink( id, label )
	--P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://catalog.archives.gov/id/'..id..' '..(label or 'National Archives (ZDA)')..']'..p.getCatForId( 'NARA' )
end

function p.nclLink( id, label )
	--P1048's format regex: \d+ (e.g. 1081436)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence='..id..'&CON_LNG=ENG '..(label or 'Tajvan')..']'..p.getCatForId( 'NCL' ) --no https as of 9/2019
end

function p.ndlLink( id, label )
	--P349's format regex: 0?\d{8} (e.g. 012345678)
	if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..(label or 'Japonska')..']'..p.getCatForId( 'NDL' )
end

function p.ngvLink( id, label )
	--P2041's format regex: \d+ (e.g. 12354)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.ngv.vic.gov.au/explore/collection/artist/'..id..'/ '..(label or 'Viktorija')..']'..p.getCatForId( 'NGV' )
end

function p.nkcLink( id, label )
	--P691's format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234)
	if not id:match( '^[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..'&CON_LNG=ENG '..(label or 'Češka republika')..']'..p.getCatForId( 'NKC' )
end

function p.nlaLink( id, label )
	--P409's format regex: [1-9][0-9]{0,11} (e.g. 123456789012)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://nla.gov.au/anbd.aut-an'..id..' '..(label or 'Avstralija')..']'..p.getCatForId( 'NLA' )
end

function p.nlgLink( id, label )
	--P3348's format regex: [1-9]\d* (e.g. 1)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://data.nlg.gr/resource/authority/record'..id..' '..(label or 'Grčija')..']'..p.getCatForId( 'NLG' )
end

function p.nliLink( id, label )
	--P949's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://uli.nli.org.il/F/?func=direct&doc_number='..id..'&local_base=nlx10'..' '..(label or 'Izrael')..']'..p.getCatForId( 'NLI' )
end

function p.nlkLink( id, label )
	--P5034's format regex: KA.(19|20).{7} (e.g. KAC201501465)
	if not id:match( '^KA.19.......$' ) and
	   not id:match( '^KA.20.......$' ) then
		return false
	end
	return '[https://nl.go.kr/authorities/resource/'..id..' '..(label or 'Koreja')..']'..p.getCatForId( 'NLK' )
end

function p.nlpLink( id, label )
	--P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836)
	if not id:match( '^9810%d+$' ) and
	   not id:match( '^A%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..(label or 'Poljska')..']'..p.getCatForId( 'NLP' )
end

function p.nlrLink( id, label )
	--P1003's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://aleph.bibnat.ro:8991/F/?func=direct&local_base=NLR10&doc_number='..id..' '..(label or 'Romunija')..']'..p.getCatForId( 'NLR' )
end

function p.nskLink( id, label )
	--P1375's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://katalog.nsk.hr/F/?func=direct&doc_number='..id..'&local_base=nsk10 '..(label or 'Hrvaška')..']'..p.getCatForId( 'NSK' ) --no https as of 9/2019
end

function p.ntaLink( id, label )
	--P1006's format regex: \d{8}[\dX] (e.g. 12345678X)
	if not id:match( '^%d%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[http://data.bibliotheken.nl/id/thes/p'..id..' '..(label or 'Nizozemska')..']'..p.getCatForId( 'NTA' )
end

function p.orcidLink( id, label )
	id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483
	if not id then
		return false
	end
	id = id:sub( 1, 4 )..'-'..id:sub( 5, 8 )..'-'..id:sub( 9, 12 )..'-'..id:sub( 13, 16 )
	return '[https://orcid.org/'..id..' '..(label or 'ORCID')..']'..p.getCatForId( 'ORCID' )
end

function p.picLink( id, label )
	--P2750's format regex: [1-9]\d* (e.g. 1)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://pic.nypl.org/constituents/'..id..' '..(label or 'Photographers\' Identities')..']'..p.getCatForId( 'PIC' )
end

function p.plwabnLink( id, label )
	--P7293's format regex: 981[0-9]{8}05606 (e.g. 9810696457305606)
	if not id:match( '^981%d%d%d%d%d%d%d%d05606*$' ) then
		return false
	end
	return '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..(label or 'Poljska')..']'..p.getCatForId( 'PLWABN' )
end

function p.publonsLink( id, label )
	--P3829's format regex: \d+ (e.g. 654601)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://publons.com/author/'..id..'/ '..(label or 'Publons (researchers)')..']'..p.getCatForId( 'Publons' )
end

function p.ridLink( id, label )
	--P1053's format regex: [A-Z]{1,3}-\d{4}-(19|20)\d\d (e.g. AAS-5150-2020)
	if not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d$' ) and
	   not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20%d%d$' ) then
		return false
	end
	return '[https://www.researcherid.com/rid/'..id..' '..(label or 'ResearcherID')..']'..p.getCatForId( 'RID' )
end

function p.rismLink( id, label )
	--P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410)
	if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe'
	   not id:match( '^ks[1-9]%d*$' ) and
	   not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://opac.rism.info/search?id='..id..' '..(label or 'RISM (Francija)')..']'..p.getCatForId( 'RISM' )
end

function p.reroLink( id, label )
	--P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678)
	if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then
		return false
	end
	return '[http://data.rero.ch/'..id..' '..(label or 'RERO (Švica)')..']'..p.getCatForId( 'RERO' )
end

function p.rkdartistsLink( id, label )
	--P650's format regex: [1-9]\d{0,5} (e.g. 123456)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://rkd.nl/en/explore/artists/'..id..' '..(label or 'RKD Artists (Nizozemska)')..']'..p.getCatForId( 'RKDartists' )
end

function p.rkdidLink( id, label )
	--P350's format regex: [1-9]\d{0,5} (e.g. 123456)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://rkd.nl/nl/explore/images/'..id..' '..(label or 'RKD ID (Nizozemska)')..']'..p.getCatForId( 'RKDID' )
end

function p.rslLink( id, label )
	--P947's format regex: \d{1,9} (e.g. 123456789)
	if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request='..id..'&CON_LNG=ENG '..(label or 'Rusija')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019
end

function p.selibrLink( id, label )
	--P906's format regex: [1-9]\d{4,5} (e.g. 123456)
	if not id:match( '^[1-9]%d%d%d%d%d?$' ) then
		return false
	end
	return '[https://libris.kb.se/auth/'..id..' '..(label or 'Švedska')..']'..p.getCatForId( 'SELIBR' )
end

function p.sikartLink( id, label )
	--P781's format regex: \d{7,9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[http://www.sikart.ch/KuenstlerInnen.aspx?id='..id..'&lng=en '..(label or 'SIKART (Švica)')..']'..p.getCatForId( 'SIKART' ) --no https as of 9/2019
end

function p.snacLink( id, label )
	--P3430's format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A)
	if not id:match( '^%d*[A-Za-z][0-9A-Za-z]*$' ) then
		return false
	end
	return '[https://snaccooperative.org/ark:/99166/'..id..' '..(label or 'Social Networks and Archival Context')..']'..p.getCatForId( 'SNAC-ID' )
end

function p.sudocLink( id, label )
	--P269's format regex: (\d{8}[\dX]|) (e.g. 026927608)
	if not id:match( '^%d%d%d%d%d%d%d%d[%dxX]$' ) then --legacy: allow lowercase 'x'
		return false
	end
	return '[https://www.idref.fr/'..id..' '..(label or 'SUDOC (Francija)')..']'..p.getCatForId( 'SUDOC' )
end

function p.s2authoridLink( id, label )
	--P4012's format regex: [1-9]\d* (e.g. 1796130)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.semanticscholar.org/author/'..id..' '..(label or 'Semantic Scholar')..']'..p.getCatForId( 'Semantic Scholar author' ) --special cat name
end

function p.ta98Link( id, label )
	--P1323's format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678)
	if not id:match( '^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$' ) then
		return false
	end
	return '[http://tools.wmflabs.org/wikidata-externalid-url/?p=1323&url_prefix=https:%2F%2Fwww.unifr.ch%2Fifaa%2FPublic%2FEntryPage%2FTA98%20Tree%2FEntity%20TA98%20EN%2F&url_suffix=%20Entity%20TA98%20EN.htm&id='..id..' '..(label or 'Terminologia Anatomica')..']'..p.getCatForId( 'TA98' )
end

function p.tdviaLink( id, label )
	--P7314's format regex: [a-z/-]+] (e.g. barkan-omer-lutfi)
	if not id:match( '^[a-z/-]+$' ) then
		return false
	end
	return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'Encyclopedia of Islam')..']'..p.getCatForId( 'TDVİA' )
end


function p.tepapaLink( id, label )
	--P3544's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://collections.tepapa.govt.nz/agent/'..id..' '..(label or 'Te Papa (Nova Zelandija)')..']'..p.getCatForId( 'TePapa' )
end

function p.tlsLink( id, label )
	id = id:gsub(' +', '_')
	--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*/–]{3,59} (e.g. Abcd)
	local class = "[%a%d_',%.%-%(%)%*/–]"
	local regex = "^%u"..string.rep(class, 3)..string.rep(class.."?", 56).."$"
	if not mw.ustring.match( id, regex ) then
		return false
	end
	return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Švica)')..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019
end

function p.troveLink( id, label )
	--P1315's format regex: [1-9]\d{5,7} (e.g. 12345678)
	if not id:match( '^[1-9]%d%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[https://trove.nla.gov.au/people/'..id..' '..(label or 'Trove (Avstralija)')..']'..p.getCatForId( 'Trove' )
end

function p.ukparlLink( id, label )
	--P6213's format regex: [a-zA-Z\d]{8} (e.g. AQUupyiR)
	if not id:match( '^[a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d]$' ) then
		return false
	end
	return '[https://id.parliament.uk/'..id..' '..(label or 'UK Parliament')..']'..p.getCatForId( 'UKPARL' )
end

function p.ulanLink( id, label )
	--P245's format regex: 500\d{6} (e.g. 500123456)
	if not id:match( '^500%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid='..id..' '..(label or 'Artist Names (Getty)')..']'..p.getCatForId( 'ULAN' )
end

function p.uscongressLink( id, label )
	--P1157's format regex: [A-Z]00[01]\d{3} (e.g. A000123)
	if not id:match( '^[A-Z]00[01]%d%d%d$' ) then
		return false
	end
	return '[http://bioguide.congress.gov/scripts/biodisplay.pl?index='..id..' '..(label or 'US Congress')..']'..p.getCatForId( 'USCongress' ) --no https as of 9/2019
end

function p.vcbaLink( id, label )
	--P8034's format regex: \d{3}\/[1-9]\d{0,5} (e.g. 494/9793)
	if not id:match( '^%d%d%d\/[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	id = id:gsub('\/', '_')
	return '[https://opac.vatlib.it/auth/detail/'..id..' '..(label or 'Vatikan')..']'..p.getCatForId( 'VcBA' )
end

function p.viafLink( id, label )
	--P214's format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012)
	if not id:match( '^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$' ) and
	   not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d?%d?%d?$' ) then
		return false
	end
	-- If the "VIAF" entry at [[:m:Interwiki map]] would resolve to "https://viaf.org/viaf/$1" (rather than "http://viaf.org/viaf/$1", as it currently still does), the code below could change from '[https://viaf.org/viaf/'..id..' '..id..']' to '[[:VIAF:'..id..'|'..id..']]'.
	return '[https://viaf.org/viaf/'..id..' '..(label or 'VIAF')..']'..p.getCatForId( 'VIAF' )
end

function p.conorLink( id, label )
    if not id:match( '^%d+$' ) then
        return false
    end
    return '[https://plus.cobiss.si/opac7/conor/'..id..' '..(label or 'CONOR (Slovenija)')..']'..p.getCatForId( 'CONOR.SI' )
end

function p.sicrisLink( id, label )
	-- 	P6556 format: [0-9]{4}[1-9]
    if not id:match( '^%d+$' ) then
        return false
    end
    return '[https://www.sicris.si/public/jqm/search_basic.aspx?lang=slv&opt=2&subopt=1&opdescr=search&code1=rsr&code2=auto&search_term='..id..' '..(label or 'SICRIS (Slovenija)')..']'..p.getCatForId( 'SICRIS' )
end

function p.OSPLink( id, label )
    return '[https://www.obrazislovenskihpokrajin.si/oseba/'..id..' '..(label or 'OSP (Slovenija)')..']'..p.getCatForId( 'OSP' )
end

function p.SIGICLink( id, label )
	if not id:match( '^%d+$' ) then
		return false
    end
    return '[http://sigic.nuk.uni-lj.si/?mod=search&action=avtor&id='..id..' '..(label or 'SIGIC (Slovenija)')..']'..p.getCatForId( 'SIGIC' )
end

function p.sbiLink( id, label )
	if not id:match( '^%d+$' ) then
		return false
    end
    return '[http://www.slovenska-biografija.si/oseba/sbi'..id..' '..(label or 'SBI (Slovenija)')..']'..p.getCatForId( 'SBI' )
end

--[[=========================== Helper functions =============================]]

function p.append(str, c, length)
	while str:len() < length do
		str = c .. str
	end
	return str
end

--Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145
function p.getIsniCheckDigit( isni )
	local total = 0
	for i = 1, 15 do
		local digit = isni:byte( i ) - 48 --Get integer value
		total = (total + digit) * 2
	end
	local remainder = total % 11
	local result = (12 - remainder) % 11
	if result == 10 then
		return "X"
	end
	return tostring( result )
end

--Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it's invalid
--See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
function p.validateIsni( id )
	--P213 (ISNI) format regex: [0-9]{4} [0-9]{4} [0-9]{4} [0-9]{3}[0-9X] (e.g. 0000-0000-6653-4145)
	--P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d{3}-\d{3}[\dX] (e.g. 0000-0002-7398-5483)
	id = id:gsub( '[ %-]', '' ):upper()
	if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	if p.getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then
		return false
	end
	return id
end

function p.splitLccn( id )
	--P244's format regex: (n|nb|nr|no|ns|sh)([4-9][0-9]|00|20[0-1][0-9])[0-9]{6} (e.g. n78039510)
	if id:match( '^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$' ) then
		id = id:gsub( '^(%l+)(%d+)(%d%d%d%d%d%d)$', '%1/%2/%3' )
	end
	if id:match( '^%l%l?%l?/%d%d%d?%d?/%d+$' ) then
		return mw.text.split( id, '/' )
	end
	return false
end

--[[==========================================================================]]
--[[                    Wikidata & documentation functions                    ]]
--[[==========================================================================]]

function p.getIdsFromWikidata( itemId, property )
	local ids = {}
	local statements = mw.wikibase.getBestStatements( itemId, property )
	if statements then
		for _, statement in ipairs( statements ) do
			if statement.mainsnak.datavalue then
				table.insert( ids, statement.mainsnak.datavalue.value )
			end
		end
	end
	return ids
end

-- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentation
function p.docConfTable( frame )
	local wikiTable = '{| class="wikitable sortable"\n'..
					  '! rowspan=2 | Parameter\n'..
					  '! rowspan=2 | Poglavje\n'..
					  '! rowspan=2 | Se pojavi kot\n'..
					  '! rowspan=2; data-sort-type=number | Wikidata property\n'..
					  '! colspan=4 | Sledilne kategorije in števci strani\n'..
					  '|-\n'..
					  '! [[:Kategorija:Wikipedijini članki s podatki o normativni kontroli|'..       'Članki]]\n'..
					  '! [[:Kategorija:Uporabniške strani s podatki o normativni kontroli|'..               'Uporabniške strani]]\n'..
					  '! [[:Kategorija:Razne strani s podatki o normativni kontroli|'..      'Razne strani]]\n'..
					  '! [[:Kategorija:Wikipedijini članki z napakami v podatkih o normativni kontroli|'..'Napačni IDji]]\n'..
					  '|-\n'
	local lang = mw.getContentLanguage()
	for _, conf in pairs( p.conf ) do
		local param, pid, section = conf[1], conf[2], conf[4]
		local appearsAs
		if param == "WORLDCATID" then
			-- WorldCat is special
			appearsAs = "[https://www.worldcat.org/identities/lccn-n78039510 WorldCat]"
		elseif conf.prefix then
			appearsAs = conf.prefix
		else
			appearsAs = conf[3](conf[5])
		end
		local link = conf.link or param .. ' (identifikator)'
		local category = conf.category or param
		local args = { id = 'f', pid }
		local wpl = frame:expandTemplate{ title = 'P', args = args }
		--cats
		local articleCat = 'Wikipedijini članki z identifikatorji '..category
		local userCat =    'Uporabniške strani z identifikatorji '..category
		local miscCat =    'Razne strani z identifikatorji '..category
		local faultyCat =  'Wikipedijini članki z okvarjenimi identifikatorji '..category
		--counts
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
		local userCount =    lang:formatNum( mw.site.stats.pagesInCategory(userCat, 'pages') )
		local miscCount =    lang:formatNum( mw.site.stats.pagesInCategory(miscCat, 'pages') )
		local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
		
		--concat
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||[['..link..'|'..param..']]'..
					'||'..section..
					'||'..appearsAs..
					'||data-sort-value='..pid..'|'..wpl..
					'||style="text-align: right;"|[[:Kategorija:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|[[:Kategorija:'..   userCat..'|'..   userCount..']]'..
					'||style="text-align: right;"|[[:Kategorija:'..   miscCat..'|'..   miscCount..']]'..
					'||style="text-align: right;"|[[:Kategorija:'.. faultyCat..'|'.. faultyCount..']]'
	end
	
	--append derivative WorldCat cats
	local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' }
	for _, w in pairs(wcd) do
		local articleCat = 'Wikipedijini članki z identifikatorji '..w
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
		local appearsAs 
		if w == "WorldCat-LCCN" then
			appearsAs = "[https://www.worldcat.org/identities/lccn-n79-113947 WorldCat (via Library of Congress)]"
		else
			appearsAs = "[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (via VIAF)]"
		end
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||'..'—'..
					'||Splošno'..
					'||'..appearsAs..
					'||data-sort-value='..w..'|'..'—'..
					'||style="text-align: right;"|[[:Kategorija:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'
	end
	
	return require("Modul:Suppress categories").main(wikiTable)..'\n|}'
end

--[[==========================================================================]]
--[[                              Configuration                               ]]
--[[==========================================================================]]

-- If a specific "(identifier) redirect" exists for an identifier, please route through this particular redirect rather than linking directly to the target page. This reduces clutter in "What links here" and improves reverse lookup of articles where a manifestation of this particular identifier is used.


-- Parameter format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation }
-- Optional named parameters: `link` to override the link in the documentation (defaults to parameter + (identifer)),
-- category to override the ID in category names (defaults to parameter),
-- prefix to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself
p.conf = {
	{ 'AAG', 3372, p.aagLink, "Umetnostne galerije in muzeji", "1"},
	{ 'ACM-DL', 864, p.acmLink, "Znanstvene podatkovne baze", "12345678901", link="ACM DL (identifikator)"},
	{ 'ADB', 1907, p.adbLink,"Biografski slovarji", "barton-sir-edmund-toby-71"},
	{ 'AGSA', 6804, p.agsaLink, "Umetnostne galerije in muzeji", "3625"},
	{ 'autores.uy', 2558, p.autoresuyLink, "Biografski slovarji", "12345"},
	{ 'AWR', 4186, p.awrLink, "Biografski slovarji", "PR00768b"},
	{ 'BIBSYS', 1015, p.bibsysLink, "Narodne knjižnice", "1234567890123"},
	{ 'Bildindex', 2092, p.bildLink, "Inštituti za umetnostno raziskovanje", "1"},
	{ 'BNC', 1890, p.bncLink, "Narodne knjižnice", "123456789"},
	{ 'BNE', 950, p.bneLink, "Narodne knjižnice", "XX1234567"},
	{ 'BNF', 268, p.bnfLink, "Narodne knjižnice", "123456789"},
	{ 'Botanist', 428, p.botanistLink , "Znanstvene podatkovne baze", "L."},
	{ 'BPN', 651, p.bpnLink , "Biografski slovarji", "12345678"},
	{ 'CANTIC', 1273, p.canticLink, "Narodne knjižnice", "a12345678"},
	{ 'CINII', 271, p.ciniiLink, "Znanstvene podatkovne baze", "DA12345678", link = "CiNii (identifikator)"},
	{ 'CWGC', 1908, p.cwgcLink, "Drugo", "1234567"},
	{ 'DAAO', 1707, p.daaoLink, "Inštituti za umetnostno raziskovanje", "rolf-harris"},
	{ 'DBLP', 2456, p.dblpLink, "Znanstvene podatkovne baze", "123/123"},
	{ 'DIB',  6829, p.dibLink, "Biografski slovarji", "a1234"},
	{ 'DSI', 2349, p.dsiLink, "Inštituti za umetnostno raziskovanje", "1538"},
	{ 'FAST', 2163, p.fastLink, "Drugo", "1"},
	{ 'FNZA', 6792, p.fnzaLink, "Inštituti za umetnostno raziskovanje", "12"},
	{ 'GND', 227, p.gndLink, "Splošno", "4079154-3"},
	{ 'HDS', 902, p.hdsLink, "Drugo", "050123"},
	{ 'IAAF', 1146, p.iaafLink, "Drugo", "123"},
	{ 'ICCU', 396, p.iccuLink, "Narodne knjižnice", "IT\\ICCU\\CFIV\\000163"}, --formerly SBN
	{ 'ICIA', 1736, p.iciaLink, "Inštituti za umetnostno raziskovanje", "1"},
	{ 'IEU', 9070, p.ieuLink, "Drugo", "N\\A\\NationalAcademyofArtandArchitecture"},
	{ 'ISNI', 213, p.isniLink, "Splošno", "0000-0000-6653-4145", prefix = '[[ISNI (identifikator)|ISNI]]'},
	{ 'Joconde', 347, p.jocondeLink, "Inštituti za umetnostno raziskovanje", "12345678901"},
	{ 'KULTURNAV', 1248, p.kulturnavLink, "Inštituti za umetnostno raziskovanje", "12345678-1234-1234-1234-1234567890AB", link="KulturNav (identifikator)"},
	{ 'LCCN', 244, p.lccnLink, "Narodne knjižnice", "n78039510"},
	{ 'LIR', 886, p.lirLink, "Drugo", "1"},
	{ 'LNB', 1368, p.lnbLink, "Narodne knjižnice", "123456789"},
	{ 'Léonore', 640, p.leonoreLink, "Drugo", "LH/1/1", prefix = "[[Léonore (identifikator)|Léonore (Francija)]]"},
	{ 'MA', 6366, p.maLink, "Drugo", "123456789"},
	{ 'MBA', 434, p.mbaLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz'}, --special cat name
	{ 'MBAREA', 982, p.mbareaLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz area' }, --special cat name
	{ 'MBI', 1330, p.mbiLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz instrument' }, --special cat name
	{ 'MBL', 966, p.mblLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz label' }, --special cat name
	{ 'MBP', 1004, p.mbpLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz place' }, --special cat name
	{ 'MBRG', 436, p.mbrgLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz release group' }, --special cat name
	{ 'MBS', 1407, p.mbsLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz series' }, --special cat name
	{ 'MBW',  435, p.mbwLink, "Drugo", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz work' }, --special cat name
	{ 'MGP', 549, p.mgpLink, "Znanstvene podatkovne baze", "123456"},
	{ 'NARA', 1225, p.naraLink, "Drugo", "12345678"},
	{ 'NCL', 1048, p.nclLink, "Narodne knjižnice", "1081436"},
	{ 'NDL', 349, p.ndlLink, "Narodne knjižnice", "012345678"},
	{ 'NGV', 2041, p.ngvLink, "Umetnostne galerije in muzeji", "12354"},
	{ 'NKC', 691, p.nkcLink, "Narodne knjižnice", "abcd12345678901234"},
	{ 'NLA', 409, p.nlaLink, "Narodne knjižnice", "123456789012"},
	{ 'NLG', 3348, p.nlgLink, "Narodne knjižnice", "12345678"},
	{ 'NLI', 949, p.nliLink, "Narodne knjižnice", "123456789"},
	{ 'NLK', 5034, p.nlkLink, "Narodne knjižnice", "KAB197000000"},
	{ 'NLP', 1695, p.nlpLink, "Narodne knjižnice", "9810123456789012345"},
	{ 'NLR', 1003, p.nlrLink, "Narodne knjižnice", "123456789"},
	{ 'NSK', 1375, p.nskLink, "Narodne knjižnice", "123456789"},
	{ 'NTA', 1006, p.ntaLink, "Narodne knjižnice", "12345678X"},
	{ 'ORCID', 496, p.orcidLink, "Splošno", "0000-0002-7398-5483", prefix = '[[ORCID (identifikator)|ORCID]]'},
	{ 'PIC', 2750, p.picLink, "Inštituti za umetnostno raziskovanje", "1"},
	{ 'PLWABN',  7293, p.plwabnLink, "Narodne knjižnice", "9812345678905606"},
	{ 'Publons', 3829, p.publonsLink, "Znanstvene podatkovne baze", "2776255"},
	{ 'RID', 1053, p.ridLink, "Znanstvene podatkovne baze", "A-1234-1934"},
	{ 'RISM', 5504, p.rismLink, "Drugo", "pe1",  prefix = '[[RISM (identifikator)|RISM (Francija)]]'},
	{ 'RERO', 3065, p.reroLink, "Drugo", "02-A012345678", prefix = '[[RERO (identifikator)|RERO (Švica)]]'},
	{ 'RKDartists', 650, p.rkdartistsLink, "Inštituti za umetnostno raziskovanje", "123456"},
	{ 'RKDID', 350, p.rkdidLink, "Inštituti za umetnostno raziskovanje", "123456"},
	{ 'RSL', 947, p.rslLink, "Narodne knjižnice", "123456789"},
	{ 'SELIBR', 906, p.selibrLink, "Narodne knjižnice", "123456"},
	{ 'SIKART', 781, p.sikartLink, "Inštituti za umetnostno raziskovanje", '123456789'},
	{ 'SNAC-ID', 3430, p.snacLink, "Drugo", "A"},
	{ 'SUDOC', 269, p.sudocLink, "Drugo", "026927608", prefix = '[[SUDOC (identifikator)|SUDOC (Francija)]]'},
	{ 'S2AuthorId', 4012, p.s2authoridLink, "Znanstvene podatkovne baze", "1796130", category = 'Semantic Scholar author' }, --special cat name
	{ 'TA98', 1323, p.ta98Link, "Znanstvene podatkovne baze", "A12.3.45.678"},
	{ 'TDVİA', 7314, p.tdviaLink, "Drugo", "asim-b-behdele"},
	{ 'TePapa', 3544, p.tepapaLink, "Umetnostne galerije in muzeji", "1"},
	{ 'TLS',  1362, p.tlsLink, "Drugo", "Abcd"},
	{ 'Trove', 1315, p.troveLink, "Drugo", "12345678", prefix = '[[Trove (identifikator)|Trove (Avstralija)]]'}, --formerly NLA-person
	{ 'UKPARL', 6213, p.ukparlLink, "Drugo", "AQUupyiR"},
	{ 'ULAN', 245, p.ulanLink, "Inštituti za umetnostno raziskovanje", "500123456"},
	{ 'USCongress', 1157, p.uscongressLink, "Drugo", "A000123", link = "US Congress (identifikator)"},
	{ 'VcBA', 8034, p.vcbaLink, "Narodne knjižnice", "494/9793"},
	{ 'VIAF', 214, p.viafLink, "Splošno", "123456789", prefix = "[[VIAF (identifikator)|VIAF]]"},
	{ 'WORLDCATID', 7859, nil, "Splošno", nil, link = "WorldCat Identities (identifikator)"},
	{ 'CONOR.SI', 1280, p.conorLink, "Splošno", "123456789", prefix = "[[CONOR (identifikator)|CONOR (Slovenija)]]" },
	{ 'SICRIS', 6556, p.sicrisLink, "Znanstvene podatkovne baze", "12345", prefix = "[[SICRIS (identifikator)|SICRIS (Slovenija)]]" },
	{ 'SBI', 1254, p.sbiLink, "Biografski slovarji", "123456789", prefix = "[[SBI (identifikator)|SBI (Slovenija)]]"},
	{ 'OSP', 9163, p.OSPLink, "Biografski slovarji", "123456789", prefix = "[[OSP (identifikator)|OSP (Slovenija)]]"},
	{ 'SIGIC', 2164, p.SIGICLink, "Drugo", "123456789", prefix = "[[SIGIC (identifikator)|SIGIC (Slovenija)]]"},
}

-- Legitimate aliases to p.conf, for convenience
-- Format: { 'alias', 'parameter name in p.conf' }
p.aliases = {
	{ 'DNB', 'GND' }, --Deutsche Nationalbibliothek -> Gemeinsame Normdatei
	{ 'Leonore', 'Léonore' }, --alias name without diacritics
	{ 'leonore', 'Léonore' }, --lowercase variant without diacritics
	{ 'MusicBrainz', 'MBA' },
	{ 'MusicBrainz artist', 'MBA' },
	{ 'MusicBrainz label', 'MBL' },
	{ 'MusicBrainz release group', 'MBRG' },
	{ 'MusicBrainz work', 'MBW' },
	{ 'SBN', 'ICCU' }, --SBN alias to be deprecated at a later stage
	{ 'TDVIA', 'TDVİA' }, --alias name without diacritics
	{ 'tdvia', 'TDVİA' }, --lowercase variant without diacritics
}

-- Deprecated aliases to p.conf; tracked in [[Kategorija:Wikipedijini članki z nezaželenimi identifikatorji normativne kontrole]]
-- Format: { 'deprecated parameter name', 'replacement parameter name in p.conf' }
p.deprecated = {
	{ 'GKD', 'GND' },
	{ 'PND', 'GND' },
	{ 'RLS', 'RSL' },	
	{ 'SWD', 'GND' },
	{ 'NARA-organization', 'NARA' },
	{ 'NARA-person', 'NARA' },
}

--[[==========================================================================]]
--[[                                   Main                                   ]]
--[[==========================================================================]]

function p.authorityControl( frame )
	local resolveEntity = require( "Module:ResolveEntityId" )
	local parentArgs = frame:getParent().args --WD IDs added here later
	local iParentArgs = 0 --count original/manual parent args only later
	local worldcatCat = ''
	local multipleIdCat = ''
	local suppressedIdCat = ''
	local deprecatedIdCat = ''
	local differentOnWDCat = ''
	local sameOnWDCat = ''
	
	--Redirect aliases to proper parameter names
	for _, a in pairs( p.aliases ) do
		local alias, param = a[1], a[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then
			parentArgs[param] = parentArgs[alias]
		end
	end
	
	--Redirect deprecated parameters to proper parameter names, and assign tracking cat
	for _, d in pairs( p.deprecated ) do
		local dep, param = d[1], d[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then
			parentArgs[param] = parentArgs[dep]
			if namespace == 0 then
				deprecatedIdCat = '[[Kategorija:Wikipedijini članki z nezaželenimi identifikatorji normativne kontrole|'..dep..']]'
			end
		end
	end
	
	--Use QID= parameter for testing/example purposes only
	local itemId = nil
	if namespace ~= 0 then
		local qid = parentArgs['qid'] or parentArgs['QID']
		if qid then
			itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '')
			itemId = resolveEntity._id(itemId) --nil if unresolvable
		end
	else
		itemId = mw.wikibase.getEntityIdForCurrentPage()
	end
	
	--Wikidata fallback if available
	if itemId then
		local iMatches = 0
		for _, params in ipairs( p.conf ) do
			if params[2] > 0 then
				local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
				if val == nil or val == '' then
					local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
					if wikidataIds[1] then
						if val == '' and (namespace == 0 or testcases) then
							suppressedIdCat = '[[Kategorija:Wikipedijini članki z onemogočenimi identifikatorji normativne kontrole|'..params[1]..']]'
						else
							parentArgs[params[1]] = wikidataIds[1] --add ID from WD
						end
					end
				else
					iParentArgs = iParentArgs + 1
					local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
					if wikidataIds[1] and differentOnWDCat == '' then
						local bMatch = false
						for _, wd in pairs( wikidataIds ) do
							if val == wd then
								iMatches = iMatches + 1
								bMatch = true
							end
						end
						if bMatch == false then
							differentOnWDCat = '[[Kategorija:Strani z normativno kontrolo s parametri različnimi od Wikipodatkov|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[Kategorija:Strani z normativno kontrolo s parametri enakimi z Wikipodatki]]'
		end
	end
	--Configured rows
	local rct = 0
	local sectionOrder = {"Splošno","Narodne knjižnice","Umetnostne galerije in muzeji",
						  "Inštituti za umetnostno raziskovanje","Biografski slovarji","Znanstvene podatkovne baze",
						  "Drugo"}
	local sections = {
		["Splošno"] = {},
		["Narodne knjižnice"] = {},
		["Umetnostne galerije in muzeji"] = {},
		["Inštituti za umetnostno raziskovanje"] = {},
		["Biografski slovarji"] = {},
		["Znanstvene podatkovne baze"] = {},
		["Drugo"] = {}
	}
	-- Don't show NLP is PLWABN is present, since they both go to the National Library of Poland
	-- and the library has deprecated NLP IDs in favor of PLWABN IDs
	if parentArgs.PLWABN or parentArgs.plwabn then
		parentArgs.NLP = ''
		parentArgs.nlp = ''
	end
	for _, params in ipairs( p.conf ) do
		local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
		local tval, tlinks = {}, {} --init tables
		if val and val ~= '' and type(params[3]) == 'function' then
			table.insert( tval, val )
			if params.prefix then 
				table.insert( tlinks, params[3]( val, "1" ) )
			else
				table.insert( tlinks, params[3]( val ) )
			end
		end
		--collect other unique vals (IDs) from WD, if present
		if itemId and tval[1] then
			local nextIdVal = 2
			local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
			for _, v in pairs( wikidataIds ) do
				local bnew = true
				for _, w in pairs( tval ) do
					if v == w then bnew = false end
				end
				if bnew then
					table.insert( tval, v )
					table.insert( tlinks, params[3]( v, tostring(nextIdVal) ) )
					nextIdVal = nextIdVal + 1
				end
			end
		end
		--assemble
		if tval[1] then
			table.insert( sections[params[4]], p.createRow( params[1], tval, nil, tlinks, true, params.category, params.prefix) )
			rct = rct + 1
			if tval[2] then
				multipleIdCat = p.getCatForId( '- večkratni' )
			end
		end

	end
	
	--WorldCat
	local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
	if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
		table.insert( sections["Splošno"], p.createRow( 'WORLDCATID', worldcatId, '[https://www.worldcat.org/identities/'..mw.uri.encode(worldcatId, 'PATH')..' WorldCat]', nil, false ) ) --Validation?
		worldcatCat = p.getCatForId( 'WORLDCATID' )
		rct = rct + 1
	elseif worldcatId == nil then --if WORLDCATID absent but unsuppressed
		local viafId = parentArgs['viaf'] or parentArgs['VIAF']
		local lccnId = parentArgs['lccn'] or parentArgs['LCCN']
		if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated
			table.insert( sections["Splošno"], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (via VIAF)]', nil, false ) )
			if namespace == 0 then 
				worldcatCat = '[[Kategorija:Wikipedijini članki z identifikatorji WorldCat-VIAF]]'
			end
			rct = rct + 1
		elseif lccnId and lccnId ~= '' and p.lccnLink( lccnId ) then --LCCN must be present, unsuppressed, & validated
			local lccnParts = p.splitLccn( lccnId )
			if lccnParts and lccnParts[1] ~= 'sh' then
				local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3]
				table.insert( sections["Splošno"], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (via Library of Congress)]', nil, false ) )
				if namespace == 0 then
					worldcatCat = '[[Kategorija:Wikipedijini članki z identifikatorji WorldCat-LCCN]]'
				end
			end
			rct = rct + 1
		end
	elseif worldcatId == '' then --if WORLDCATID suppressed
		suppressedIdCat = '[[Kategorija:Wikipedijini članki z onemogočenimi identifikatorji normativne kontrole|WORLDCATID]]'
	end
	
	local Navbox = require('Modul:Navbox')
	local elementsCat = ''
	if rct == 0 or rct >= 25 then
		local eCat = ''..rct..' elementov normativne kontrole'
		elementsCat  = '[[Kategorija:'..eCat..']]'..p.redCatLink(eCat)
	end
	
	local outString = ''
	if rct > 0 then
		local sectionID = 1
		local args = { pid = 'identifiers' } -- #target the list of identifiers
		if testcases and itemId then args = { pid = 'identifiers', qid = itemId } end --expensive
		local pencil = frame:expandTemplate{ title = 'EditAtWikidata', args = args}
		local navboxArgs = {
			name  = 'Normativna kontrola',
			navboxclass = 'authority-control',
			bodyclass = 'hlist',
			state = parentArgs.state or 'autocollapse',
			navbar = 'off'
		}
		for _, sectName in ipairs(sectionOrder) do
			if #sections[sectName] ~= 0 then
				navboxArgs["group" .. sectionID] = sectName
				navboxArgs["list" .. sectionID] = table.concat(sections[sectName])
				sectionID = sectionID + 1
			end
		end
		if navboxArgs.group2 then
			navboxArgs.title = "[[Wikipedija:Normativna kontrola]]" .. pencil
		else
			local sect = navboxArgs.group1
			if sect == "Splošno" or sect == "Drugo" then
				-- Just say "Authority control" with no label if only general or only other IDs are present
				-- since "Splošno" is redundant and "Drugo" is silly when there's nothing to contrast it with
				navboxArgs.group1 = "[[Wikipedija:Normativna kontrola|Normativna kontrola]]" .. pencil
			else 
				navboxArgs.group1 = "[[Wikipedija:Normativna kontrola|Normativna kontrola: " .. sect .. "]] " .. pencil
			end
		end
		outString = Navbox._navbox(navboxArgs)
	end
	
	local auxCats = worldcatCat .. elementsCat .. multipleIdCat .. suppressedIdCat .. 
					deprecatedIdCat .. differentOnWDCat .. sameOnWDCat
	if testcases then
		auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Kategorija)', '%1:%2') --for easier checking
	end
	outString = outString .. auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(Kategorija:Članki)', '%1:%2') --by definition
	end
	
	return outString
end

return p