Permanente a nasalakniban a modulo

Modulo:Kontrol ti autoridad

Manipud iti Wikipedia, ti nawaya nga ensiklopedia
Darsen a mapan iti pagdaliasatan Darsen a mapan agbiruk
Dokumentasion ti modulo

Daytoy a modulo ket us-usaren ti plantilia {{Kontrol ti autoridad}}. Kitaen ti {{Kontrol ti autoridad/dok}} para kadagiti panangipalpalawag ti panagusar.


Dagiti parametro, tatagikua ti Wikidata, ken pagsurotan a katkategoria

Parametro Seksion Agparang a kas Tagikua ti Wikidata Pagsurotan a katkategoria ken bilang ti panid
Ar-artikulo Pampanid ti agar-aramat Nadumaduma a pampanid Dagiti naperdi nga ID
AAG Dagiti galeria ken museo ti arte Auckland P3372: Auckland Art Gallery artist ID 14 0 0 0
ACM-DL Dagiti sientipiko a database Gunglo para iti Komputado ti Makina P864: ACM Digital Library author ID 3 0 0 0
ADB Dagiti bibliograpiko a diksionario Australia P1907: Australian Dictionary of Biography ID 9 0 0 0
AGSA Dagiti galeria ken museo ti arte Abagatan nga Australia P6804: Art Gallery of South Australia creator ID 9 0 0 0
autores.uy Dagiti bibliograpiko a diksionario Uruguay P2558: ID ti autores.uy 0 0 0 0
AWR Dagiti bibliograpiko a diksionario Rehistro ti Babbai ti Australia P4186: Australian Women's Register ID 1 0 0 0
BIBSYS Dagiti nailian a biblioteka Norwega P1015: panangilasin ti BIBSYS 694 0 0 0
Bildindex Dagiti patakder ti panagsukisok ti arte Bildindex (Alemania) P2092: Bildindex der Kunst und Architektur ID 0 0 0 0
BNC Dagiti nailian a biblioteka Chile P1890: ID ti CCAB 188 0 0 0
BNE Dagiti nailian a biblioteka Espania P950: panangilasin ti BNE 1,008 0 0 0
BNF Dagiti nailian a biblioteka Pransia (datos) P268: panangilasin ti BNF 1,424 1 0 0
Botaniko Dagiti sientipiko a database International Plant Names Index P428: botanist author abbreviation 54 0 0 0
BPN Dagiti bibliograpiko a diksionario Olanda P651: BPN 33 0 0 0
CANTIC Dagiti nailian a biblioteka Katalonia P1273: CANTIC 708 0 0 0
CINII Dagiti sientipiko a database CiNii (Hapon) P271: panangilasin ti mannurat ti CiNii 575 0 0 0
CWGC Dadduma Komision dagiti Tanem ti Gubat ti Mankomunidad P1908: CWGC person ID 0 0 0 0
DAAO Dagiti patakder ti panagsukisok ti arte Dagiti Artista ti Australia P1707: DAAO ID 2 0 0 0
DBLP Dagiti sientipiko a database DBLP (siensia ti kompiuter) P2456: DBLP author ID 8 0 0 0
DIB Dagiti bibliograpiko a diksionario Irlanda P6829: Dictionary of Irish Biography ID 11 0 0 0
DSI Dagiti patakder ti panagsukisok ti arte Dagiti sientipiko nga ilustrador P2349: Stuttgart Database of Scientific Illustrators ID 16 0 0 0
FAST Dadduma Faceted Application of Subject Terminology P2163: FAST ID 1,217 0 0 0
FNZA Dagiti patakder ti panagsukisok ti arte Dagiti Artista ti Baro a Selanda P6792: Find NZ Artists ID 0 0 0 0
GND Sapasap Integrated Authority File (Alemania) P227: panangilasin ti GND 1,893 1 4 0
HDS Dadduma Naipakasaritaan a Diksionario ti Suisa P902: ID ti HDS 208 0 0 0
IAAF Dadduma World Athletics P1146: World Athletics athlete ID 1 0 0 0
ICCU Dagiti nailian a biblioteka Italia P396: panangilasin ti SBN 380 0 0 0
ICIA Dagiti patakder ti panagsukisok ti arte ICIA (Israel) P1736: Information Center for Israeli Art artist ID 0 0 0 0
IEU Dadduma Ensiklopedia ti Intenet ti Ukrania P9070: Internet Encyclopedia of Ukraine ID 10 0 0 0
ISNI Sapasap ISNI P213: ISNI 1,398 1 1 0
Joconde Dagiti patakder ti panagsukisok ti arte Joconde (Pransia) P347: Joconde work ID 0 0 0 0
KULTURNAV Dagiti patakder ti panagsukisok ti arte KulturNav (Norwega) P1248: KulturNav-ID 44 0 0 0
LCCN Dagiti nailian a biblioteka Estados Unidos P244: Panagtengngel a Numero ti Biblioteka ti Kongreso (LCCN) 1,876 1 4 0
LIR Dadduma Lexicon Istoric Retic (Suisa) P886: Lexicon istoric retic ID 4 0 0 0
LNB Dagiti nailian a biblioteka Letonia P1368: ID ti LNB 472 0 0 0
Léonore Dadduma Léonore (Pransia) P640: panangilasin ti Léonore 26 0 0 0
MA Dadduma Akademiko ti Microsoft P6366: Microsoft Academic ID 117 0 0 0
MBA Dadduma MusicBrainz (artista) P434: ID ti artista ti MusicBrainz 526 0 0 0
MBAREA Dadduma MusicBrainz (ayan) P982: ID ti ayan ti MusicBrainz 445 0 0 0
MBI Dadduma MusicBrainz (instrumento) P1330: ID ti instrumento ti MusicBrainz 1 0 0 0
MBL Dadduma MusicBrainz (etiketa) P966: ID ti etiketa ti MusicBrainz 0 0 0 0
MBP Dadduma MusicBrainz (lugar) P1004: ID ti lugar ti MusicBrainz 1 0 0 0
MBRG Dadduma MusicBrainz (grupo ti panagipablaak) P436: ID ti grupo ti panagipablaak ti MusicBrainz 0 0 0 0
MBS Dadduma MusicBrainz (serye) P1407: ID ti serye ti MusicBrainz 0 0 0 0
MBW Dadduma MusicBrainz (obra) P435: MusicBrainz work ID 2 0 0 0
MGP Dagiti sientipiko a database Proyekto ti Henelohia ti Matematika P549: Mathematics Genealogy Project ID 60 0 0 0
NARA Dadduma Nailian nga Ar-arkibo (EU) P1225: U.S. National Archives Identifier 607 0 0 0
NCL Dagiti nailian a biblioteka Taiwan P1048: NCL ID 20 0 0 0
NDL Dagiti nailian a biblioteka Hapon P349: panangilasin ti NDL 1,021 0 0 0
NGV Dagiti galeria ken museo ti arte Victoria P2041: National Gallery of Victoria artist ID 19 0 0 0
NKC Dagiti nailian a biblioteka Republika a Tseka P691: panangilasin ti NKC 1,426 0 0 0
NLA Dagiti nailian a biblioteka Australia P409: panangilasin ti NLA 683 0 0 0
NLG Dagiti nailian a biblioteka Gresia P3348: ID ti Nailian a Biblioteka ti Gresia 419 0 0 0
NLI Dagiti nailian a biblioteka Israel P949: panangilasin ti NLI (Israel) 775 0 0 0
NLK Dagiti nailian a biblioteka Korea P5034: National Library of Korea ID 427 0 0 0
NLP Dagiti nailian a biblioteka Polonia P1695: NLP ID (unique) 1 0 0 0
NLR Dagiti nailian a biblioteka Romania P1003: ID ti Nailian a Biblioteka ti Romania 63 0 0 0
NSK Dagiti nailian a biblioteka Kroasia P1375: NSK ID 370 0 0 0
NTA Dagiti nailian a biblioteka Olanda P1006: panangilasin ti NTA (Olanda) 986 0 0 0
ORCID Sapasap ORCID P496: ORCID 4 1 0 0
PIC Dagiti patakder ti panagsukisok ti arte Identidad dagiti Potograpo P2750: Photographers' Identities Catalog ID 31 0 0 0
PLWABN Dagiti nailian a biblioteka Polonia P7293: PLWABN ID 843 0 0 0
Publons Dagiti sientipiko a database Publons (dagiti agsuksukisok) P3829: Publons author ID 0 0 0 0
RID Dagiti sientipiko a database ResearcherID P1053: ResearcherID 1 0 0 0
RISM Dadduma RISM (Pransia) P5504: RISM ID 184 0 0 0
RERO Dadduma RERO (Suisa) P3065: RERO ID 541 0 0 0
RKDartists Dagiti patakder ti panagsukisok ti arte RKD Artists (Olanda) P650: RKDartists 120 0 0 0
RKDID Dagiti patakder ti panagsukisok ti arte RKD ID (Olanda) P350: RKDimages ID 0 0 0 0
RSL Dagiti nailian a biblioteka Rusia P947: panangilasin ti RSL (tao) 86 0 0 0
SELIBR Dagiti nailian a biblioteka Suesia P906: SELIBR 651 0 0 0
SIKART Dagiti patakder ti panagsukisok ti arte SIKART (Suisa) P781: SIKART ID 3 0 0 0
SNAC-ID Dadduma Social Networks and Archival Context P3430: SNAC ARK ID 798 0 0 0
SUDOC Dadduma SUDOC (Pransia) P269: dagiti turay ti SUDOC 1,159 0 0 0
S2AuthorId Dagiti sientipiko a database Semantic Scholar P4012: Semantic Scholar author ID 14 0 0 0
TA98 Dagiti sientipiko a database Terminologia Anatomica P1323: Terminologia Anatomica 98 ID 0 0 0 0
TDVİA Dadduma Ensiklopedia ti Islam P7314: TDV İslam Ansiklopedisi ID 109 0 0 0
TePapa Dagiti galeria ken museo ti arte Te Papa (Baro a Selanda) P3544: Te Papa agent ID 53 0 0 0
TLS Dadduma Theaterlexikon (Suisa) P1362: Theaterlexikon der Schweiz ID 5 0 0 0
Trove Dadduma Trove (Australia) P1315: NLA Trove ID 754 0 0 0
UKPARL Dadduma Parlamento ti NP P6213: UK Parliament identifier 1 0 0 0
ULAN Dagiti patakder ti panagsukisok ti arte Nagnagan ti artista (Getty) P245: panangilasin ti ULAN 328 0 0 0
USCongress Dadduma Kongreso ti EU P1157: US Congress Bio ID 70 0 0 0
VcBA Dagiti nailian a biblioteka Batikano P8034: Vatican Library VcBA ID 530 0 0 0
VIAF Sapasap VIAF P214: panangilasin ti VIAF 1,943 1 4 0
WORLDCATID Sapasap WorldCat P7859: WorldCat Identities ID 1,828 0 0 0
Sapasap WorldCat (babaen ti Biblioteka ti Kongreso) 0
Sapasap WorldCat (babaen ti VIAF) 116

