モジュール:Authority control

半永久的に保護されているモジュール
モジュールの解説[表示] [編集] [履歴] [キャッシュを破棄]

{{Normdaten}}のコードを生成しているモジュールです。

引数、関連ウィキデータプロパティと追跡カテゴリ

識別子 グループ 表示名 ウィキデータのプロパティ 追跡カテゴリのページ数
記事 利用者ページ その他のページ 誤った識別子
AAG 美術館と博物館 オークランド P3372: オークランド美術館芸術家ID 508 0 1 0
ACM-DL 科学データベース 計算機協会 P864: ACM電子図書館著者識別子 271 0 1 0
ADB 人名辞典 オーストラリア P1907: オーストラリア人名辞典ID 324 0 1 7
AGSA 美術館と博物館 南オーストラリア P6804: 南オーストラリア美術館芸術家ID 569 0 1 0
autores.uy 人名辞典 ウルグアイ P2558: autores.uy ID 48 0 1 0
AWR 人名辞典 Australian Women's Register P4186: Australian Women's Register ID 119 0 1 0
BIBSYS 国立図書館 ノルウェー P1015: BIBSYS識別子 23,832 0 1 0
Bildindex 美術研究組織 Bildindex(ドイツ) P2092 34 0 1 0
BNC 国立図書館 チリ P1890: チリ書誌典拠収集目録識別子 2,242 0 1 0
BNE 国立図書館 スペイン P950: スペイン国立図書館識別子 32,127 0 1 0
BNF 国立図書館 フランス (データ) P268: フランス国立図書館識別子 78,629 1 1 1
Botanist 科学データベース International Plant Names Index P428: 植物学者の短縮名 1,610 0 1 0
BPN 人名辞典 オランダ P651 1,183 0 1 0
CANTIC 国立図書館 カタルーニャ P1273: CANTIC識別子(旧) 11,321 0 1 0
CINII 科学データベース CiNii(日本) P271: CiNii Books著者ID 36,168 0 8 0
CWGC その他 コモンウェルス戦争墓地委員会 P1908: CWGC人物識別子 56 0 1 0
DAAO 美術研究組織 オーストラリアのアーティスト P1707 91 0 1 0
DBLP 科学データベース DBLP(コンピュータ科学) P2456: DBLP著者識別子 931 0 1 0
DIB 人名辞典 アイルランド P6829 0 0 0 613
DSI 美術研究組織 科学画家 P2349: シュトゥットガルト科学イラストレーター・データベースID 848 0 1 0
FAST その他 Faceted Application of Subject Terminology P2163: FAST識別子 61,147 0 1 0
FNZA 美術研究組織 ニュージーランドのアーティスト P6792 64 0 1 0
GND 全般 統合典拠ファイル(ドイツ) P227: GND識別子 122,153 2 25 0
HDS その他 スイス歴史辞典 P902: スイス歴史事典識別子 2,725 0 1 0
IAAF その他 ワールドアスレティックス P1146: IAAF ID 2,629 0 1 0
ICCU 国立図書館 イタリア P396: イタリア国立図書館サービス著者識別子 0 0 0 9,244
ICIA 美術研究組織 ICIA(イスラエル) P1736 19 0 1 0
IEU その他 ウクライナ・インターネット百科事典 P9070: ウクライナ・インターネット百科事典識別子 365 0 1 0
ISNI 全般 ISNI P213: ISNI 132,593 1 9 0
Joconde 美術研究組織 Joconde(フランス) P347: Joconde 94 0 1 0
KULTURNAV 美術研究組織 KulturNav(ノルウェー) P1248 1,427 0 1 0
LCCN 国立図書館 アメリカ P244: アメリカ議会図書館典拠管理識別子 172,144 2 16 1
LIR その他 Lexicon Istoric Retic(スイス) P886: Lexicon istoric retic識別子 44 0 1 0
LNB 国立図書館 ラトビア P1368: LNB識別子 10,980 0 1 0
Léonore その他 Léonore(フランス) P640: Léonore ID 339 0 0 899
MA その他 マイクロソフト・アカデミック P6366: Microsoft Academic識別子 20,667 0 0 3
MBA その他 MusicBrainz アーティスト P434: MusicBrainzアーティスト識別子 42,430 0 2 0
MBAREA その他 MusicBrainz 地域 P982: MusicBrainz地域ID 14,320 0 1 0
MBI その他 MusicBrainz 楽器 P1330: MusicBrainz楽器ID 418 0 1 0
MBL その他 MusicBrainz レーベル P966: MusicBrainzレーベルID 1,418 0 1 0
MBP その他 MusicBrainz 場所 P1004: MusicBrainz 場所 ID 2,000 0 1 0
MBRG その他 MusicBrainz リリース・グループ P436: MusicBrainzリリース・グループID 21,710 0 1 0
MBS その他 MusicBrainz シリーズ P1407: MusicBrainzシリーズID 373 0 1 0
MBW その他 MusicBrainz 作品 P435: MusicBrainz作品ID 8,024 0 1 0
MGP 科学データベース Mathematics Genealogy Project P549: Mathematics Genealogy Project ID 2,410 0 1 0
NARA その他 公文書館(アメリカ) P1225: アメリカ国立公文書記録管理局識別子 11,224 0 1 0
NCL 国立図書館 台湾 P1048: 国家図書館識別子 306 0 1 0
NDL 国立図書館 日本 P349: 国立国会図書館典拠ID 111,517 0 15 0
NGV 美術館と博物館 ヴィクトリア P2041: ビクトリア国立美術館芸術家ID 1,018 0 1 0
NKC 国立図書館 チェコ P691: チェコ国立図書館識別子 60,477 0 1 0
NLA 国立図書館 オーストラリア P409: オーストラリア図書館識別子 17,346 0 2 0
NLG 国立図書館 ギリシャ P3348: ギリシャ国立図書館識別子 7,432 0 1 0
NLI 国立図書館 イスラエル P949: イスラエル国立図書館識別子 (旧) 15,949 0 1 0
NLK 国立図書館 韓国 P5034: 韓国国立中央図書館識別子 28,709 0 1 1
NLP 国立図書館 ポーランド P1695: ポーランド国立図書館識別子(旧) 226 0 0 0
NLR 国立図書館 ルーマニア P1003: ルーマニア国立図書館識別子 117 0 1 0
NSK 国立図書館 クロアチア P1375: NSK識別子 6,532 0 1 0
NTA 国立図書館 オランダ P1006: NTA PPN識別子 49,876 0 1 0
ORCID 全般 ORCID P496: ORCID 1,048 2 2 0
PIC 美術研究組織 Photographers' Identities P2750: 写真家識別目録識別子 1,508 0 1 0
PLWABN 国立図書館 ポーランド P7293: ポーランド国立図書館識別子 36,800 0 1 0
Publons 科学データベース Publons(研究者) P3829: Publons著者識別子 117 0 1 0
RID 科学データベース ResearcherID P1053: ResearcherID 169 1 1 0
RISM その他 RISM(フランス) P5504 4,120 0 1 0
RERO その他 RERO(スイス) P3065: 西スイス図書館ネットワーク識別子 13,041 0 1 0
RKDartists 美術研究組織 RKDアーティスト(オランダ) P650: RKDartists識別子 6,407 0 1 0
RKDID 美術研究組織 RKD ID(オランダ) P350: RKDimages 135 0 1 0
RSL 国立図書館 ロシア P947: ロシア国立図書館 (モスクワ)人物識別子 504 0 1 0
SELIBR 国立図書館 スウェーデン P906: SELIBR識別子 13,251 0 3 0
SIKART 美術研究組織 SIKART(スイス) P781 175 0 1 0
SNAC-ID その他 Social Networks and Archival Context P3430: SNAC ARK識別子 29,100 0 1 0
SUDOC その他 SUDOC(フランス) P269: IdRef識別子 68,982 0 2 1
S2AuthorId 科学データベース Semantic Scholar P4012 256 0 0 0
TA98 科学データベース Terminologia Anatomica P1323: Terminologia Anatomica 98 1,024 0 1 0
TDVİA その他 イスラーム百科事典(トルコ) P7314 1,191 0 1 0
TePapa 美術館と博物館 Te Papa(ニュージーランド) P3544: テ・パパ代理識別子 1,000 0 1 0
TLS その他 Theaterlexikon(スイス) P1362 152 0 1 0
Trove その他 Trove(オーストラリア) P1315: NLAトローヴ人物識別子 19,357 0 1 0
UKPARL その他 英議会 P6213: イギリス議会識別子 258 0 1 0
ULAN 美術研究組織 アーティスト名(ゲティ) P245: ULAN 9,620 0 1 0
USCongress その他 米議会 P1157: アメリカ国会識別子 1,033 0 1 0
VcBA 国立図書館 バチカン P8034: バチカン図書館VcBA識別子 10,415 0 1 0
VIAF 全般 VIAF P214: VIAF識別子 238,847 2 50 1
WORLDCATID 全般 WorldCat P7859: WorldCat識別識別子 206,475 0 0 0
全般 WorldCat(アメリカ議会図書館経由) 1,570
全般 WorldCat(VIAF経由) 32,562

