มอดูล:Authority control

จากวิกิพีเดีย สารานุกรมเสรี
Documentation icon คู่มือการใช้งานมอดูล[ดู] [แก้] [ประวัติ] [ล้างแคช]

มอดูลนี้ประกอบด้วยโค้ดของแม่แบบ {{Authority control}} ดูเอกสารประกอบ

พารามิเตอร์ คุณลักษณะวิกิสนเทศ และหมวดหมู่ติดตาม

พารามิเตอร์ส่วนแสดงผลเป็นคุณลักษณะวิกิสนเทศหมวดหมู่การติดตามและจำนวนหน้า
บทความรหัสผิดพลาด
AAGหอศิลป์และพิพิธภัณฑ์ออกแลนด์P337240
ACM-DLฐานข้อมูลทางวิทยาศาสตร์สมาคมคอมพิวเตอร์เอซีเอ็มP86400
ADBพจนานุกรมชีวประวัติออสเตรเลียP190700
admiraltyตัวระบุประภาคารAdmiraltyP356200
AGSAหอศิลป์และพิพิธภัณฑ์รัฐเซาท์ออสเตรเลียP680430
ARLHSตัวระบุประภาคารARLHSP298000
autores.uyพจนานุกรมชีวประวัติอุรุกวัยP255810
AWRพจนานุกรมชีวประวัติAustralian Women's RegisterP418640
BIBSYSหอสมุดแห่งชาตินอร์เวย์P10153020
BildindexสถาบันวิจัยศิลปะBildindex (Germany)P209200
BNCหอสมุดแห่งชาติชิลีP1890490
BNEหอสมุดแห่งชาติสเปนP9505500
BNFหอสมุดแห่งชาติฝรั่งเศส (ข้อมูล)P268: BNF1,4580
BNMMหอสมุดแห่งชาติอาร์เจนตินาP3788360
Botanistฐานข้อมูลทางวิทยาศาสตร์International Plant Names IndexP42820
BPNพจนานุกรมชีวประวัติเนเธอร์แลนด์P65160
CANTICหอสมุดแห่งชาติแคว้นกาตาลุญญาP1273: ตัวระบุ CANTIC40
CANTICNหอสมุดแห่งชาติกาตาลุญญาP99841890
CCGตัวระบุประภาคารCCGP392000
CINIIฐานข้อมูลทางวิทยาศาสตร์CiNii (Japan)P2713680
CWGCอื่น ๆCommonwealth War Graves CommissionP190810
DAAOสถาบันวิจัยศิลปะศิลปินชาวออสเตรเลียP170700
DBLPฐานข้อมูลทางวิทยาศาสตร์DBLP (computer science)P245630
DIBพจนานุกรมชีวประวัติเกาะไอร์แลนด์P682930
DSIสถาบันวิจัยศิลปะScientific illustratorsP234910
DTBIOพจนานุกรมชีวประวัติเยอรมนีP79022460
EMUหอสมุดแห่งชาติยูเครนP46131380
FASTอื่น ๆFaceted Application of Subject TerminologyP21638930
FNZAสถาบันวิจัยศิลปะศิลปินชาวนิวซีแลนด์P679210
GNDหอสมุดแห่งชาติเยอรมนีP227: ตัวระบุ GND2,3113
Google Scholarฐานข้อมูลทางวิทยาศาสตร์Google ScholarP196080
HDSอื่น ๆHistorical Dictionary of SwitzerlandP9021660
IAAFอื่น ๆกรีฑาโลกP114610
ICCUหอสมุดแห่งชาติอิตาลีP396910
ICIAสถาบันวิจัยศิลปะICIA (Israel)P173600
IEUอื่น ๆInternet Encyclopedia of UkraineP9070240
ISNIทั่วไปISNIP213: ISNI (ISO 27729)1,2130
J9Uหอสมุดแห่งชาติอิสราเอลP8189: J9U2,2150
JocondeสถาบันวิจัยศิลปะJoconde (France)P34720
KULTURNAVสถาบันวิจัยศิลปะKulturNav (Norway)P1248170
LCCNหอสมุดแห่งชาติสหรัฐP244: LCCN2,6450
LIRอื่น ๆLexicon Istoric Retic (Switzerland)P88640
LNBหอสมุดแห่งชาติลัตเวียP1368: ตัวระบุ LNB2310
Marina MilitareตัวระบุประภาคารอิตาลีP386300
MarineTrafficตัวระบุประภาคารMarineTrafficP360100
MATHSNฐานข้อมูลทางวิทยาศาสตร์MathSciNetP4955130
MBAอื่น ๆมิวสิกเบรนซ์ ศิลปินP434: ตัวระบุชื่อศิลปินของ MusicBrainz4630
MBAREAอื่น ๆมิวสิกเบรนซ์ พื้นที่P9828220
MBIอื่น ๆมิวสิกเบรนซ์ เครื่องดนตรีP133000
MBLอื่น ๆมิวสิกเบรนซ์ ค่ายเพลงP966340
MBPอื่น ๆมิวสิกเบรนซ์ สถานที่P1004400
MBRGอื่น ๆมิวสิกเบรนซ์ กลุ่มการวางจำหน่ายP436780
MBSอื่น ๆมิวสิกเบรนซ์ ซีรีส์P140760
MBWอื่น ๆมิวสิกเบรนซ์ ผลงานP4351530
MGPฐานข้อมูลทางวิทยาศาสตร์Mathematics Genealogy ProjectP549200
NARAอื่น ๆNational Archives (US)P12254750
NCLหอสมุดแห่งชาติไต้หวันP1048: ตัวระบุ NCL110
NDLหอสมุดแห่งชาติญี่ปุ่นP349: ตัวระบุ NDL1,2250
NGAตัวระบุประภาคารNGAP356300
NGVหอศิลป์และพิพิธภัณฑ์วิกตอเรียP2041110
NKCหอสมุดแห่งชาติเช็กเกียP691: ตัวระบุ NKC1,5450
NLAหอสมุดแห่งชาติออสเตรเลียP409: ตัวระบุ NLA3030
NLGหอสมุดแห่งชาติกรีซP33481270
NLKหอสมุดแห่งชาติเกาหลีP50342900
NLPหอสมุดแห่งชาติโปแลนด์P1695: ตัวระบุ NLP30
NLRหอสมุดแห่งชาติโรมาเนียP100370
NSKหอสมุดแห่งชาติโครเอเชียP1375: ตัวระบุ NSK1370
NTAหอสมุดแห่งชาติเนเธอร์แลนด์P10064380
ORCIDทั่วไปORCIDP496130
PICสถาบันวิจัยศิลปะPhotographers' IdentitiesP275080
PLWABNหอสมุดแห่งชาติโปแลนด์P72934110
Publonsฐานข้อมูลทางวิทยาศาสตร์Publons (researchers)P382920
RIDฐานข้อมูลทางวิทยาศาสตร์ResearcherIDP105320
RISMอื่น ๆRISM (France)P5504260
REROอื่น ๆRERO (Switzerland)P30652410
RKDartistsสถาบันวิจัยศิลปะRKD Artists (Netherlands)P650280
RKDIDสถาบันวิจัยศิลปะRKD ID (Netherlands)P35010
RSLหอสมุดแห่งชาติรัสเซียP947160
Scopusฐานข้อมูลทางวิทยาศาสตร์Scopus authorP1153160
SELIBRหอสมุดแห่งชาติสวีเดนP9062880
SIKARTสถาบันวิจัยศิลปะSIKART (Switzerland)P78100
SNAC-IDอื่น ๆSocial Networks and Archival ContextP34302280
SUDOCอื่น ๆSUDOC (France)P269: ตัวระบุ idRef1,1350
TA98ฐานข้อมูลทางวิทยาศาสตร์Terminologia AnatomicaP1323110
TDVİAอื่น ๆİslâm AnsiklopedisiP73141400
TePapaหอศิลป์และพิพิธภัณฑ์Te Papa (New Zealand)P3544190
TLSอื่น ๆTheaterlexikon (Switzerland)P136200
Troveอื่น ๆTrove (Australia)P13152780
UKPARLอื่น ๆรัฐสภาสหราชอาณาจักรP621310
ULANสถาบันวิจัยศิลปะArtist Names (Getty)P245890
USCGตัวระบุประภาคารUSCGP372300
USCongressอื่น ๆรัฐสภาสหรัฐP115740
VcBAหอสมุดแห่งชาตินครรัฐวาติกันP80341340
VIAFทั่วไปVIAFP214: VIAF2,6530
WORLDCATIDทั่วไปเวิลด์แคตP78592,1400
ZBMATHฐานข้อมูลทางวิทยาศาสตร์zbMATHP1556220
-ทั่วไปเวิลด์แคต (ผ่านหอสมุดรัฐสภา)8
-ทั่วไปเวิลด์แคต (ผ่าน VIAF)519
ทั้งหมด9627,8243