Dagiti maipatinayon a pagsurotan a katkategoria

Isayangkat pay daytoy a modulo dagiti sumaganad a pagsurotan a kategoria:

Bilang dagiti panagilasin

require('Modulo:No globals')

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

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

function p.getCatForId( id )
	local catName = ''
	if namespace == 0 then
		catName = 'Dagiti artikulo ti Wikipedia nga agraman kadagiti panangilasin ti '.. id ..' '
	elseif namespace == 2 and not title.isSubpage then
		catName = 'Pampanid ti agar-aramat nga agraman kadagiti panangilasin ti '.. id ..' '
	else
		catName = 'Nadumaduma a pampanid nga agraman kadagiti panangilasin ti '.. id ..' '
	end
	return '[[Kategoria:'..catName..']]'..p.redCatLink(catName)
end

function p.redCatLink( catName ) --catName == 'Blah' (not 'Category:Blah', not '[[Category:Blah]]')
	if catName and catName ~= '' and
	   testcases == false and
	   mw.title.new(catName, 14).exists == false
	then
		return '[[Kategoria:Pampanid nga agraman kadagiti kategoria ti naisilpo iti nalabbasit a kontrol ti autoridad]]'
	end
	return ''
end

function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix)
	local catName = 'Dagiti artikulo ti Wikipedia nga agraman kadagiti naperdi a panangilasin ti '..(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">Saan nga umiso ti id ti '..id..' '..rawValues[i]..'.</span>[[Kategoria:'..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">Saan nga umiso ti id ti '..id..' '..rawValues..'.</span>[[Kategoria:'..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 'Gunglo para iti Komputado ti Makina')..']'..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 'Australia')..']'..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 'Abagatan nga Australia')..']'..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 'Rehistro ti Babbai ti Australia')..']'..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 'Norwega')..']'..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 (Alemania)')..']'..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 'Chile')..']'..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 'Espania')..']'..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 'Pransia')..'] [https://data.bnf.fr/ark:/12148/'..id..' (datos)]'..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( 'Botaniko' )
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 'Olanda')..']'..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 'Katalonia')..']'..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 (Hapon)')..']'..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 'Komision dagiti Tanem ti Gubat ti Mankomunidad')..']'..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 'Dagiti Artista ti Australia')..']'..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 (siensia ti kompiuter)')..']'..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 'Irlanda')..']'..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 'Dagiti sientipiko nga ilustrador')..']'..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 'Dagiti Artista ti Baro a Selanda')..']'..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 (Alemania)')..']'..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 'Naipakasaritaan a Diksionario ti Suisa')..']'..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 'Italia')..']'..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 (Israel)')..']'..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 'Ensiklopedia ti Intenet ti Ukrania')..']'..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 (Pransia)')..']'..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 (Norwega)')..']'..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 'Estados Unidos')..']'..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 (Suisa)')..']'..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 'Letonia')..']'..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 (Pransia)')..']'..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 'Akademiko ti Microsoft')..']'..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 (panangilasin)|MusicBrainz]] [' .. url .. ' (artista)]' .. 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( 'ayan ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBAREA (panangilasin)|MusicBrainz]] [' .. url .. ' (ayan)]' .. 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( 'instrumento ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBI (panangilasin)|MusicBrainz]] [' .. url .. ' (instrumento)]' .. 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( 'etiketa ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBL (panangilasin)|MusicBrainz]] [' .. url .. ' (etiketa)]' .. 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( 'lugar ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBP (panangilasin)|MusicBrainz]] [' .. url .. ' (lugar)]' .. 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( 'grupo ti panagipablaak ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBRG (panangilasin)|MusicBrainz]] [' .. url .. ' (grupo ti panagipablaak)]' .. 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( 'serye ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBS (panangilasin)|MusicBrainz]] [' .. url .. ' (serye)]' .. 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( 'obra ti MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBW (panangilasin)|MusicBrainz]] [' .. url .. ' (obra)]' .. 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 'Proyekto ti Henelohia ti Matematika')..']'..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 'Nailian nga Ar-arkibo (EU)')..']'..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 'Taiwan')..']'..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 'Hapon')..']'..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 'Victoria')..']'..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 'Republika a Tseka')..']'..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 'Australia')..']'..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 'Gresia')..']'..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 'Israel')..']'..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 'Korea')..']'..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 'Polonia')..']'..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 'Romania')..']'..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 'Kroasia')..']'..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 'Olanda')..']'..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 'Identidad dagiti  Potograpo')..']'..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 'Polonia')..']'..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 (dagiti agsuksukisok)')..']'..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 (Pransia)')..']'..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 (Suisa)')..']'..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 (Olanda)')..']'..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 (Olanda)')..']'..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 'Rusia')..']'..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 'Suesia')..']'..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 (Suisa)')..']'..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 (Pransia)')..']'..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( 'mannurat ti Semantic Scholar' ) --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 'Ensiklopedia ti 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 (Baro a Selanda)')..']'..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 (Suisa)')..']'..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 (Australia)')..']'..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 'Parlamento ti NP')..']'..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 'Nagnagan ti artista (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 'Kongreso ti EU')..']'..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 'Batikano')..']'..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