その他の追跡カテゴリ

上記のほか、このモジュールは下記の追跡カテゴリも追加します。

require('Module:No globals')

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

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

function p.getCatForId( id )
	local catName = ''
	if namespace == 0 then
		catName = id..'識別子が指定されている記事'
	elseif namespace == 2 and not title.isSubpage then
		catName = id..'識別子が指定されている利用者ページ'
	else
		catName = id..'識別子が指定されているその他のページ'
	end
	return '[[Category:'..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 '[[Category:赤リンクの典拠情報カテゴリがあるページ]]'
	end
	return ''
end

function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix )
	local catName = '誤った'..(specialCat or id)..'識別子が指定されている記事'
	if links then -- all links[] use withUid = false; no check needed
		local row = ''
		if prefix then
			row = row .. '*' .. prefix
		end
		local totlen = 0
		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>[[Category:'..catName..']]'..p.redCatLink(catName)
			end
		end
		return row..'\n'
	elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed
		if withUid then
			return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n'
		end
		return '*<span class="nowrap">'..link..'</span>\n'
	end

	return '* <span class="error">'..id..'識別子の値'..rawValues..'は正しくありません。</span>[[Category:'..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 'オークランド')..']'..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-2]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71)
	if not id:match( '^[a-z][-a-z]+-[1-2]%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.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.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(ドイツ)')..']'..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.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.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(日本)')..']'..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 'コモンウェルス戦争墓地委員会')..']'..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 'オーストラリアのアーティスト')..']'..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(コンピュータ科学)')..']'..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 'アイルランド')..']'..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 '科学画家')..']'..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 'ニュージーランドのアーティスト')..']'..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.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 'スイス歴史辞典')..']'..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: 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 'イタリア')..']'..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(イスラエル)')..']'..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 'ウクライナ・インターネット百科事典')..']'..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(フランス)')..']'..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(ノルウェー)')..']'..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(スイス)')..']'..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.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(フランス)')..']'..p.getCatForId( 'Léonore' ) --no https as of 9/2019