หมวดหมู่ติดตามเพิ่มเติม

มอดูลนี้ยังใช้หมวดหมู่ติดตามที่ซ่อนอยู่ดังต่อไปนี้:

จำนวนตัวระบุ

พารามิเตอร์สถานะ

ดูเพิ่ม

  • m:Interwiki map – คำจำกัดความของคำนำหน้าอินเตอร์วิกิที่กำหนดเองทั่วโลก

require('มอดูล:No globals')

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

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

local function addCat( cat )
	if cat and cat ~= '' then return '[[หมวดหมู่:'..cat..']]'..p.redCatLink(cat) end
	return ''
end

function p.getCatForId( id )
	local cat = ''
	if namespace == 0 then
		cat = 'บทความที่มีตัวระบุ '..id
	end
	return addCat(cat)
end

function p.redCatLink( cat ) --cat == 'Blah' (not 'Category:Blah', not '[[Category:Blah]]')
	if cat and cat ~= '' and testcases == false and mw.title.new(cat, 14).exists == false then
		return '[[หมวดหมู่:หน้าที่มีหมวดหมู่การควบคุมรายการหลักฐานที่มีลิงก์แดง]]'
	end
	return ''
end

function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix)
	local faultyCat = 'บทความที่มีข้อบกพร่องตัวระบุ '..(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..' '..rawValues[i]..' ไม่ถูกต้อง</span>'..addCat(faultyCat)
			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..' '..rawValues..' ไม่ถูกต้อง</span>'..addCat(faultyCat)..'\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 'ออกแลนด์')..']'..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 'สมาคมคอมพิวเตอร์เอซีเอ็ม')..']'..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 'ออสเตรเลีย')..']'..p.getCatForId( 'ADB' )
end

function p.admiraltyLink(id,label)
	--P3562's format regex: [A-Q]\d{4}(\.\d+)? (e.g. D1204.1)
	if not id:match('^[A-Q]%d%d%d%d$') and
	   not id:match('^[A-Q]%d%d%d%d%.%d+$') then
		return false
	end
	return id..p.getCatForId( 'admiralty' )
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 'รัฐเซาท์ออสเตรเลีย')..']'..p.getCatForId( 'AGSA' )
end