--[[=========================== 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 | Parametro\n'..
					  '! rowspan=2 | Seksion\n'..
					  '! rowspan=2 | Agparang a kas\n'..
					  '! rowspan=2; data-sort-type=number | Tagikua ti Wikidata\n'..
					  '! colspan=4 | Pagsurotan a katkategoria ken bilang ti panid\n'..
					  '|-\n'..
					  '! [[:Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti pakaammo ti kontrol ti autoridad|'..             'Ar-artikulo]]\n'..
					  '! [[:Kategoria:Pampanid ti agar-aramat nga agraman kadagiti pakaammo ti kontrol ti autoridad|'..                  'Pampanid ti agar-aramat]]\n'..
					  '! [[:Kategoria:Nadumaduma a pampanid nga agraman kadagiti pakaammo ti kontrol ti autoridad|'..                    'Nadumaduma a pampanid]]\n'..
					  '! [[:Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti naperdi a panangilasin ti kontrol ti autoridad|'..'Dagiti naperdi nga ID]]\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 .. ' (panangilasin)'
		local category = conf.category or param
		local args = { id = 'f', pid }
		local wpl = frame:expandTemplate{ title = 'Silpo ti tagikua ti Wikidata', args = args }
		--cats
		local articleCat = 'Dagiti artikulo ti Wikipedia nga agraman kadagiti panangilasin ti '..category..' '
		local userCat =    'Pampanid ti agar-aramat nga agraman kadagiti panangilasin ti '..category..' '
		local miscCat =    'Nadumaduma a pampanid nga agraman kadagiti panangilasin ti '..category..' '
		local faultyCat =  'Dagiti artikulo ti Wikipedia nga agraman kadagiti naperdi a panangilasin ti '..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;"|[[:Kategoria:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|[[:Kategoria:'..   userCat..'|'..   userCount..']]'..
					'||style="text-align: right;"|[[:Kategoria:'..   miscCat..'|'..   miscCount..']]'..
					'||style="text-align: right;"|[[:Kategoria:'.. faultyCat..'|'.. faultyCount..']]'
	end
	
	--append derivative WorldCat cats
	local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' }
	for _, w in pairs(wcd) do
		local articleCat = 'Dagiti artikulo ti Wikipedia nga agraman kadagiti panangilasin ti '..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 (babaen ti Biblioteka ti Kongreso)]"
		else
			appearsAs = "[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (babaen ti VIAF)]"
		end
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||'..'—'..
					'||Sapasap'..
					'||'..appearsAs..
					'||data-sort-value='..w..'|'..'—'..
					'||style="text-align: right;"|[[:Kategoria:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'
	end
	
	return require("Modulo:Lapdan ti katkategoria").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, "Dagiti galeria ken museo ti arte", "1"},
	{ 'ACM-DL', 864, p.acmLink, "Dagiti sientipiko a database", "12345678901", link="ACM DL (panangilasin)"},
	{ 'ADB', 1907, p.adbLink,"Dagiti bibliograpiko a diksionario", "barton-sir-edmund-toby-71"},
	{ 'AGSA', 6804, p.agsaLink, "Dagiti galeria ken museo ti arte", "3625"},
	{ 'autores.uy', 2558, p.autoresuyLink, "Dagiti bibliograpiko a diksionario", "12345"},
	{ 'AWR', 4186, p.awrLink, "Dagiti bibliograpiko a diksionario", "PR00768b"},
	{ 'BIBSYS', 1015, p.bibsysLink, "Dagiti nailian a biblioteka", "1234567890123"},
	{ 'Bildindex', 2092, p.bildLink, "Dagiti patakder ti panagsukisok ti arte", "1"},
	{ 'BNC', 1890, p.bncLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'BNE', 950, p.bneLink, "Dagiti nailian a biblioteka", "XX1234567"},
	{ 'BNF', 268, p.bnfLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'Botaniko', 428, p.botanistLink , "Dagiti sientipiko a database", "L."},
	{ 'BPN', 651, p.bpnLink , "Dagiti bibliograpiko a diksionario", "12345678"},
	{ 'CANTIC', 1273, p.canticLink, "Dagiti nailian a biblioteka", "a12345678"},
	{ 'CINII', 271, p.ciniiLink, "Dagiti sientipiko a database", "DA12345678", link = "CiNii (panangilasin)"},
	{ 'CWGC', 1908, p.cwgcLink, "Dadduma", "1234567"},
	{ 'DAAO', 1707, p.daaoLink, "Dagiti patakder ti panagsukisok ti arte", "rolf-harris"},
	{ 'DBLP', 2456, p.dblpLink, "Dagiti sientipiko a database", "123/123"},
	{ 'DIB',  6829, p.dibLink, "Dagiti bibliograpiko a diksionario", "a1234"},
	{ 'DSI', 2349, p.dsiLink, "Dagiti patakder ti panagsukisok ti arte", "1538"},
	{ 'FAST', 2163, p.fastLink, "Dadduma", "1"},
	{ 'FNZA', 6792, p.fnzaLink, "Dagiti patakder ti panagsukisok ti arte", "12"},
	{ 'GND', 227, p.gndLink, "Sapasap", "4079154-3"},
	{ 'HDS', 902, p.hdsLink, "Dadduma", "050123"},
	{ 'IAAF', 1146, p.iaafLink, "Dadduma", "123"},
	{ 'ICCU', 396, p.iccuLink, "Dagiti nailian a biblioteka", "IT\\ICCU\\CFIV\\000163"}, --formerly SBN
	{ 'ICIA', 1736, p.iciaLink, "Dagiti patakder ti panagsukisok ti arte", "1"},
	{ 'IEU', 9070, p.ieuLink, "Dadduma", "N\\A\\NationalAcademyofArtandArchitecture"},
	{ 'ISNI', 213, p.isniLink, "Sapasap", "0000-0000-6653-4145", prefix = '[[ISNI (panangilasin)|ISNI]]'},
	{ 'Joconde', 347, p.jocondeLink, "Dagiti patakder ti panagsukisok ti arte", "12345678901"},
	{ 'KULTURNAV', 1248, p.kulturnavLink, "Dagiti patakder ti panagsukisok ti arte", "12345678-1234-1234-1234-1234567890AB", link="KulturNav (panangilasin)"},
	{ 'LCCN', 244, p.lccnLink, "Dagiti nailian a biblioteka", "n78039510"},
	{ 'LIR', 886, p.lirLink, "Dadduma", "1"},
	{ 'LNB', 1368, p.lnbLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'Léonore', 640, p.leonoreLink, "Dadduma", "LH/1/1", prefix = "[[Léonore (panangilasin)|Léonore (Pransia)]]"},
	{ 'MA', 6366, p.maLink, "Dadduma", "123456789"},
	{ 'MBA', 434, p.mbaLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz'}, --special cat name
	{ 'MBAREA', 982, p.mbareaLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'ayan ti MusicBrainz' }, --special cat name
	{ 'MBI', 1330, p.mbiLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'instrumento ti MusicBrainz' }, --special cat name
	{ 'MBL', 966, p.mblLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'etiketa ti MusicBrainz' }, --special cat name
	{ 'MBP', 1004, p.mbpLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'lugar ti MusicBrainz' }, --special cat name
	{ 'MBRG', 436, p.mbrgLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'grupo ti panagipablaak ti MusicBrainz' }, --special cat name
	{ 'MBS', 1407, p.mbsLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'serye ti MusicBrainz' }, --special cat name
	{ 'MBW',  435, p.mbwLink, "Dadduma", "12345678-1234-1234-1234-1234567890AB", category = 'obra ti MusicBrainz' }, --special cat name
	{ 'MGP', 549, p.mgpLink, "Dagiti sientipiko a database", "123456"},
	{ 'NARA', 1225, p.naraLink, "Dadduma", "12345678"},
	{ 'NCL', 1048, p.nclLink, "Dagiti nailian a biblioteka", "1081436"},
	{ 'NDL', 349, p.ndlLink, "Dagiti nailian a biblioteka", "012345678"},
	{ 'NGV', 2041, p.ngvLink, "Dagiti galeria ken museo ti arte", "12354"},
	{ 'NKC', 691, p.nkcLink, "Dagiti nailian a biblioteka", "abcd12345678901234"},
	{ 'NLA', 409, p.nlaLink, "Dagiti nailian a biblioteka", "123456789012"},
	{ 'NLG', 3348, p.nlgLink, "Dagiti nailian a biblioteka", "12345678"},
	{ 'NLI', 949, p.nliLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'NLK', 5034, p.nlkLink, "Dagiti nailian a biblioteka", "KAB197000000"},
	{ 'NLP', 1695, p.nlpLink, "Dagiti nailian a biblioteka", "9810123456789012345"},
	{ 'NLR', 1003, p.nlrLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'NSK', 1375, p.nskLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'NTA', 1006, p.ntaLink, "Dagiti nailian a biblioteka", "12345678X"},
	{ 'ORCID', 496, p.orcidLink, "Sapasap", "0000-0002-7398-5483", prefix = '[[ORCID (panangilasin)|ORCID]]'},
	{ 'PIC', 2750, p.picLink, "Dagiti patakder ti panagsukisok ti arte", "1"},
	{ 'PLWABN',  7293, p.plwabnLink, "Dagiti nailian a biblioteka", "9812345678905606"},
	{ 'Publons', 3829, p.publonsLink, "Dagiti sientipiko a database", "2776255"},
	{ 'RID', 1053, p.ridLink, "Dagiti sientipiko a database", "A-1234-1934"},
	{ 'RISM', 5504, p.rismLink, "Dadduma", "pe1",  prefix = '[[RISM (panangilasin)|RISM (Pransia)]]'},
	{ 'RERO', 3065, p.reroLink, "Dadduma", "02-A012345678", prefix = '[[RERO (panangilasin)|RERO (Suisa)]]'},
	{ 'RKDartists', 650, p.rkdartistsLink, "Dagiti patakder ti panagsukisok ti arte", "123456"},
	{ 'RKDID', 350, p.rkdidLink, "Dagiti patakder ti panagsukisok ti arte", "123456"},
	{ 'RSL', 947, p.rslLink, "Dagiti nailian a biblioteka", "123456789"},
	{ 'SELIBR', 906, p.selibrLink, "Dagiti nailian a biblioteka", "123456"},
	{ 'SIKART', 781, p.sikartLink, "Dagiti patakder ti panagsukisok ti arte", '123456789'},
	{ 'SNAC-ID', 3430, p.snacLink, "Dadduma", "A"},
	{ 'SUDOC', 269, p.sudocLink, "Dadduma", "026927608", prefix = '[[SUDOC (panangilasin)|SUDOC (Pransia)]]'},
	{ 'S2AuthorId', 4012, p.s2authoridLink, "Dagiti sientipiko a database", "1796130", category = 'mannurat ti Semantic Scholar' }, --special cat name
	{ 'TA98', 1323, p.ta98Link, "Dagiti sientipiko a database", "A12.3.45.678"},
	{ 'TDVİA', 7314, p.tdviaLink, "Dadduma", "asim-b-behdele"},
	{ 'TePapa', 3544, p.tepapaLink, "Dagiti galeria ken museo ti arte", "1"},
	{ 'TLS',  1362, p.tlsLink, "Dadduma", "Abcd"},
	{ 'Trove', 1315, p.troveLink, "Dadduma", "12345678", prefix = '[[Trove (panangilasin)|Trove (Australia)]]'}, --formerly NLA-person
	{ 'UKPARL', 6213, p.ukparlLink, "Dadduma", "AQUupyiR"},
	{ 'ULAN', 245, p.ulanLink, "Dagiti patakder ti panagsukisok ti arte", "500123456"},
	{ 'USCongress', 1157, p.uscongressLink, "Dadduma", "A000123", link = "US Congress (panangilasin)"},
	{ 'VcBA', 8034, p.vcbaLink, "Dagiti nailian a biblioteka", "494/9793"},
	{ 'VIAF', 214, p.viafLink, "Sapasap", "123456789", prefix = "[[VIAF (panangilasin)|VIAF]]"},
	{ 'WORLDCATID', 7859, nil, "Sapasap", nil, link = "WorldCat Identities (panangilasin)"},
}