end

function p.maLink( id, label )
	--P6366's format regex: [1-9]\d{4,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 'マイクロソフト・アカデミック')..']'..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 (識別子)|MusicBrainz]] [' .. 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地域' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBAREA (識別子)|MusicBrainz]] [' .. 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楽器' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBI (識別子)|MusicBrainz]] [' .. 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レーベル' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBL (識別子)|MusicBrainz]] [' .. 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場所' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBP (識別子)|MusicBrainz]] [' .. 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リリース・グループ' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBRG (識別子)|MusicBrainz]] [' .. 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シリーズ' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBS (識別子)|MusicBrainz]] [' .. 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作品' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat
	else
		return '[[MBW (識別子)|MusicBrainz]] [' .. 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://genealogy.math.ndsu.nodak.edu/id.php?id='..id..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' )
end

function p.naraLink( id, label )
	--P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://catalog.archives.gov/id/'..id..' '..(label or '公文書館(アメリカ)')..']'..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.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.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 'イスラエル')..']'..p.getCatForId( 'NLI' )
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(研究者)')..']'..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(フランス)')..']'..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(スイス)')..']'..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アーティスト(オランダ)')..']'..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(オランダ)')..']'..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.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(スイス)')..']'..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(フランス)')..']'..p.getCatForId( 'SUDOC' )
end