function p.ARLHSLink(id,label)
	--P2980's format regex: [A-Z]{3}\d{3,4}[A-Z]?| e.g. LAT023
	if not id:match('^[A-Z][A-Z][A-Z]%d%d%d%d?[A-Z]?$') then
		return false
	end
	return '[http://wlol.arlhs.com/lighthouse/'..id..'.html '..(label or 'ARLHS')..']'..p.getCatForId( 'ARLHS' )
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 'อุรุกวัย')..']'..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 'นอร์เวย์')..']'..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 (Germany)')..']'..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 'ชิลี')..']'..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 'สเปน')..']'..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 'ฝรั่งเศส')..'] [https://data.bnf.fr/ark:/12148/'..id..' (ข้อมูล)]'..p.getCatForId( 'BNF' )
end

function p.bnmmLink( id, label )
	--P3788's format regex: \d{9} (e.g. 000024044)
	if id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return '[https://catalogo.bn.gov.ar/F/?func=direct&local_base=BNA10&doc_number='..id..' '..(label or 'อาร์เจนตินา')..']'..p.getCatForId( 'BNMM' )
	else
		return false
	end
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 'เนเธอร์แลนด์')..']'..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 'แคว้นกาตาลุญญา')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019
end

function p.canticnLink( id, label )
	--P9984's format regex: 981(0|1)\d{9}06706 (e.g. 981058515460906706)
	if not id:match( '^981[0-1]%d%d%d%d%d%d%d%d%d06706$' ) then
		return false
	end
	return '[https://cantic.bnc.cat/registre/'..id..' '..(label or 'กาตาลุญญา')..']'..p.getCatForId( 'CANTICN' )
end

function p.ccgLink( id, label )
	--P3920's format regex: ([NAIP])?[1-9]\d*(\.\d+)? (e.g. A1761)
	if not id:match( '^[NAIP]?[1-9]%d*$' ) and 
	   not id:match( '^[NAIP]?[1-9]%d*%.%d+$' ) then
		return false
	end
	return id..p.getCatForId( 'CCG' )
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 (Japan)')..']'..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.emuLink( id, label )
	--P4613's format regex: \d{1,6} (e.g. 15409 (or 015409))
	if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[http://esu.com.ua/search_articles.php?id='..id..' '..(label or 'ยูเครน')..']'..p.getCatForId( 'EMU' )
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 'ศิลปินชาวออสเตรเลีย')..']'..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: 0[01]\d{4}(\.[A-D])? (e.g. 001953)
	if not id:match( '^0[01]%d%d%d%d%.?[A-D]?$' ) then
		return false
	end
	return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'เกาะไอร์แลนด์')..']'..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.dtbioLink( id, label )
	--P7902's format regex: 1[0-9]{7,8}[0-9X] (e.g. 118554700)
	if not id:match( '^1[0-9]%d%d%d%d%d%d%d?[0-9X]$' ) then
		return false
	end
	return '[https://www.deutsche-biographie.de/pnd'..id..'.html?language=en '..(label or 'เยอรมนี')..']'..p.getCatForId( 'DTBIO' )
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 'ศิลปินชาวนิวซีแลนด์')..']'..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 'เยอรมนี')..']'..p.getCatForId( 'GND' )
end

function p.googleLink( id, label )
	--P1960's format regex: [-_0-9A-Za-z]{12} (e.g. CUO0vDcAAAAJ)
	if not id:match( '^[%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u]$' ) then
		return false
	end
	return '[https://scholar.google.com/citations?user='..id..' '..(label or 'Google Scholar')..']'..p.getCatForId( 'Google Scholar' )
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 'Historical Dictionary of Switzerland')..']'..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 'กรีฑาโลก')..']'..p.getCatForId( 'IAAF' )
end

function p.iccuLink( id, label )
	--P396's format regex: \D{2}[A-Z0-3]V\d{6} (e.g. CFIV000163)
	if not id:match( '^%u%u[%u0-3]V%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/nome/'..id..' '..(label or 'อิตาลี')..']'..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 '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.j9uLink( id, label )
	--P8189's format regex: 9870(0|1)\d{8}05171 (e.g. 987007305652505171)
	if not id:match( '^9870[0-1]%d%d%d%d%d%d%d%d05171$' ) then
		return false
	end
	return '[http://uli.nli.org.il/F/?func=find-b&local_base=NLX10&find_code=UID&request='..id..' '..(label or 'อิสราเอล')..']'..p.getCatForId( 'J9U' )
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 (France)')..']'..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 (Norway)')..']'..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 'สหรัฐ')..']'..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 (Switzerland)')..']'..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 'ลัตเวีย')..']'..p.getCatForId( 'LNB' )
end

function p.marinaMilitareLink( id, label )
	--P3863's format regex: [1-9]\d* (e.g. 3856)
	if id:match( '^[1-9]%d*$' ) then
		return '[http://www.marina.difesa.it/cosa-facciamo/per-la-difesa-sicurezza/fari/Pagine/'..id..'.aspx '..(label or 'อิตาลี')..']'..p.getCatForId( 'Marina Militare' )
	else
		return false
	end
end

function p.mathsnLink( id, label )
	--P4955's format regex: [1-9]\d{4,6} (e.g. 175270)
	if not id:match( '^[1-9]%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[https://mathscinet.ams.org/mathscinet/MRAuthorID/'..id..' '..(label or 'MathSciNet')..']'..p.getCatForId( 'MATHSN' )
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 '[[มิวสิกเบรนซ์]] ['..url..' ศิลปิน]'..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 '[[มิวสิกเบรนซ์]] ['..url..' พื้นที่]'..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 '[[มิวสิกเบรนซ์]] ['..url..' เครื่องดนตรี]'..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 '[[มิวสิกเบรนซ์]] ['..url..' ค่ายเพลง]'..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 '[[มิวสิกเบรนซ์]] ['..url..' สถานที่]'..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 '[[มิวสิกเบรนซ์]] ['..url..' กลุ่มการวางจำหน่าย]'..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 '[[มิวสิกเบรนซ์]] ['..url..' ซีรีส์]'..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 '[[มิวสิกเบรนซ์]] ['..url..' ผลงาน]'..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://www.mathgenealogy.org/id.php?id='..id..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' )
end

function p.mtLink( id, label )
	--P3601's format regex: \d{10} (e.g. 1000004707)
	if id:match( '^%d%d%d%d%d%d%d%d%d%d$' ) then
		return '[https://www.marinetraffic.com/en/ais/details/lights/'..id..' '..(label or 'MarineTraffic')..']'..p.getCatForId( 'MarineTraffic' )
	else
		return false
	end
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 (US)')..']'..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 'ไต้หวัน')..']'..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 'ญี่ปุ่น')..']'..p.getCatForId( 'NDL' )
end