-- 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 [[Category:Wikipedia articles with deprecated authority control identifiers]]
-- 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( "Modulo: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 = '[[Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti nasukatanen a panangilasin ti kontrol ti autoridad|'..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 = '[[Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti napasardeng a panangilasin ti kontrol ti autoridad|'..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 = '[[Kategoria:Pampanid nga agus-usar iti kontrol ti autoridad nga agraman kadagiti parametro a sabali iti Wikidata|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[Kategoria:Pampanid nga agus-usar iti kontrol ti autoridad nga agraman kadagiti parametro a maipada amin iti Wikidata]]'
		end
	end
	--Configured rows
	local rct = 0
	local sectionOrder = {"Sapasap","Dagiti nailian a biblioteka","Dagiti galeria ken museo ti arte",
						  "Dagiti patakder ti panagsukisok ti arte","Dagiti bibliograpiko a diksionario","Dagiti sientipiko a database",
						  "Dadduma"}
	local sections = {
		["Sapasap"] = {},
		["Dagiti nailian a biblioteka"] = {},
		["Dagiti galeria ken museo ti arte"] = {},
		["Dagiti patakder ti panagsukisok ti arte"] = {},
		["Dagiti bibliograpiko a diksionario"] = {},
		["Dagiti sientipiko a database"] = {},
		["Dadduma"] = {}
	}
	-- 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( 'agduduma' )
			end
		end

	end
	
	--WorldCat
	local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
	if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
		table.insert( sections["Sapasap"], 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["Sapasap"], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (babaen ti VIAF)]', nil, false ) )
			if namespace == 0 then 
				worldcatCat = '[[Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti panangilasin ti 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["Sapasap"], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (babaen ti Biblioteka ti Kongreso)]', nil, false ) )
				if namespace == 0 then
					worldcatCat = '[[[Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti panangilasin ti WorldCat-LCCN]]'
				end
			end
			rct = rct + 1
		end
	elseif worldcatId == '' then --if WORLDCATID suppressed
		suppressedIdCat = '[[Kategoria:Dagiti artikulo ti Wikipedia nga agraman kadagiti napasardeng a panangilasin ti kontrol ti autoridad|WORLDCATID]]'
	end
	
	local Navbox = require('Modulo:Navbox')
	local elementsCat = ''
	if rct == 0 or rct >= 25 then
		local eCat = 'Kontrol ti autoridad nga agraman kadagiti ' .. rct .. ' nga elemento'
		elementsCat  = '[[Kategoria:'..eCat..']]'..p.redCatLink(eCat)
	end
	
	local outString = ''
	if rct > 0 then
		local sectionID = 1
		local args = { pid = 'panangilasin' } -- #target the list of identifiers
		if testcases and itemId then args = { pid = 'panangilasin', qid = itemId } end --expensive
		local pencil = frame:expandTemplate{ title = 'EditAtWikidata', args = args}
		local navboxArgs = {
			name  = 'Kontrol ti autoridad',
			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 = "[[Tulong:Kontrol ti autoridad|Kontrol ti autoridad]]" .. pencil
		else
			local sect = navboxArgs.group1
			if sect == "Sapasap" or sect == "Dadduma" then
				-- Just say "Authority control" with no label if only general or only other IDs are present
				-- since "general" is redundant and "other" is silly when there's nothing to contrast it with
				navboxArgs.group1 = "[[Tulong:Kontrol ti autoridad|Kontrol ti autoridad]]" .. pencil
			else 
				navboxArgs.group1 = "[[Tulong:Kontrol ti autoridad|Kontrol ti autoridad: " .. 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, '(%[%[)(Kategoria)', '%1:%2') --for easier checking
	end
	outString = outString .. auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(Kategoria:Dagiti artikulo)', '%1:%2') --by definition
	end
	
	return outString
end

return p