function p.s2authoridLink( id, label )
	--P4012's format regex: [1-9]\d* (e.g. 1796130)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.semanticscholar.org/author/'..id..' '..(label or 'Semantic Scholar')..']'..p.getCatForId( 'Semantic Scholar著者' ) --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 'イスラーム百科事典(トルコ)')..']'..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(ニュージーランド)')..']'..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(スイス)')..']'..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(オーストラリア)')..']'..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 'アーティスト名(ゲティ)')..']'..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 '米議会')..']'..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), 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 | 識別子\n'..
					  '! rowspan=2 | グループ\n'..
					  '! rowspan=2 | 表示名\n'..
					  '! rowspan=2; data-sort-type=number | ウィキデータのプロパティ\n'..
					  '! colspan=4 | 追跡カテゴリのページ数\n'..
					  '|-\n'..
					  '! [[:Category:典拠管理情報がある記事|'..                '記事]]\n'..
					  '! [[:Category:典拠管理情報がある利用者ページ|'..        '利用者ページ]]\n'..
					  '! [[:Category:典拠管理情報があるその他のページ|'..      'その他のページ]]\n'..
					  '! [[:Category:誤った典拠管理情報が指定されている記事|'..'誤った識別子]]\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 .. ' (識別子)'
		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 userCat =    category..'識別子が指定されている利用者ページ'
		local miscCat =    category..'識別子が指定されているその他のページ'
		local faultyCat =  '誤った'..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;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|[[:Category:'..   userCat..'|'..   userCount..']]'..
					'||style="text-align: right;"|[[:Category:'..   miscCat..'|'..   miscCount..']]'..
					'||style="text-align: right;"|[[:Category:'.. faultyCat..'|'.. faultyCount..']]'
	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 WorldCat(アメリカ議会図書館経由)]"
		else
			appearsAs = "[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat(VIAF経由)]"
		end
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||'..'—'..
					'||全般'..
					'||'..appearsAs..
					'||data-sort-value='..w..'|'..'—'..
					'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'
	end
	
	return require("Module:Suppress categories").main(wikiTable)..'\n|}'
end

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

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