function p.ngaLink(id,label)
	--P3563's format rgex: 11[0-6]-\d+(\.\d+)? (e.g. 114-7721.2)
	if not id:match('^11[0-6]%-%d+%.?%d*$') then
		return false
	end
	return '[https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fmsi.nga.mil%2FqueryResults%3Fpublications%2Fngalol%2Flights-buoys%3Fvolume%3D%251%26featureNumber%3D%252%26includeRemovals%3Dfalse%26output%3Dhtml&exp=(%5Cd%7B3%7D)-(.*)&id='..id..' '..(label or 'NGA')..']'..p.getCatForId( 'NGA' )
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 'วิกตอเรีย')..']'..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 'เช็กเกีย')..']'..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 'ออสเตรเลีย')..']'..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 'กรีซ')..']'..p.getCatForId( 'NLG' )
end

function p.nlkLink( id, label )
	--P5034's format regex: (KAB|KAC|KSH)([0-9]{4}|[0-9]{4}[a-zA-Z])[0-9]{4,6} (e.g. KAC201501465)
	if not id:match( '^KAB%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and
		not id:match( '^KAC%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and
		not id:match( '^KSH%d%d%d%d%a?%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[https://lod.nl.go.kr/resource/'..id..' '..(label or 'เกาหลี')..']'..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 'โปแลนด์')..']'..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 'โรมาเนีย')..']'..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 'โครเอเชีย')..']'..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 'เนเธอร์แลนด์')..']'..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 'โปแลนด์')..']'..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 (France)')..']'..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 (Switzerland)')..']'..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 (Netherlands)')..']'..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 (Netherlands)')..']'..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 'รัสเซีย')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019
end

function p.scopusLink( id, label )
	--P1153's format regex: [1-9]\d{9,10} (e.g. 35247902700)
	if not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d?$' ) then
		return false
	end
	return '[https://www.scopus.com/authid/detail.uri?authorId='..id..' '..(label or 'Scopus author')..']'..p.getCatForId( 'Scopus' )
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 'สวีเดน')..']'..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 (Switzerland)')..']'..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 (France)')..']'..p.getCatForId( 'SUDOC' )
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
	local longurl = '[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='
	return longurl..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( '^[%d%l/-]+$' ) then
		return false
	end
	return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'İslâm Ansiklopedisi')..']'..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 (New Zealand)')..']'..p.getCatForId( 'TePapa' )
end

function p.tlsLink( id, label )
	id = id:gsub(' +', '_')
	--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*\/–&]{3,89} (e.g. Abcd)
	--Mediawiki page title partial URL so consider validation with mw.title or "[^#<>%[%] {|}]"
	local class = "[%w_',%.%-%(%)%*%/–&]"
	local idlen = mw.ustring.len (id)
	if idlen < 4 or idlen > 90 then
		return false
	end
	local regex = '^%u'..string.rep(class, idlen - 1)..'$'
	if not mw.ustring.match( id, regex ) then
		return false
	end
	return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Switzerland)')..']'..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 'รัฐสภาสหราชอาณาจักร')..']'..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.uscgLink( id, label )
	--P3723's format regex: [1-7]-\d{1,5}(.[1-9])? (e.g. 6-0695)
	if not id:match( '^[1-7]%-%d%d?%d?%d?%d?$' ) and
	   not id:match( '^[1-7]%-%d%d?%d?%d?%d?%.%d*[1-9]$' ) then
		return false
	end
	return '[[USCG (identifier)|USCG]] ([https://www.navcen.uscg.gov/pdf/lightlists/LightList%20V'..mw.ustring.sub(id,1,1)..'.pdf '..id..'])'..p.getCatForId( 'USCG' )
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 'รัฐสภาสหรัฐ')..']'..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 'นครรัฐวาติกัน')..']'..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),
	-- then 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.worldcatidLink( id, label )
	--P7859's format regex: viaf-\d+|lccn-n[a-z]?[0-9\-]+|n[cps]-.+ (e.g. viaf-100181709, lccn-n78-95332, np-verbeck,%20william$1861)
	if not id:match( '^viaf%-%d+$' ) and
	   not id:match( '^lccn%-n[a-z]?[0-9%-]+$' ) and
	   not id:match( '^n[cps]%-.+$' ) then
		return false
	end
	return '[https://www.worldcat.org/identities/'..mw.uri.encode(id, 'PATH')..'/ '..(label or 'เวิลด์แคต')..']'..p.getCatForId( 'WORLDCATID' )
end

function p.zbmathLink( id, label )
	--P1556's format regex: [a-z][a-z\-]*(\.[a-z][a-z\-]*)?(\.[0-9]*)? (e.g. turing.alan-m)
	local ps = {'%l[%l%-]*', '%.%l[%l%-]*', '%.%d*'}
	if not id:match( '^'..ps[1]..'$' ) and -- prefix with no capture options
	   not id:match( '^'..ps[1]..ps[2]..'$' ) and -- prefix with first capture option
	   not id:match( '^'..ps[1]..ps[3]..'$' ) and -- prefix with second capture option
	   not id:match( '^'..ps[1]..ps[2]..ps[3]..'$' ) then -- prefix and both capture options
		return false
	end
	return '[https://zbmath.org/authors/?q=ai:'..id..' '..(label or 'zbMATH')..']'..p.getCatForId( 'ZBMATH' )
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 = {}
	if not mw.wikibase then
		return ids
	end
	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

