Module:Authority control
This Lua module is used on approximately 2,010,000 pages, or roughly 14060% of all pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
Related pages |
---|
This module uses one or more Wikidata properties; see § Parameters for details.
This module depends on the following other modules: |
This module contains the code of the {{Authority control}} template. See its documentation.
Parameters, Wikidata properties, and tracking categories
Script error: The function "docConfTable" does not exist.
Additional tracking categories
This module also implements the following hidden tracking categories:
- Category:Pages with red-linked authority control categories (0) – error category to identify missing categories
- Category:Articles with deprecated authority control identifiers (0) – fix/migrate/remove deprecated IDs
- Category:Articles with suppressed authority control identifiers (0) – tracking only (no error)
- Category:Articles with multiple identifiers (0) – tracking only (no error)
- Category:Pages using authority control with parameters (2) – migrate IDs to Wikidata, if possible (no error)
- Category:Pages using authority control with parameters different on Wikidata (0) – determine/remove incorrect IDs & migrate to Wikidata
- Category:Pages using authority control with parameters all matching Wikidata (0) – template parameters may safely be removed
Number of identifiers
- Category:AC with 0 elements (0)
- Category:AC with 25 elements (0)
- Category:AC with 26 elements (0)
- Category:AC with 27 elements (0)
- Category:AC with 28 elements (0)
- Category:AC with 29 elements (0)
- Category:AC with 30 elements (0)
- Category:AC with 31 elements (0)
- Category:AC with 32 elements (0)
- Category:AC with 33 elements (0)
- Category:AC with 34 elements (0)
- Category:AC with 35 elements (0)
- Category:AC with 36 elements (0)
- Category:AC with 37 elements (0)
- Category:AC with 38 elements (0)
- Category:AC with 39 elements (0)
- Category:AC with 40 elements (0)
- Category:AC with 41 elements (0)
- Category:AC with 42 elements (0)
- Category:AC with 43 elements (0)
- Category:AC with 44 elements (0)
- Category:AC with 45 elements (0)
State parameter
- Category:AC using state parameter: collapsed (0)
- Category:AC using state parameter: expanded (0)
- Category:AC using state parameter: autocollapse (0)
- Category:AC using state parameter: other (0)
See also
- m:Interwiki map – definition of global custom interwiki prefixes
--[[ __ __ _ _ _ _ _ _ _ _ _ | \/ | ___ __| |_ _| | ___ _ / \ _ _| |_| |__ ___ _ __(_) |_ _ _ ___ ___ _ __ | |_ _ __ ___ | | | |\/| |/ _ \ / _` | | | | |/ _ (_) / _ \| | | | __| '_ \ / _ \| '__| | __| | | | / __/ _ \| '_ \| __| '__/ _ \| | | | | | (_) | (_| | |_| | | __/_ / ___ \ |_| | |_| | | | (_) | | | | |_| |_| | | (_| (_) | | | | |_| | | (_) | | |_| |_|\___/ \__,_|\__,_|_|\___(_)_/ \_\__,_|\__|_| |_|\___/|_| |_|\__|\__, | \___\___/|_| |_|\__|_| \___/|_| |___/ This module is intended to be the engine behind "Template:Authority control". Please do not modify this code without applying the changes first at "Module:Authority control/sandbox" and testing at "Module:Authority control/testcases". Authors and maintainers: * User:Jarekt - original version ]] local properties = require('Module:Authority control/conf') local core = require('Module:Core') -- ================================================== -- === Internal functions =========================== -- ================================================== local function getSitelink(item, lang) -- get item's siteling in specific language local langList = mw.language.getFallbacksFor(lang) table.insert(langList, 1, lang) for _, language in ipairs(langList) do local sitelink = mw.wikibase.sitelink( item, language .. 'wiki' ) if sitelink then return 'w:'.. language ..':'.. sitelink end end return nil end -- ================================================== local function getIdentifierNameLink( lang, item1, item2, label ) -- Identifier names, like VIAF, LCCN, ISNI, need to be linked to the articles about them if possible -- Alternativly they can be linked to the articles for institutions that issue them local id_name_URL = nil -- 1) try wikipedia sitelink for the identifier in users language and in English if item1 and item1 ~='' then id_name_URL = getSitelink(item1, lang) end -- 2) try wikipedia sitelink for the issuedBy property in users language and in English if id_name_URL==nil and item2 and item2 ~='' then -- if no link than id_name_URL = getSitelink(item2, lang) end -- 3) if still no links than link to wikidata if id_name_URL then return string.format("[[%s|%s]]", id_name_URL, label) -- link to wikipedia else return string.format("[[d:%s|%s]]", item1, label) -- link to wikidata end end -- ================================================== -- Create link to a single identifier -- INPUTS: -- * val - value of the identifier -- * URL_format - string used to create URL -- * params - additional parameters related to this type of identifiers. Single item from "conf" -- * color - color of the link local function getIdentifierValLink(val, URL_format, params, color) if not val or val=='' then return '' end -- check if identifier is in the right format local mismatchStr = '' local val_ = val:gsub( ' ', '' ) -- remove spaces if (params.regexp and not val:match( params.regexp )) then mismatchStr = string.format("<span style=\"color:red\">[does not match %s pattern]</span>", params.regexp) elseif (params.verify) then -- check if special "Verify" function is present mismatchStr = params.verify(val_) -- add error message if any end -- identifier_value_URL local val_URL = URL_format:gsub('$1', val_)-- URL part of the link for the identifier value if color~="blue" then val = string.format('<span style=\"color:%s\">%s</span>', color, val) end return string.format("<span class=\"plainlinks\">[%s %s]</span>%s", val_URL, val, mismatchStr) -- link to the identifier's external website end -- ================================================== -- Convert between 2 formats of LCCN: "n/79/63767" -> "n79063767" -- "n/79/63767" format was used as input by {{Authority Control}} templates -- "n79063767" format is used by wikidata local function fixLCCN(id) if id then local a, b, c = string.match(id, "([%a%d]*)/([%a%d]*)/([%a%d]*)") if c then local pad = 6 - string.len(c) if pad > 0 then c = string.rep("0", pad)..c end id = a..b..c end end return id end -- fixLCCN -- ================================================== -- Verify last "check" digit is correct. ISNI and several other -- identifiers use last digit as a verification digit local function verifyLastDigit( id ) local total = 0 for i = 1, #id-1 do local digit = id:byte( i ) - 48 --Get integer value total = (total + digit) * 2 end --local remainder = total % 11 local lastDigit = tostring((12 - total % 11) % 11) if lastDigit == '10' then lastDigit = "X" end if (lastDigit == string.sub( id, -1)) then return '' else return "<span style=\"color:red\">[last digit should be " .. lastDigit .. "]</span>" end end -- ================================================== -- === Settings ===================================== -- ================================================== -- In order to add a new identifier associated with Wikidata property do the following -- 1) go to [[Template:Authority control/IdentifierList]] and verify that the property number is on the list, if not than edit the page to add it -- 2) copy code generated at [[Template:Authority control/IdentifierList]] to protected [[Module:Authority control/conf]] -- 3) add the property to the "conf" list below -- load 'Module:Authority control/conf' which holds hardwired data derived from Wikidata's properties of -- properties --conf holds list of identifiers to be displayed local conf = { -- people {label='VIAF' , property='P214' , lang='' , regexp='^%d+$' }, {label='ISNI' , property='P213' , lang='' , regexp='^%d%d%d%d %d%d%d%d %d%d%d%d %d%d%d[%dX]$', verify=verifyLastDigit }, {label='ORCID' , property='P496' , lang='' , regexp='^0000%-000[1-3]%-%d%d%d%d%-%d%d%d[%dX]$' }, {label='ULAN' , property='P245' , lang='' , regexp='^500%d%d%d%d%d%d$' }, -- 'Union List of Artist Names' by Getty Research Institute {label='ResearcherID', property='P1053', lang='' , regexp='^[A-Z]{1,3}-\d{4}-(19|20)\d\d$' }, {label='LCCN' , property='P244' , lang='en', regexp='^[ns][broshj]?%d%d%d%d%d%d%d%d%d?%d?$' }, -- Library of Congress Authorities {label='GND' , property='P227' , lang='de', regexp='^[%dX%-]+$'}, {label='SELIBR' , property='P906' , lang='se', regexp='^%d+$' }, -- National Library of Sweden {label='SUDOC' , property='P269' , lang='fr', regexp='^%d%d%d%d%d%d%d%d[%dxX]$' }, {label='BNF' , property='P268' , lang='fr', regexp='^%d+%w?$' }, -- Bibliothèque nationale de France {label='BPN' , property='P651' , lang='nl', regexp='^%d%d%d%d%d%d%d%d$' }, -- Biografisch Portaal number {label='NAID' , property='P1225', lang='en', regexp='^%d+$' }, -- NARA ID (redirect for US National Archives Identifier (P1225)) {label='Museofile' , property='P539' , lang='fr', regexp='^M%d%d%d%d%-?%d?%d?$' }, --Ministry of Culture (France) {label='NDL' , property='P349' , lang='ja', regexp='^0?%d%d%d%d%d%d%d%d$' }, -- National Diet Library (of Japan) {label='NLA' , property='P409' , lang='en', regexp='^[1-9]%d*$' }, -- National Library of Australia {label='BIBSYS' , property='P1015', lang='no', regexp='^%d+$' }, -- Norwegian information system BIBSYS {label='HDS' , property='P902' , lang='de', regexp='^%d%d%d?%d?%d?%d?$' }, -- Historical Dictionary of Switzerland {label='MusicBrainz' , property='P434' , lang='en', regexp='^[-%x]+$' }, {label='MGP' , property='P549' , lang='en', regexp='^%d%d?%d?%d?%d?%d?$' }, -- Mathematics Genealogy Project {label='NCL' , property='P1048', lang='zh', regexp='^%d+$' }, --National Central Library (Taiwan) {label='NKC' , property='P691' , lang='cs', regexp='^%l%l%l?%l?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' }, --National Library of the Czech Republic {label='Léonore' , property='P640' , lang='fr', regexp='^[LHC%/%d]+$' }, {label='SBN' , property='P396' , lang='it'}, -- Istituto Centrale per il Catalogo Unico / National Library Service (SBN) of Italy {label='RSL' , property='P947' , lang='ru', regexp='^%d%d%d%d%d%d%d%d%d$' }, --Russian State Library {label='Botanist' , property='P428' , lang='en' }, {label='US Congress' , property='P1157', lang='en', regexp='^%u00[01]%d%d%d' }, {label='BNE' , property='P950' , lang='es', regexp='' }, --Biblioteca Nacional de España {label='CALIS' , property='P270' , lang='zh'}, --China Academic Library and Information {label='CiNii' , property='P271' , lang='jp', regexp='^DA%d%d%d%d%d%d%d[%dX]$' }, {label='TLS' , property='P1362', lang='de', regexp='' }, -- Theaterlexikon der Schweiz {label='SIKART' , property='P781' , lang='de', regexp='^%d%d%d%d%d%d%d%d?%d?%d?$' }, -- Swiss {label='NLP' , property='P1695', lang='pl', regexp='' }, -- National Library of Poland {label='WGA' , property='P1882', lang='en', regexp='' }, -- Web Gallery of Art {label='KulturNav' , property='P1248', lang='no', regexp='' }, {label='RKD' , property='P650' , lang='nl', regexp='^[1-9]%d%d?%d?%d?%d?$' }, --Netherlands Institute for Art History#Online artist pages {label='autores.uy' , property='P2558', lang='es', regexp='^[1-9]%d?%d?%d?%d?$' }, --autores.uy {label='J9U' , property='P8189', lang='he', regexp='' }, --National Library of Israel J9U ID {label='FIDE' , property='P1440', lang='en', regexp='' }, -- FIDE database for chess players {label='Chess Games' , property='P1665', lang='en', regexp='' }, -- Chess Games {label='ISSN' , property='P236', lang='', regexp='' }, -- P1629: International Standard Serial Number {label='OSM' , property='P402', lang='', regexp='' }, -- P1629: OpenStreetMap {label='Joconde' , property='P347', lang='fr', regexp='' }, -- Joconde ID {label='Rijksmonument',property='P359', lang='nl', regexp='' }, -- Rijksmonument ID {label='IMO' , property='P458', lang='', regexp='' }, --IMO ship number {label='BNCF' , property='P508', lang='it', regexp='' }, -- BNCF Thesaurus ID {label='MMSI' , property='P587', lang='', regexp='' }, -- P1629: Maritime Mobile Service Identity {label='Open Library', property='P648', lang='', regexp='' }, -- P1629: Open Library {label='NRHP' , property='P649', lang='en', regexp='' }, -- NRHP reference number {label='DBNL' , property='P723', lang='', regexp='' }, -- DBNL author ID {label='UNESCO' , property='P757', lang='', regexp='' }, -- World Heritage Site ID {label='BIC' , property='P808', lang='', regexp='' }, -- Bien de Interés Cultural (BIC) code {label='LIR' , property='P886', lang='', regexp='' }, -- LIR {label='BNR' , property='P1003', lang='ro', regexp='' }, -- NLR (Romania) ID {label='Koninklijke' , property='P1006', lang='nl', regexp='' }, -- National Thesaurus for Author Names ID {label='Louvre' , property='P9394', lang='', regexp='' }, -- Louvre ID {label='OCLC' , property='P243', lang='', regexp='' }, -- OCLC {label='ISBN-13' , property='P212', lang='', regexp='' }, -- ISBN-13 {label='ISBN-10' , property='P957', lang='', regexp='' }, -- ISBN-10 {label='Historic England', property='P1216', lang='en', regexp='' }, -- National Heritage List for England number {label='Oxford Dict.', property='P1415', lang='en', regexp='' }, -- Oxford Dictionary of National Biography ID {label='kulturnoe-nasledie', property='P1483', lang='ru', regexp='' }, -- kulturnoe-nasledie.ru ID {label='Catalunya' , property='P1600', lang='ca', regexp='' }, -- Inventari del Patrimoni Arquitectònic de Catalunya code {label='COAM' , property='P2917', lang='es', regexp='' }, -- COAM structure ID {label='SIMBAD' , property='P3083', lang='fr', regexp='' }, -- SIMBAD ID {label='JCyL' , property='P3177', lang='es', regexp='' }, -- Patrimonio Web JCyL ID {label='Zaragoza' , property='P3178', lang='es', regexp='' }, -- Zaragoza monument ID {label='BDI' , property='P3318', lang='es', regexp='' }, -- Patrimonio Inmueble de Andalucía ID {label='SIPCA' , property='P3580', lang='es', regexp='' }, -- SIPCA code {label='DOCOMOMO' , property='P3758', lang='', regexp='' }, -- DOCOMOMO Ibérico ID {label='Czech Monument', property='P4075', lang='cz', regexp='' }, -- Czech Monument Catalogue Number {label='MEG' , property='P4157', lang='ch', regexp='' }, -- P1629: Musée d'ethnographie de Genève {label='Enciclopédia Itaú Cultural' , property='P4399', lang='pt_br', regexp='' }, -- Enciclopédia Itaú Cultural ID {label='Monumentos de São Paulo' , property='P4360', lang='pt_br', regexp='' }, -- Monumentos de São Paulo ID {label='Infopatrimônio' , property='P4372', lang='pt_br', regexp='' }, -- Infopatrimônio ID {label="Musée d'Orsay" , property='P4659', lang='fr' , regexp='' }, -- Musée d'Orsay artwork ID {label='MuBE' , property='P4721', lang='pt_br', regexp='' }, -- MuBE Virtual ID {label='Hispania Nostra' , property='P4868', lang='es' , regexp='' }, -- Hispania Nostra Red List ID {label='NLK' , property='P5034', lang='ko' , regexp='' }, -- National Library of Korea ID } -- ================================================== -- === External functions =========================== -- ================================================== local p = {} function p.getAuthorityControlTag( lang ) -- get a localized interwiki link to article "Authority Control" local field_name = "[[w:en:Help:Authority control|Authority control]]" -- hardwire the default if lang~='en' then field_name = core.getLabel("Q36524", lang) end return field_name end -- ================================================== function p._authorityControl(entity, args, lang, length) -- INPUTS: -- * entity - wikidata entity if already created or nil. If provided than you should still provide args.Wikidata -- * args - structure with identifier fields: args.VIAF, args.LCCN, args.Wikidata, etc. -- * lang - language code -- * length - maximum length of the identifier array, or number of identifiers to display -- OUTPUTS: -- * results - wikicode string equivalent to {{Authority control|...|bare=1 }} call -- * cats - wikicode with maintenance categories -- count custom parameters (not pulled from Wikidata) local nCustomParam = 0 for _,params in ipairs( conf ) do if (args[params.label]~=nil) then nCustomParam = nCustomParam + 1 end end -- Get entity - record of wikidata related to a single item local q = args.wikidata if not entity and q then entity = mw.wikibase.getEntity(q) end -- Check if this is category item local cats = '' -- categories (mismatching and missing) if entity and entity.claims and entity.claims.P31 then for _, statement in pairs( entity.claims.P31) do if (statement.mainsnak.snaktype == "value") and (statement.mainsnak.datavalue.value.id == 'Q4167836') then -- P31 == Wikimedia category cats = '[[Category:Wrong Wikidata ID in authority control data: category item]]' end if (statement.mainsnak.snaktype == "value") and (statement.mainsnak.datavalue.value.id == 'Q4167410') then -- P31 == Wikimedia disambiguation page cats = '[[Category:Wrong Wikidata ID in authority control data: disambiguation item]]' end end end --compare provided arguments with Wikidata identifiers local data = {} -- structure similar to "args" but filled with wikidata data for _,params in ipairs( conf ) do local label = string.lower(params.label) data[label] = nil if entity and entity.claims and params.property and entity.claims[params.property] then -- if we have wikidata item and item has the property -- capture all Wikidata values for the identifier --for _, statement in pairs( entity.claims[params.property]) do for _, statement in pairs( entity:getBestStatements( params.property )) do if (statement.mainsnak.snaktype == "value") then -- or if statement.mainsnak.datavalue then local v = statement.mainsnak.datavalue.value if data[label]==nil then data[label] = v -- save the first value end if args[label] == v then -- match between template and wikidata identifiers data[label] = '' -- ignore identifier from wikidata break end end end end end --Create string with all the identifiers listed local results1 = {} -- high priority list local results2 = {} -- low priority list properties.P214.item = 'Q54919'; -- hardwire link to VIAF local today = '+' .. os.date('!%F') .. 'T00:00:00Z/11' local TransStr = 'https://quickstatements.toolforge.org/#/v1=%s|%s|%%22%s%%22|S143|Q565|S813|'.. today -- QuickStatementts URL TransStr = '<span class=\"plainlinks\" title=\"Click (+) to copy to wikidata\">['.. TransStr .. ' (+)]</span>' for _,params in ipairs( conf ) do local label = string.lower(params.label) local val1 = args[label] -- identifier value provided to the template local val2 = data[label] -- identifier value pulled from wikidata if val1 or val2 then local P = properties[params.property] -- properties of wikidata identifier propertyc -- name_link - link for the identifier name local name_link = getIdentifierNameLink( lang, P.item, P.issuedBy, params.label ) -- val_link - identifier value or values local transfer = '' local val3 = string.gsub(val1 or '', ' ', '' ) -- remove spaces local val_link if not val1 then val_link = getIdentifierValLink(val2, P.URL_format, params, 'blue') -- wikidata only no local identifier elseif val2=='' then val_link = getIdentifierValLink(val1, P.URL_format, params, 'magenta') -- match was found elseif val2 then val_link = getIdentifierValLink(val1, P.URL_format, params, 'darkgreen') .. "/"..getIdentifierValLink(val2, P.URL_format, params, 'blue') cats = string.format("%s[[Category:Pages using authority control with identifiers mismatching Wikidata]]\n", cats) transfer = string.format(TransStr, q, params.property, val3) elseif not val2 and entity then val_link = getIdentifierValLink(val1, P.URL_format, params, 'darkgreen') cats = string.format("%s[[Category:Pages using authority control with identifiers missing from Wikidata]]\n", cats) transfer = string.format(TransStr, q, params.property, val3) else val_link = getIdentifierValLink(val1, P.URL_format, params, 'blue') -- local identifier and no wikidata q-code end -- combine them all local lineStr = string.format("\n*%s: <span class=\"uid\">%s</span>%s", name_link, val_link, transfer) if (params.lang==lang) or (params.lang=='') then table.insert(results1, lineStr) -- add to high priority list else table.insert(results2, lineStr) -- add to low priority list end end end -- for all sources -- merge high and low priority lists, trim them if needed and convert to string --table.insert(results1, "\n*End list 1") -- for debuging --table.insert(results2, "\n*End list 2") for _,v in pairs(results2) do table.insert(results1, v) end local results = table.concat(results1, "", 1, math.min(#results1, length or #results1)) -- Add Link to wikidata if q then results = string.format("\n*[[File:Wikidata-logo.svg|20px|wikidata:%s|link=wikidata:%s]]: [[d:%s|%s]]%s",q,q,q,q,results) end -- Add link to Worldcat if (args.worldcatid==nil and (args.lccn or data.lccn)) then args.worldcatid = 'lccn-' .. (args.lccn or data.lccn) end if args.worldcatid then results = string.format("%s\n*<span class=\"uid\">[//www.worldcat.org/identities/%s WorldCat]</span>", results, args.worldcatid) end -- Add maintenance categories if q == nil then cats = string.format("%s[[Category:Pages using authority control without Wikidata link]]\n", cats) end if nCustomParam>0 then if cats=='' and entity ~= nil then cats = string.format("%s[[Category:Pages using authority control with all identifiers matching Wikidata]]\n", cats) end if string.find(results, "<span style=\"color:red\">") then cats = string.format("%s[[Category:Pages using authority control with badly formated identifier]]\n", cats) end end -- return results if results~='' then -- if there are any results than wrap them in <div> tag results = string.format('<div class="hlist">%s\n</div>', results) end return results, cats end -- =========================================================================== -- === Version of the function to be called from template namespace -- =========================================================================== function p.authorityControl(frame) -- prepare arguments local args = core.getArgs(frame) local bare = core.yesno(args.bare,false) -- Convert template arguments to the same format as used on wikidata if args.bnf then args.bnf = string.sub(args.bnf, 3) -- trim first 2 characters end if args.isni then -- group in sets of 4 args.isni = string.sub(args.isni, 1, 4).." "..string.sub(args.isni, 5, 8) .." "..string.sub(args.isni, 9,12).." "..string.sub(args.isni,13,16) end if args.isbn then local isbn = isbn.gsub( ' ', '' ) if #isbn==10 then args['isbn-10'] = args.isbn elseif #isbn==13 then args['isbn-13'] = args.isbn end args.isbn = nil end args.gnd = args.gnd or args.pnd --redirect PND to GND args.lccn = fixLCCN(args.lccn) args.wikidata = args.wikidata or args.q or nil -- call the inner "core" function local results, cats = p._authorityControl(nil, args, args.lang, args.length) local namespace = mw.title.getCurrentTitle().namespace local LUT = {[2]='user', [6]='file', [10]='template', [828]='module'} if (LUT[namespace] or math.fmod(namespace,2)==1) then -- lets not add categories to some namespaces, or talk pages and concentrate -- on templates and categories instead cats = '' end --package results as a infobox if not "bare" if not bare then -- Get field name for authority control local field_name = p.getAuthorityControlTag(args.lang) -- build table results = string.format('<tr><td class="type fileinfo-paramfield">%s</td><td>\n%s\n</td></tr>', field_name, results) local dir = mw.language.new( args.lang ):getDir() -- get text direction local style = 'class="toccolours mw-content-%s layouttemplate commons-file-information-table" style="width: 100%%;" dir="%s" lang="%s"' style = string.format(style, dir, dir, args.lang) results = string.format('<table %s>\n%s\n</table>\n', style, results) else results = string.format('\n%s\n', results) end return results..cats end return p