-- Parameter format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation }
-- Optional named parameters: `link` to override the link in the documentation (defaults to parameter + (identifer)),
-- category to override the ID in category names (defaults to parameter),
-- prefix to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself
p.conf = {
	{ 'AAG', 3372, p.aagLink, "美術館と博物館", "1", link = ":en:AAG (identifier)"},
	{ 'ACM-DL', 864, p.acmLink, "科学データベース", "12345678901", link="ACM DL (識別子)"},
	{ 'ADB', 1907, p.adbLink, "人名辞典", "barton-sir-edmund-toby-71", link = ":en:ADB (identifier)"},
	{ 'AGSA', 6804, p.agsaLink, "美術館と博物館", "3625"},
	{ 'autores.uy', 2558, p.autoresuyLink, "人名辞典", "12345"},
	{ 'AWR', 4186, p.awrLink, "人名辞典", "PR00768b", link = ":en:AWR (identifier)"},
	{ 'BIBSYS', 1015, p.bibsysLink, "国立図書館", "1234567890123", link = ":en:BIBSYS (identifier)"},
	{ 'Bildindex', 2092, p.bildLink, "美術研究組織", "1", link = ":en:Bildindex (identifier)"},
	{ 'BNC', 1890, p.bncLink, "国立図書館", "123456789", link = ":en:BNC (identifier)"},
	{ 'BNE', 950, p.bneLink, "国立図書館", "XX1234567"},
	{ 'BNF', 268, p.bnfLink, "国立図書館", "123456789"},
	{ 'Botanist', 428, p.botanistLink , "科学データベース", "L."},
	{ 'BPN', 651, p.bpnLink , "人名辞典", "12345678", link = ":en:BPN (identifier)"},
	{ 'CANTIC', 1273, p.canticLink, "国立図書館", "a12345678", link = ":en:CANTIC (identifier)"},
	{ 'CINII', 271, p.ciniiLink, "科学データベース", "DA12345678", link = "CiNii (識別子)"},
	{ 'CWGC', 1908, p.cwgcLink, "その他", "1234567"},
	{ 'DAAO', 1707, p.daaoLink, "美術研究組織", "rolf-harris", link = ":en:DAAO (identifier)"},
	{ 'DBLP', 2456, p.dblpLink, "科学データベース", "123/123"},
	{ 'DIB',  6829, p.dibLink, "人名辞典", "a1234", link = ":en:DIB (identifier)"},
	{ 'DSI', 2349, p.dsiLink, "美術研究組織", "1538", link = ":en:DSI (identifier)"},
	{ 'FAST', 2163, p.fastLink, "その他", "1", link = ":en:FAST (identifier)"},
	{ 'FNZA', 6792, p.fnzaLink, "美術研究組織", "12", link = ":en:FNZA (identifier)"},
	{ 'GND', 227, p.gndLink, "全般", "4079154-3"},
	{ 'HDS', 902, p.hdsLink, "その他", "050123"},
	{ 'IAAF', 1146, p.iaafLink, "その他", "123"},
	{ 'ICCU', 396, p.iccuLink, "国立図書館", "IT\\ICCU\\CFIV\\000163", link = ":en:ICCU (identifier)"}, --formerly SBN
	{ 'ICIA', 1736, p.iciaLink, "美術研究組織", "1", link = ":en:ICIA (identifier)"},
	{ 'IEU', 9070, p.ieuLink, "その他", "N\\A\\NationalAcademyofArtandArchitecture", link = ":en:IEU (identifier)"},
	{ 'ISNI', 213, p.isniLink, "全般", "0000-0000-6653-4145", prefix = '[[ISNI (識別子)|ISNI]]'},
	{ 'Joconde', 347, p.jocondeLink, "美術研究組織", "12345678901", link = ":en:Joconde (identifier)"},
	{ 'KULTURNAV', 1248, p.kulturnavLink, "美術研究組織", "12345678-1234-1234-1234-1234567890AB", link=":en:KulturNav (identifier)"},
	{ 'LCCN', 244, p.lccnLink, "国立図書館", "n78039510"},
	{ 'LIR', 886, p.lirLink, "その他", "1"},
	{ 'LNB', 1368, p.lnbLink, "国立図書館", "123456789", link = ":en:LNB (identifier)"},
	{ 'Léonore', 640, p.leonoreLink, "その他", "LH/1/1", prefix = "[[:en:Léonore (identifier)|Léonore(フランス)]]"},
	{ 'MA', 6366, p.maLink, "その他", "123456789", link = ":en:MA (identifier)"},
	{ '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地域' }, --special cat name
	{ 'MBI', 1330, p.mbiLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz楽器' }, --special cat name
	{ 'MBL', 966, p.mblLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainzレーベル' }, --special cat name
	{ 'MBP', 1004, p.mbpLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz場所' }, --special cat name
	{ 'MBRG', 436, p.mbrgLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainzリリース・グループ' }, --special cat name
	{ 'MBS', 1407, p.mbsLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainzシリーズ' }, --special cat name
	{ 'MBW',  435, p.mbwLink, "その他", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz作品' }, --special cat name
	{ 'MGP', 549, p.mgpLink, "科学データベース", "123456"},
	{ 'NARA', 1225, p.naraLink, "その他", "12345678"},
	{ 'NCL', 1048, p.nclLink, "国立図書館", "1081436"},
	{ 'NDL', 349, p.ndlLink, "国立図書館", "012345678"},
	{ 'NGV', 2041, p.ngvLink, "美術館と博物館", "12354"},
	{ 'NKC', 691, p.nkcLink, "国立図書館", "abcd12345678901234", link = ":en:NKC (identifier)"},
	{ 'NLA', 409, p.nlaLink, "国立図書館", "123456789012"},
	{ 'NLG', 3348, p.nlgLink, "国立図書館", "12345678", link = ":en:NLG (identifier)"},
	{ 'NLI', 949, p.nliLink, "国立図書館", "123456789"},
	{ 'NLK', 5034, p.nlkLink, "国立図書館", "KAB197000000"},
	{ 'NLP', 1695, p.nlpLink, "国立図書館", "9810123456789012345"},
	{ 'NLR', 1003, p.nlrLink, "国立図書館", "123456789"},
	{ 'NSK', 1375, p.nskLink, "国立図書館", "123456789", link = ":en:NSK (identifier)"},
	{ 'NTA', 1006, p.ntaLink, "国立図書館", "12345678X", link = ":en:NTA (identifier)"},
	{ 'ORCID', 496, p.orcidLink, "全般", "0000-0002-7398-5483", prefix = '[[ORCID (識別子)|ORCID]]'},
	{ 'PIC', 2750, p.picLink, "美術研究組織", "1", link = ":en:PIC (identifier)"},
	{ 'PLWABN',  7293, p.plwabnLink, "国立図書館", "9812345678905606"},
	{ 'Publons', 3829, p.publonsLink, "科学データベース", "2776255", link = ":en:Publons (identifier)"},
	{ 'RID', 1053, p.ridLink, "科学データベース", "A-1234-1934"},
	{ 'RISM', 5504, p.rismLink, "その他", "pe1",  prefix = '[[:en:RISM (identifier)|RISM(フランス)]]'},
	{ 'RERO', 3065, p.reroLink, "その他", "02-A012345678", prefix = '[[:en:RERO (identifier)|RERO(スイス)]]'},
	{ 'RKDartists', 650, p.rkdartistsLink, "美術研究組織", "123456"},
	{ 'RKDID', 350, p.rkdidLink, "美術研究組織", "123456"},
	{ 'RSL', 947, p.rslLink, "国立図書館", "123456789"},
	{ 'SELIBR', 906, p.selibrLink, "国立図書館", "123456", link = ":en:SELIBR (identifier)"},
	{ 'SIKART', 781, p.sikartLink, "美術研究組織", '123456789', link = ":en:SIKART (identifier)"},
	{ 'SNAC-ID', 3430, p.snacLink, "その他", "A"},
	{ 'SUDOC', 269, p.sudocLink, "その他", "026927608", prefix = '[[SUDOC (識別子)|SUDOC(フランス)]]'},
	{ 'S2AuthorId', 4012, p.s2authoridLink, "科学データベース", "1796130", category = 'Semantic Scholar著者', link = ":en:S2AuthorId (identifier)" }, --special cat name
	{ 'TA98', 1323, p.ta98Link, "科学データベース", "A12.3.45.678", link = ":en:TA98 (identifier)"},
	{ 'TDVİA', 7314, p.tdviaLink, "その他", "asim-b-behdele", link = ":en:TDVİA (identifier)"},
	{ 'TePapa', 3544, p.tepapaLink, "美術館と博物館", "1"},
	{ 'TLS',  1362, p.tlsLink, "その他", "Abcd", link = ":en:TLS (identifier)"},
	{ 'Trove', 1315, p.troveLink, "その他", "12345678", prefix = '[[:en:Trove (identifier)|Trove(オーストラリア)]]'}, --formerly NLA-person
	{ 'UKPARL', 6213, p.ukparlLink, "その他", "AQUupyiR"},
	{ 'ULAN', 245, p.ulanLink, "美術研究組織", "500123456", link = ":en:ULAN (identifier)"},
	{ 'USCongress', 1157, p.uscongressLink, "その他", "A000123", link = ":en:US Congress (identifier)"},
	{ 'VcBA', 8034, p.vcbaLink, "国立図書館", "494/9793"},
	{ 'VIAF', 214, p.viafLink, "全般", "123456789", prefix = "[[VIAF (識別子)|VIAF]]"},
	{ 'WORLDCATID', 7859, nil, "全般", nil, link = "WorldCat Identities (識別子)"},
}

-- 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( "Module:ResolveEntityId" )
	local parentArgs = frame:getParent().args --WD IDs added here later
	local iParentArgs = 0 --count original/manual parent args only later
	local worldcatCat = ''
	local multipleIdCat = ''
	local suppressedIdCat = ''
	local deprecatedIdCat = ''
	local differentOnWDCat = ''
	local sameOnWDCat = ''
	
	--Redirect aliases to proper parameter names
	for _, a in pairs( p.aliases ) do
		local alias, param = a[1], a[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then
			parentArgs[param] = parentArgs[alias]
		end
	end
	
	--Redirect deprecated parameters to proper parameter names, and assign tracking cat
	for _, d in pairs( p.deprecated ) do
		local dep, param = d[1], d[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then
			parentArgs[param] = parentArgs[dep]
			if namespace == 0 then
				deprecatedIdCat = '[[Category:非推奨の典拠管理識別子が指定されている記事|'..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 = '[[Category:抑制された典拠管理識別子がある記事|'..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 = '[[Category:ウィキデータと異なる典拠管理識別子をパラメータで指定しているページ|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[Category:ウィキデータと同じ典拠管理識別子をパラメータで指定しているページ]]'
		end
	end
	--Configured rows
	local rct = 0
	local sectionOrder = {"全般","国立図書館","美術館と博物館",
						"美術研究組織","人名辞典","科学データベース",
						"その他"}
	local sections = {
		["全般"] = {},
		["国立図書館"] = {},
		["美術館と博物館"] = {},
		["美術研究組織"] = {},
		["人名辞典"] = {},
		["科学データベース"] = {},
		["その他"] = {}
	}
	-- 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( 'multiple' )					-- 日本語版でのカテゴリ導入は様子を見てから
			end
		end
	end
	
	--WorldCat
	local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
	if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
		table.insert( sections["全般"], 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["全般"], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat(VIAF経由)]', nil, false ) )
			if namespace == 0 then
				worldcatCat = '[[Category: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..' WorldCat(アメリカ国会図書館経由)]', nil, false ) )
				if namespace == 0 then 
					worldcatCat = '[[Category:WorldCat-LCCN識別子が指定されている記事]]'
				end
			end
			rct = rct + 1
		end
	elseif worldcatId == '' then --if WORLDCATID suppressed
		suppressedIdCat = '[[Category:抑制された典拠管理識別子がある記事|WORLDCATID]]'
	end
	
	local Navbox = require('Module:Navbox')
	local elementsCat = ''
	if rct == 0 or rct >= 25 then
		local eCat = rct..'種類以上の識別子があるページ'
		--elementsCat  = '[[Category:'..eCat..']]'..p.redCatLink(eCat)
		elementsCat  = '' --25種類以上の識別子が指定された場合、追跡カテゴリをつけるという機能は日本語版では導入されていない
	end
	
	local outString = ''
	if rct > 0 then
		local sectionID = 1
		local args = { pid = 'identifiers' } -- #target the list of identifiers
		if testcases and itemId then args = { pid = 'identifiers', qid = itemId } end --expensive
		local pencil = frame:expandTemplate{ title = 'EditAtWikidata', args = args}
		local navboxArgs = {
			name  = 'Normdaten',
			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 = "[[Help:典拠管理|典拠管理]]" .. pencil
		else
			local sect = navboxArgs.group1
			if 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 = "[[Help:典拠管理|典拠管理]]" .. pencil
			else
				navboxArgs.group1 = "[[Help:典拠管理|典拠管理:" .. 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, '(%[%[)(Category)', '%1:%2') --for easier checking
	end
	outString = outString .. auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(Category:[^%]]*記事)', '%1:%2') --by definition
	end
	
	return outString
end

return p