function p.checkcat( category,label )
	local ret='[[:หมวดหมู่:'..category..'|'..label..']]'
	if mw.title.new(category, 14).exists == false then
		ret = ret..' <span class="plainlinks" style="font-size:85%;">&#91;['..tostring(mw.uri.fullUrl('หมวดหมู่:'..category,'action=edit&preload=Template:Authority_control/preload'))..' สร้าง]&#93;</span>'
	end
	return ret
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 = '<table class="wikitable sortable">'..
	  '<tr><th rowspan=2>พารามิเตอร์</th>'..
	  '<th rowspan=2>ส่วน</th>'..
	  '<th rowspan=2>แสดงผลเป็น</th>'..
	  '<th rowspan=2 data-sort-type=number>คุณลักษณะวิกิสนเทศ</th>'..
	  '<th colspan=2>หมวดหมู่การติดตามและจำนวนหน้า</th></tr>'..
	  '<tr><th>[[:หมวดหมู่:บทความที่มีข้อมูลการควบคุมรายการหลักฐาน|บทความ]]</th>'..
	  '<th>[[:หมวดหมู่:บทความที่มีข้อมูลการควบคุมรายการหลักฐานผิดพลาด|รหัสผิดพลาด]]</th></tr>'
	local lang = mw.getContentLanguage()
	local a, f, P = 0, 0, 0 --cumulative sums
	for _, conf in pairs( p.conf ) do
		local param, pid, section = conf[1], conf[2], conf[4]
		local appearsAs
		if conf.prefix then
			appearsAs = conf.prefix
		else
			appearsAs = conf[3](conf[5])
		end
		local link = conf.link or param..' (identifier)'
		local category = conf.category or param
		local args = { id = 'f', pid }
		local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args }
		--cats
		local articleCat = 'บทความที่มีตัวระบุ '..category
		local faultyCat =  'บทความที่มีข้อบกพร่องตัวระบุ '..category
		--counts
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
		local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
		--calcs
		P = P + 1 --property count
		a = a + lang:parseFormattedNumber(articleCount)
		f = f + lang:parseFormattedNumber(faultyCount)
		--concat
		wikiTable = wikiTable..'<tr><td>[['..link..'|'..param..']]</td>'..
			'<td>'..section..'</td>'..
			'<td>'..appearsAs..'</td>'..
			'<td data-sort-value='..pid..'>'..wpl..'</td>'..
			'<td style="text-align: right;">'..p.checkcat(articleCat,articleCount)..'</td>'..
			'<td style="text-align: right;">'..p.checkcat(faultyCat,faultyCount)..'</td></tr>'
	end
	
	--append derivative WorldCat cats
	local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' }
	for _, w in pairs(wcd) do
		local articleCat = 'บทความที่มีตัวระบุ '..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 เวิลด์แคต (ผ่านหอสมุดรัฐสภา)]'
		else
			appearsAs = '[https://www.worldcat.org/identities/containsVIAFID/12345789 เวิลด์แคต (ผ่าน VIAF)]'
		end
		a = a + lang:parseFormattedNumber(articleCount)
		wikiTable = wikiTable..'<tr><td>-</td>'..
			'<td>ทั่วไป</td>'..
			'<td>'..appearsAs..'</td>'..
			'<td data-sort-value='..w..'>—</td>'..
			'<td style="text-align: right;">[[:หมวดหมู่:'..articleCat..'|'..articleCount..']]</td>'..
			'<td style="text-align: right;">—</td></tr>'
	end
	
	--append sums
	wikiTable = wikiTable..'<tr><th style="text-align: right;" colspan=3>ทั้งหมด</th>'..
		'<th style="text-align: right;">'..lang:formatNum(P)..'</th>'..
		'<th style="text-align: right;">'..lang:formatNum(a)..'</th>'..
		'<th style="text-align: right;">'..lang:formatNum(f)..'</th></tr></table>'

	return require('มอดูล:Suppress categories').main(wikiTable)
end

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

-- Please use "<parameter> (identifier)" redirects rather than linking directly to the target page.
-- This reduces clutter in "What links here" on both the redirect and the target,
-- and improves reverse lookup of articles where a manifestation of each identifier is used.

-- p.conf table basic format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation }
-- p.conf table 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 "... with <parameter> identifiers")
--  prefix: to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself
p.conf = {
	{ 'AAG', 3372, p.aagLink, 'หอศิลป์และพิพิธภัณฑ์', '1' },
	{ 'ACM-DL', 864, p.acmLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '12345678901', link = 'ACM DL (identifier)' },
	{ 'ADB', 1907, p.adbLink,'พจนานุกรมชีวประวัติ', 'barton-sir-edmund-toby-71' },
	{ 'admiralty', 3562, p.admiraltyLink, 'ตัวระบุประภาคาร', 'D1204.1', prefix='[[Admiralty number|Admiralty]]'},
	{ 'AGSA', 6804, p.agsaLink, 'หอศิลป์และพิพิธภัณฑ์', '3625' },
	{ 'ARLHS', 2980, p.ARLHSLink, 'ตัวระบุประภาคาร', 'LAT023'},
	{ 'autores.uy', 2558, p.autoresuyLink, 'พจนานุกรมชีวประวัติ', '12345' },
	{ 'AWR', 4186, p.awrLink, 'พจนานุกรมชีวประวัติ', 'PR00768b' },
	{ 'BIBSYS', 1015, p.bibsysLink, 'หอสมุดแห่งชาติ', '1234567890123' },
	{ 'Bildindex', 2092, p.bildLink, 'สถาบันวิจัยศิลปะ', '1' },
	{ 'BNC', 1890, p.bncLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'BNE', 950, p.bneLink, 'หอสมุดแห่งชาติ', 'XX1234567' },
	{ 'BNF', 268, p.bnfLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'BNMM', 3788, p.bnmmLink, 'หอสมุดแห่งชาติ', '000024044' },
	{ 'Botanist', 428, p.botanistLink , 'ฐานข้อมูลทางวิทยาศาสตร์', 'L.' },
	{ 'BPN', 651, p.bpnLink , 'พจนานุกรมชีวประวัติ', '12345678' },
	{ 'CANTIC', 1273, p.canticLink, 'หอสมุดแห่งชาติ', 'a12345678' },
	{ 'CANTICN', 9984, p.canticnLink, 'หอสมุดแห่งชาติ', '981058515460906706' },
	{ 'CCG', 3920, p.ccgLink, 'ตัวระบุประภาคาร', 'A1761', prefix='[[CCG (identifier)|CCG]]' },
	{ 'CINII', 271, p.ciniiLink, 'ฐานข้อมูลทางวิทยาศาสตร์', 'DA12345678', link = 'CiNii (identifier)' },
	{ 'CWGC', 1908, p.cwgcLink, 'อื่น ๆ', '1234567' },
	{ 'DAAO', 1707, p.daaoLink, 'สถาบันวิจัยศิลปะ', 'rolf-harris' },
	{ 'DBLP', 2456, p.dblpLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '123/123' },
	{ 'DIB',  6829, p.dibLink, 'พจนานุกรมชีวประวัติ', '001953' },
	{ 'DSI', 2349, p.dsiLink, 'สถาบันวิจัยศิลปะ', '1538' },
	{ 'DTBIO', 7902, p.dtbioLink, 'พจนานุกรมชีวประวัติ', '118554700' },
	{ 'EMU', 4613, p.emuLink, 'หอสมุดแห่งชาติ', '15409' },
	{ 'FAST', 2163, p.fastLink, 'อื่น ๆ', '1' },
	{ 'FNZA', 6792, p.fnzaLink, 'สถาบันวิจัยศิลปะ', '12' },
	{ 'GND', 227, p.gndLink, 'หอสมุดแห่งชาติ', '4079154-3' },
	{ 'Google Scholar', 1960, p.googleLink, 'ฐานข้อมูลทางวิทยาศาสตร์', 'QPdLuj8AAAAJ' },
	{ 'HDS', 902, p.hdsLink, 'อื่น ๆ', '050123' },
	{ 'IAAF', 1146, p.iaafLink, 'อื่น ๆ', '123' },
	{ 'ICCU', 396, p.iccuLink, 'หอสมุดแห่งชาติ', 'CFIV000163' }, --formerly SBN
	{ 'ICIA', 1736, p.iciaLink, 'สถาบันวิจัยศิลปะ', '1' },
	{ 'IEU', 9070, p.ieuLink, 'อื่น ๆ', 'N\\A\\NationalAcademyofArtandArchitecture' },
	{ 'ISNI', 213, p.isniLink, 'ทั่วไป', '0000-0000-6653-4145', prefix = '[[ISNI (identifier)|ISNI]]' },
	{ 'J9U', 8189, p.j9uLink, 'หอสมุดแห่งชาติ', '987007305652505171' },
	{ 'Joconde', 347, p.jocondeLink, 'สถาบันวิจัยศิลปะ', '12345678901' },
	{ 'KULTURNAV', 1248, p.kulturnavLink, 'สถาบันวิจัยศิลปะ', '12345678-1234-1234-1234-1234567890AB', link = 'KulturNav (identifier)' },
	{ 'LCCN', 244, p.lccnLink, 'หอสมุดแห่งชาติ', 'n78039510' },
	{ 'LIR', 886, p.lirLink, 'อื่น ๆ', '1' },
	{ 'LNB', 1368, p.lnbLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'Marina Militare', 3863, p.marinaMilitareLink, 'ตัวระบุประภาคาร', '3856' },
	{ 'MarineTraffic', 3601, p.mtLink, 'ตัวระบุประภาคาร', '1000004707' },
	{ 'MATHSN', 4955, p.mathsnLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '175270' },
	{ 'MBA', 434, p.mbaLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz' }, --special cat name
	{ 'MBAREA', 982, p.mbareaLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz area' }, --special cat name
	{ 'MBI', 1330, p.mbiLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz instrument' }, --special cat name
	{ 'MBL', 966, p.mblLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz label' }, --special cat name
	{ 'MBP', 1004, p.mbpLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz place' }, --special cat name
	{ 'MBRG', 436, p.mbrgLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz release group' }, --special cat name
	{ 'MBS', 1407, p.mbsLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz series' }, --special cat name
	{ 'MBW',  435, p.mbwLink, 'อื่น ๆ', '12345678-1234-1234-1234-1234567890AB', category = 'MusicBrainz work' }, --special cat name
	{ 'MGP', 549, p.mgpLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '123456' },
	{ 'NARA', 1225, p.naraLink, 'อื่น ๆ', '12345678' },
	{ 'NCL', 1048, p.nclLink, 'หอสมุดแห่งชาติ', '1081436' },
	{ 'NDL', 349, p.ndlLink, 'หอสมุดแห่งชาติ', '012345678' },
	{ 'NGA', 3563, p.ngaLink, 'ตัวระบุประภาคาร', '114-5592'},
	{ 'NGV', 2041, p.ngvLink, 'หอศิลป์และพิพิธภัณฑ์', '12354' },
	{ 'NKC', 691, p.nkcLink, 'หอสมุดแห่งชาติ', 'abcd12345678901234' },
	{ 'NLA', 409, p.nlaLink, 'หอสมุดแห่งชาติ', '123456789012' },
	{ 'NLG', 3348, p.nlgLink, 'หอสมุดแห่งชาติ', '12345678' },
	{ 'NLK', 5034, p.nlkLink, 'หอสมุดแห่งชาติ', 'KAB197000000' },
	{ 'NLP', 1695, p.nlpLink, 'หอสมุดแห่งชาติ', '9810123456789012345' },
	{ 'NLR', 1003, p.nlrLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'NSK', 1375, p.nskLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'NTA', 1006, p.ntaLink, 'หอสมุดแห่งชาติ', '12345678X' },
	{ 'ORCID', 496, p.orcidLink, 'ทั่วไป', '0000-0002-7398-5483', prefix = '[[ORCID (identifier)|ORCID]]' },
	{ 'PIC', 2750, p.picLink, 'สถาบันวิจัยศิลปะ', '1' },
	{ 'PLWABN',  7293, p.plwabnLink, 'หอสมุดแห่งชาติ', '9812345678905606' },
	{ 'Publons', 3829, p.publonsLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '2776255' },
	{ 'RID', 1053, p.ridLink, 'ฐานข้อมูลทางวิทยาศาสตร์', 'A-1234-1934' },
	{ 'RISM', 5504, p.rismLink, 'อื่น ๆ', 'pe1',  prefix = '[[RISM (identifier)|RISM (France)]]' },
	{ 'RERO', 3065, p.reroLink, 'อื่น ๆ', '02-A012345678', prefix = '[[RERO (identifier)|RERO (Switzerland)]]' },
	{ 'RKDartists', 650, p.rkdartistsLink, 'สถาบันวิจัยศิลปะ', '123456' },
	{ 'RKDID', 350, p.rkdidLink, 'สถาบันวิจัยศิลปะ', '123456' },
	{ 'RSL', 947, p.rslLink, 'หอสมุดแห่งชาติ', '123456789' },
	{ 'Scopus', 1153, p.scopusLink, 'ฐานข้อมูลทางวิทยาศาสตร์', '7005487412' },
	{ 'SELIBR', 906, p.selibrLink, 'หอสมุดแห่งชาติ', '123456' },
	{ 'SIKART', 781, p.sikartLink, 'สถาบันวิจัยศิลปะ', '123456789' },
	{ 'SNAC-ID', 3430, p.snacLink, 'อื่น ๆ', 'A' },
	{ 'SUDOC', 269, p.sudocLink, 'อื่น ๆ', '026927608', prefix = '[[SUDOC (identifier)|SUDOC (France)]]' },
	{ 'TA98', 1323, p.ta98Link, 'ฐานข้อมูลทางวิทยาศาสตร์', 'A12.3.45.678' },
	{ 'TDVİA', 7314, p.tdviaLink, 'อื่น ๆ', 'asim-b-behdele' },
	{ 'TePapa', 3544, p.tepapaLink, 'หอศิลป์และพิพิธภัณฑ์', '1' },
	{ 'TLS',  1362, p.tlsLink, 'อื่น ๆ', 'Abcd' },
	{ 'Trove', 1315, p.troveLink, 'อื่น ๆ', '12345678', prefix = '[[Trove (identifier)|Trove (Australia)]]' }, --formerly NLA-person
	{ 'UKPARL', 6213, p.ukparlLink, 'อื่น ๆ', 'AQUupyiR' },
	{ 'ULAN', 245, p.ulanLink, 'สถาบันวิจัยศิลปะ', '500123456' },
	{ 'USCG', 3723, p.uscgLink, 'ตัวระบุประภาคาร', '6-0695', prefix='[[USCG (identifier)|USCG]]'},
	{ 'USCongress', 1157, p.uscongressLink, 'อื่น ๆ', 'A000123', link = 'US Congress (identifier)' },
	{ 'VcBA', 8034, p.vcbaLink, 'หอสมุดแห่งชาติ', '494/9793' },
	{ 'VIAF', 214, p.viafLink, 'ทั่วไป', '123456789', prefix = '[[VIAF (identifier)|VIAF]]' },
	{ 'WORLDCATID', 7859, p.worldcatidLink, 'ทั่วไป', 'lccn-n78-95332', link = 'WorldCat Identities (identifier)' },
	{ 'ZBMATH', 1556, p.zbmathLink, 'ฐานข้อมูลทางวิทยาศาสตร์', 'turing.alan-m' },
}

-- Legitimate aliases to p.conf, for convenience
-- Format: { 'alias', 'parameter name in p.conf' }
p.aliases = {
	{ 'DNB', 'GND' }, --Deutsche Nationalbibliothek -> Gemeinsame Normdatei
	{ '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: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( 'มอดูล:ResolveEntityId' )
	local parentArgs = frame:getParent().args --WD IDs added here later
	local iParentArgs = 0 --count original/manual parent args only later
	local worldcatCat = ''
	local elementsCat = ''
	local multipleIdCat = ''
	local suppressedIdCat = ''
	local suppressedIdCatArts = ''
	local deprecatedIdCat = ''
	local differentOnWDCat = ''
	local sameOnWDCat = ''
	local stateCat = ''
	
	--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 = '[[หมวดหมู่:บทความที่มีตัวระบุการควบคุมรายการหลักฐานที่เลิกใช้แล้ว |'..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
	elseif mw.wikibase then
		itemId = mw.wikibase.getEntityIdForCurrentPage()
	end
	
	--Wikidata fallback if available
	if itemId then
		local suppressedIdCount = 0
		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
							suppressedIdCount = suppressedIdCount + 1
							suppressedIdCat = '[[หมวดหมู่:บทความที่มีตัวระบุการควบคุมรายการหลักฐานที่ถูกระงับ|'..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 = '[[หมวดหมู่:หน้าที่ใช้การควบคุมรายการหลักฐานที่มีพารามิเตอร์ที่แตกต่างกันกับวิกิสนเทศ|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[หมวดหมู่:หน้าที่ใช้การควบคุมรายการหลักฐานที่มีพารามิเตอร์ทั้งหมดตรงกับวิกิสนเทศ]]'
		end
		if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then
			if namespace == 0 or testcases then
--				local s = 's'
--				if suppressedIdCount == 1 then s = '' end
				local sCat = 'ACArt ที่มีส่วนประกอบ '..suppressedIdCount..' รายการถูกระงับ'--..s
				suppressedIdCatArts = addCat(sCat)
			end
		end
	end
	
	--configure rows
	local rct = 0
	local sectionOrder = {
		'ทั่วไป',
		'หอสมุดแห่งชาติ',
		'หอศิลป์และพิพิธภัณฑ์',
		'สถาบันวิจัยศิลปะ',
		'พจนานุกรมชีวประวัติ',
		'ฐานข้อมูลทางวิทยาศาสตร์',
		'ตัวระบุประภาคาร',
		'อื่น ๆ'
	}
	local sections = {
		['ทั่วไป'] = {},
		['หอสมุดแห่งชาติ'] = {},
		['หอศิลป์และพิพิธภัณฑ์'] = {},
		['สถาบันวิจัยศิลปะ'] = {},
		['พจนานุกรมชีวประวัติ'] = {},
		['ฐานข้อมูลทางวิทยาศาสตร์'] = {},
		['ตัวระบุประภาคาร'] = {},
		['อื่น ๆ'] = {}
	}
	--don't show CANTIC if CANTICN is present, since they both go to the Library of Catalonia
	--and the library has deprecated CANTIC IDs in favor of CANTICN IDs
	if parentArgs.CANTICN or parentArgs.canticn then
		parentArgs.CANTIC = ''
		parentArgs.cantic = ''
	end
	--don't show NLP if 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( 'หลายรายการ' )
			end
		end

	end

	--WorldCat-VIAF & WorldCat-LCCN
	local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
	if 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['ทั่วไป'], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' เวิลด์แคต (ผ่าน VIAF)]', nil, false ) )
			if namespace == 0 then 
				worldcatCat = '[[หมวดหมู่:บทความที่มีตัวระบุ 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['ทั่วไป'], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' เวิลด์แคต (ผ่านหอสมุดรัฐสภา)]', nil, false ) )
				if namespace == 0 then
					worldcatCat = '[[หมวดหมู่:บทความที่มีตัวระบุ WorldCat-LCCN]]'
				end
			end
			rct = rct + 1
		end
	end
	
	--configure Navbox
	local outString = ''
	local extrap = true
	local extra = parentArgs.extralist
	if extra == nil or extra == '' then
		extrap = false
	end
	if rct > 0 or extrap then
		local Navbox = require('มอดูล:Navbox')
		local sectionID = 1
		local args = { pid = 'identifiers' } -- #target the list of identifiers
		if testcases and itemId then args.qid = itemId end --expensive
		local pencil = require('มอดูล:EditAtWikidata')._showMessage(args)
		local navboxArgs = {
			name  = 'Authority control',
			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 extrap then
			if parentArgs.extragroup then
				navboxArgs['group'..sectionID] = parentArgs.extragroup
			else
				navboxArgs['group'..sectionID] = 'เพิ่มเติม'
			end
			navboxArgs['list'..sectionID] = extra
			sectionID = sectionID + 1
		end
		if navboxArgs.list2 then
			navboxArgs.title = '[[วิธีใช้:การควบคุมรายการหลักฐาน|การควบคุมรายการหลักฐาน]]'..pencil
		else
			local sect = navboxArgs.group1
			if sect == 'ทั่วไป' or sect == 'อื่น ๆ' or sect == 'เพิ่มเติม' 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 = '[[วิธีใช้:การควบคุมรายการหลักฐาน|การควบคุมรายการหลักฐาน]]'..pencil
			else 
				navboxArgs.group1 = '[[วิธีใช้:การควบคุมรายการหลักฐาน|การควบคุมรายการหลักฐาน: '..sect..']] '..pencil
			end
		end
		outString = Navbox._navbox(navboxArgs)
	end
	
	--auxCats
	if rct == 0 or rct >= 25 then
		if namespace == 0 or testcases then
			local eCat = 'การควบคุมรายการหลักฐานที่มีส่วนประกอบ '..rct..' รายการ'
			elementsCat = addCat(eCat)
		end
	end
	if parentArgs.state then
		if namespace == 0 or testcases then
			local sCat
			if parentArgs.state == 'collapsed' then sCat = 'การควบคุมรายการหลักฐานใช้พารามิเตอร์สถานะ: ยุบ'
			elseif parentArgs.state == 'expanded' then sCat = 'การควบคุมรายการหลักฐานใช้พารามิเตอร์สถานะ: ขยาย'
			elseif parentArgs.state == 'autocollapse' then sCat = 'การควบคุมรายการหลักฐานใช้พารามิเตอร์สถานะ: ยุบอัตโนมัติ'
			else sCat = 'การควบคุมรายการหลักฐานใช้พารามิเตอร์สถานะ: อื่น ๆ'
			end
			stateCat = addCat(sCat)
		end
	end
	local auxCats = worldcatCat..elementsCat..multipleIdCat..suppressedIdCat..suppressedIdCatArts..
					deprecatedIdCat..differentOnWDCat..sameOnWDCat..stateCat
	if testcases then
		auxCats = mw.ustring.gsub(auxCats, '(%[%[)(หมวดหมู่)', '%1:%2') --for easier checking
	end
	
	--out
	outString = outString..auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(หมวดหมู่:บทความ)', '%1:%2') --by definition
	end
	
	return outString
end

return p