# Module:External links 2

-- Localizable part  
-- Please, note, that labels to various sites and cataloges are taken from Wikidata (i.e. Wikidata label)  

local linksPrefix = ''  
local project = 'Wikipedia'  
local categoryTemplateEmpty = false  
local categoryWithWikimediaCommons = false  
local templateLink = 'View this template|link=Template:External links 2'  

local group1Label = 'Social networks'  
local group2Label = 'Texts'  
local group3Label = 'Audio, photo and video'  
local group4Label = 'Profiles and catalogs'  
local group5Label = 'Dictionaries and enciclopedias'  
local group6Label = 'Authority control'  

-- The language codes that should be always displayed even if they have normal rank and claim with another language and prefferered rank exists  
local preferredLanguage = 'Q1860'; -- English  

function categoryAuthorityControl( code )  
return 'Wikipedia articles with ' .. code .. ' identifiers'  
end  
function categoryExternalLink( code )  
return false  
end  

local templateColorName = 'color';  
-- some project have "named" colors, defined by templates  
function colorByTitle( , colorTitle )  
local templateName = 'Color/' .. colorTitle;  
local templateTitle = mw.title.makeTitle( 'Template', templateName );  
if ( templateTitle == nil or not templateTitle.exists ) then  
return false;  
end  
return :expandTemplate{ title = templateName };  
end  

-- feed free to correct labels and categories, or add/remove sources here  
local dictionaryProperties = {  
{ 'Grand Catalonian', 'P1296', function ( id ) return 'http://www.enciclopedia.cat/enciclopèdies/gran-enciclopèdia-catalana/EC-GEC-' .. id .. '.xml' end},  
{ 'Grand Soviet', 'Q17378135', function ( link ) return link end},  
{ 'Britannica', 'P1417', function ( id ) return 'http://global.britannica.com/'.. id end},  
{ 'Brockhaus and Efron', 'Q602358', function ( title ) return ':s:ru:ЭСБЕ/' .. title end},  
{ 'Kirill and Mefodiy', 'Q4091875', function ( link ) return link end },  
{ 'Sort Literature', 'Q4239850', function ( link ) return link end},  
{ 'Krugosvet', 'Q2627728', function ( link ) return link end},  
{ 'Larousse', 'Q17329836', function ( link ) return link end},  
{ 'Literature', 'Q4263804', function ( link ) return link end},  
{ 'Lentapedia', 'Q17290934', function ( title ) return ':s:ru:Лентапедия/' .. title end},  
{ 'Orthodox', 'Q2498180', function ( link ) return link end},  
{ 'Historical of Switzerland', 'P902', function ( id ) return 'http://www.hls-dhs-dss.ch/textes/f/F' .. id .. '.php' end},  
{ 'Historical of Switzerland (online)', 'P886', function ( id ) return 'http://www.e-lir.ch/e-LIR___Lexicon.' .. id .. '.450.0.html' end},  
}  

-- Non-localizable part (not need to localize )  
local moduleNavbox = require('Module:Navbox')  

local titleBasedLinks = { ['Q602358'] = true, ['Q17290934'] = true, }  

local p = {}  

function link( url )  
return url  
end  

function allocineFilmLink( id )  
return 'http://www.allocine.fr/film/fichefilm_gen_cfilm=' .. id .. '.html'  
end  

function allocinePersonneLink( id )  
return 'http://www.allocine.fr/personne/fichepersonne_gen_cpersonne=' .. id .. '.html'  
end  

function allocineSeriesLink( id )  
return 'http://www.allocine.fr/series/ficheserie_gen_cserie=' .. id .. '.html'  
end  

function animenewsnetworkLink( id )  
if string.match( id, '^anime\/' ) then  
return 'http://www.animenewsnetwork.com/encyclopedia/anime.php?id=' .. mw.ustring.sub( id, 7 )  
end  
if string.match( id, '^company\/' ) then  
return 'http://www.animenewsnetwork.com/encyclopedia/company.php?id=' .. mw.ustring.sub( id, 9 )  
end  
if string.match( id, '^manga\/' ) then  
return 'http://www.animenewsnetwork.com/encyclopedia/manga.php?id=' .. mw.ustring.sub( id, 7 )  
end  
if string.match( id, '^people\/' ) then  
return 'http://www.animenewsnetwork.com/encyclopedia/people.php?id=' .. mw.ustring.sub( id, 8 )  
end  
if string.match( id, '^releases\/' ) then  
return 'http://www.animenewsnetwork.com/encyclopedia/releases.php?id=' .. mw.ustring.sub( id, 10 )  
end  
return false  
end  

function bavLink( id )  
return 'http://viaf.org/processed/BAV%7C' .. id  
end  

function bibsysLink( id )  
return 'http://ask.bibsys.no/ask/action/result?cmd=&kilde=biblio&cql=bs.autid+%3D+' .. id .. '&feltselect=bs.autid'  
end  

function bloggerLink( id )  
return 'http://' .. id .. '.blogspot.com'  
end  

function bncLink( id )  
return 'http://cantic.bnc.cat/registres/CUCId/' .. id  
end  

function bneLink( id )  
return 'http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id=' .. id  
end  

function bnfLink( id )  
return 'http://catalogue.bnf.fr/ark:/12148/cb' .. id  
end  

function boxofficemojoLink( id )  
return 'http://www.boxofficemojo.com/movies/?id=' .. id .. '.htm'  
end  

function bpnLink( id ) return 'http://www.biografischportaal.nl/persoon/' .. id end  
function calisLink( id ) return 'http://opac.calis.edu.cn/aopac/ajsp/detail.jsp?actionfrom=1&actl=CAL++' .. id end  
function cbdbLink( id ) return 'http://db1.ihp.sinica.edu.tw/cbdbc/cbdbkmeng?~~AAA' .. id end  
function ciniiLink( id ) return 'http://ci.nii.ac.jp/author/' .. id end  
function conorLink( id ) return 'http://www.cobiss.si/scripts/cobiss?command=DISPLAY&base=CONOR&rid=' .. id end  
function chitalnyaRuLink( id ) return 'http://www.chitalnya.ru/users/' .. id .. '/' end  
function commonsWikimediaLink( id ) return ':commons:Category:' .. id end  

function dmozLink( id )  
return 'http://www.dmoz.org/' .. id  
end  

function duduLink( id )  
return 'http://dudu.com/' .. id  
end  

function egaxaLink( id )  
return 'http://viaf.org/processed/EGAXA%7Cvtls' .. id  
end  

function facebookLink( id )  
return 'https://www.facebook.com/' .. id  
end  

function fanLibRuLink( id )  
local firstChar = mw.ustring.sub( id, 1, 1 )  
return 'http://fan.lib.ru/' .. firstChar .. '/' .. id .. '/'  
end  

function flickrLink( id )  
return 'https://www.flickr.com/' .. id  
end  

function findagraveLink( id )  
return 'http://www.findagrave.com/cgi-bin/fg.cgi?page=gr&GRid=' .. id  
end  

function genealogyAsmLink( id )  
return 'http://www.genealogy.ams.org/id.php?id=' .. id  
end  

function gndLink( id )  
return 'http://d-nb.info/gnd/' .. id  
end  

function ibdbPersonLink( id )  
return 'http://www.ibdb.com/person.php?id=' .. id  
end  
function ibdbProductionLink( id )  
return 'http://www.ibdb.com/production.php?id=' .. id  
end  
function ibdbShowLink( id )  
return 'http://www.ibdb.com/show.php?id=' .. id  
end  
function ibdbVenueLink( id )  
return 'http://www.ibdb.com/venue.php?id=' .. id  
end  

function isfdbAuthorLink( id )  
return 'http://www.isfdb.org/cgi-bin/ea.cgi?' .. id  
end  
function isfdbPublicationLink( id )  
return 'http://www.isfdb.org/cgi-bin/pl.cgi?' .. id  
end  
function isfdbSeriesLink( id )  
return 'http://www.isfdb.org/cgi-bin/pe.cgi?' .. id  
end  
function isfdbPublisherLink( id )  
return 'http://www.isfdb.org/cgi-bin/publisher.cgi?' .. id  
end  

function imslpLink( id )  
return 'http://imslp.org/wiki/' .. id  
end  

function imdbLink( id )  
if string.match( id, '^ch' ) then  
return 'http://www.imdb.com/character/' .. id  
end  
if string.match( id, '^co' ) then  
return 'http://www.imdb.com/company/' .. id  
end  
if string.match( id, '^nm' ) then  
return 'http://www.imdb.com/name/' .. id  
end  
if string.match( id, '^tt' ) then  
return 'http://www.imdb.com/title/' .. id  
end  

return false  
end  

function isniLink( id )  
id = id:gsub( '[ %-]', '' ):upper  
return 'http://isni-url.oclc.nl/isni/' .. id  
end  

function lccnLink( id )  
return 'http://id.loc.gov/authorities/names/' .. id  
end  

function lastfmLink( id )  
return 'http://www.lastfm.ru/music/' .. id  
end  

function liveinternetLink( id )  
return 'http://www.liveinternet.ru/users/' .. id  
end  

function livejournalLink( id )  
return 'http://' .. id .. '.livejournal.com/'  
end  

function iccuLink( id )  
id = id:gsub( '\\\\', '%5C' ):upper  
return 'http://opac.sbn.it/opacsbn/opac/iccu/scheda_authority.jsp?bid=' .. id  
end  

function instagramLink( id )  
return 'http://instagram.com/' .. id  
end  

function lnbLink( id )  
return 'http://viaf.org/processed/LNB%7CLNC10-' .. id  
end  

function merimeeLink( id )  
return false  
end  

function mixcloudLink( id )  
return 'https://mixcloud.com/' .. id .. '/'  
end  

function moikrugLink( id )  
return 'http://' .. id .. '.moikrug.ru/'  
end  

function myspaceLink( id )  
return 'https://myspace.com/' .. id  
end  

function myMailRuLink( id )  
return 'http://my.mail.ru/' .. id  
end  

function musicBrainzArtistLink( id )  
return 'https://musicbrainz.org/artist/' .. id  
end  
function musicBrainzReleazeGroupLink( id )  
return 'https://musicbrainz.org/release-group/' .. id  
end  
function musicBrainzWorkLink( id )  
return 'https://musicbrainz.org/work/' .. id  
end  

function nclLink( id ) return 'http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence=' .. id end  
function ndlLink( id ) return 'http://id.ndl.go.jp/auth/ndlna/' .. id end  
function nlcLink( id ) return false end  
function nliLink( id ) return 'http://a20.libnet.ac.il/F?func=find-b&REQUEST=' .. id .. '&find_code=SYS&local_base=NNL10' end  
function nkcLink( id ) return 'http://aut.nkp.cz/' .. id end  
function nlaLink( id ) return 'http://nla.gov.au/anbd.aut-an' .. id end  
function nlrLink( id ) return 'http://alephnew.bibnat.ro:8991/F?func=find-b&request=' .. id .. '000354872&find_code=SYS&adjacent=Y&local_base=NLR10' end  
function nszlLink( id ) return 'http://viaf.org/processed/NSZL%7C' .. id end  
function nskLink( id ) return 'http://viaf.org/processed/NSK%7C' .. id end  
function ntaLink( id ) return 'http://opc4.kb.nl/PPN?PPN=' .. id end  
function nukatLink( id ) return 'http://viaf.org/processed/NUKAT%7C' .. id end  

function okLink( id )  
return 'http://www.odnoklassniki' .. '.ru/profile/' .. id  
end  

function orcidLink( id )  
id = id:gsub( '[ %-]', '' ):upper  
return 'http://orcid.org/' .. id  
end  

function plusGoogleLink( id )  
return 'https://plus.google.com/' .. id .. '/posts'  
end  

function promodjLink( id )  
return 'http://promodj.com/' .. id  
end  

function prozaRuLink( id )  
return 'http://proza.ru/avtor/' .. id  
end  

function ptbnpLink( id )  
return 'http://viaf.org/processed/PTBNP%7C' .. id  
end  

function qroomLink( id )  
return 'http://qroom.ru/' .. id  
end  

function rkdArtistsLink( id )  
return 'http://www.rkd.nl/rkddb/dispatcher.aspx?action=search&database=ChoiceArtists&search=priref=' .. id  
end  

function rkdImagesLink( id )  
return 'http://explore.rkd.nl/en/images/' .. id  
end  

function ridLink( id )  
return 'http://www.researcherid.com/rid/' .. id  
end  

function rodovidLink( id )  
return 'http://ru.rodovid.org/wk/Person:' .. id  
end  

function rottentomatoesLink( id )  
return 'http://www.rottentomatoes.com/' .. id  
end  

function rslLink( id )  
return 'http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request=' .. id  
end  

function rutubeLink( id )  
if string.match( id, '^%d+$' ) then  
return 'http://rutube.ru/video/persion/' .. id .. '/'  
end  
return 'http://' .. id .. '.rutube.ru/'  
end  

function samlibRuLink( id )  
local firstChar = mw.ustring.sub( id, 1, 1 )  
return 'http://samlib.ru/' .. firstChar .. '/' .. id .. '/'  
end  

function scopusLink( id )  
return 'http://www.scopus.com/authid/detail.url?authorId=' .. id  
end  

function selibrLink( id )  
return 'http://libris.kb.se/auth/' .. id  
end  

function soundcloudLink( id )  
return 'http://soundcloud.com/' .. id .. '/'  
end  

function sprashivaiRuLink( id )  
return 'http://sprashivai.ru/' .. id  
end  

function springMeLink( id )  
return 'http://www.spring.me/' .. id  
end  

function stihiRuLink( id )  
return 'http://stihi.ru/avtor/' .. id  
end  

function sudocLink( id )  
return 'http://www.idref.fr/' .. id  
end  

function tumblrLink( id )  
return 'https://' .. id .. '.tumblr.com/'  
end  

function twitterLink( id )  
return 'https://twitter.com/' .. id  
end  

function ulanLink( id )  
return 'http://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid=' .. id  
end  

function vkLink( id )  
return 'https://vk.com/' .. id  
end  

function vkrugudruzeiLink( id )  
return 'http://' .. id .. '.vkrugudruzei.ru/'  
end  

function vimeoLink( id )  
return 'https://vimeo.com/' .. id  
end  

function viafLink( id )  
return 'http://viaf.org/viaf/' .. id  
end  

function yaRuLink( id )  
return 'http://' .. id .. '.ya.ru/'  
end  

function youtubeLink( id )  
return 'https://youtube.com/' .. id  
end  

function getLabelWithoutLink( id, defaultLabel )  
return mw.wikibase.label( id ) or defaultLabel;  
end  

function getLabelWithLink( id, defaultTitle, label )  
local link = mw.wikibase.sitelink( id );  
if ( link ~= nil ) then  
return * .. label .. *;  
end  
local title = mw.wikibase.label( id ) or defaultTitle;  
return '<span title="' .. title .. '">' .. label .. '</span>'  
end  

local socialNetworkProperties = {  
{ getLabelWithoutLink( 'Q116933', 'ВКонтакте'), 'Q116933', vkLink, categoryExternalLink( 'ВКонтакте' ) },  
{ getLabelWithoutLink( 'Q4101720', 'В кругу друзей'), 'Q4101720', vkrugudruzeiLink, categoryExternalLink( 'В кругу друзей' ) },  
{ getLabelWithoutLink( 'Q219523', 'Живой журнал'), 'Q219523', livejournalLink, categoryExternalLink( 'Живой журнал' ) },  
{ getLabelWithoutLink( 'Q4299813', 'Мой круг'), 'Q4299813', moikrugLink, categoryExternalLink( 'Мой круг' ) },  
{ getLabelWithoutLink( 'Q4299858', 'Мой мир'), 'Q4299858', myMailRuLink, categoryExternalLink( 'Мой мир' ) },  
{ getLabelWithoutLink( 'Q1123836', 'Одноклассники'), 'Q1123836', okLink, categoryExternalLink( 'Одноклассники' ) },  
{ getLabelWithoutLink( 'Q17195318', 'Спрашивай.Ру'), 'Q17195318', sprashivaiRuLink, categoryExternalLink( 'Спрашивай.Ру' ) },  
{ getLabelWithoutLink( 'Q798490', 'Я.ру'), 'Q798490', yaRuLink, categoryExternalLink( 'Я.ру' ) },  
{ getLabelWithoutLink( 'Q171186', 'Blogger'), 'Q171186', bloggerLink, categoryExternalLink( 'Blogger' ) },  
{ getLabelWithoutLink( 'Q4037665', 'Dudu'), 'Q4037665', duduLink, categoryExternalLink( 'Dudu' ) },  
{ getLabelWithoutLink( 'Q355', 'Facebook'), 'Q355', facebookLink, categoryExternalLink( 'Facebook' ) },  
{ getLabelWithoutLink( 'Q356', 'Google+'), 'Q356', plusGoogleLink, categoryExternalLink( 'Google+' ) },  
{ getLabelWithoutLink( 'Q4043051', 'LiveInternet'), 'Q4043051', liveinternetLink, categoryExternalLink( 'LiveInternet' ) },  
{ getLabelWithoutLink( 'Q40629', 'MySpace'), 'Q40629', myspaceLink, categoryExternalLink( 'MySpace' ) },  
{ getLabelWithoutLink( 'Q17144398', 'QRoom'), 'Q17144398', qroomLink, categoryExternalLink( 'QRoom' ) },  
{ getLabelWithoutLink( 'Q1002972', 'Spring.me'), 'Q1002972', springMeLink, categoryExternalLink( 'Spring.me' ) },  
{ getLabelWithoutLink( 'Q384060', 'Tumblr'), 'Q384060', tumblrLink, categoryExternalLink( 'Tumblr' ) },  
{ getLabelWithoutLink( 'Q918', 'Twitter'), 'Q918', twitterLink, categoryExternalLink( 'Twitter' ) },  
}  

local textsProperties = {  
{ getLabelWithoutLink( 'Q17254543', 'Изба-читальня'), 'Q17254543', chitalnyaRuLink, categoryExternalLink( 'Изба-читальня' ) },  
{ getLabelWithoutLink( 'Q17195344', 'Журнал «Самиздат»'), 'Q17195344', samlibRuLink, categoryExternalLink( 'Самиздат' ) },  
{ getLabelWithoutLink( 'Q4380129', 'Проза.ру'), 'Q4380129', prozaRuLink, categoryExternalLink( 'Проза.ру' ) },  
{ getLabelWithoutLink( 'Q4442644', 'Стихи.ру'), 'Q4442644', stihiRuLink, categoryExternalLink( 'Стихи.ру' ) },  
{ getLabelWithoutLink( 'Q17300505', 'Lib.Ru/Фантастика'), 'Q17300505', fanLibRuLink, categoryExternalLink( 'Lib.Ru/Фантастика' ) },  
}  

local contentHostingProperties = {  
{ getLabelWithoutLink( 'Q565', 'Wikimedia Commons' ), 'P373', commonsWikimediaLink, categoryWithWikimediaCommons, true },  
{ getLabelWithoutLink( 'Q103204', 'Flickr' ), 'Q103204', flickrLink, categoryExternalLink( 'Flickr' ), false },  
{ getLabelWithoutLink( 'Q209330', 'Instagram' ), 'Q209330', instagramLink, categoryExternalLink( 'Instagram' ), false },  
{ getLabelWithoutLink( 'Q183718', 'Last.fm' ), 'Q183718', lastfmLink, categoryExternalLink( 'Last.fm' ), false },  
{ getLabelWithoutLink( 'Q6883832', 'Mixcloud' ), 'Q6883832', mixcloudLink, categoryExternalLink( 'Mixcloud' ), false },  
{ getLabelWithoutLink( 'Q17117201', 'PROMODJ' ), 'Q17117201', promodjLink, categoryExternalLink( 'PROMODJ' ), false },  
{ getLabelWithoutLink( 'Q372827', 'Rutube' ), 'Q372827', rutubeLink, categoryExternalLink( 'Rutube' ), false },  
{ getLabelWithoutLink( 'Q568769', 'SoundCloud' ), 'Q568769', soundcloudLink, categoryExternalLink( 'SoundCloud' ), false },  
{ getLabelWithoutLink( 'Q156376', 'Vimeo' ), 'Q156376', vimeoLink, categoryExternalLink( 'Vimeo' ), false },  
{ getLabelWithoutLink( 'Q866', 'YouTube' ), 'Q866', youtubeLink, categoryExternalLink( 'YouTube' ), false },  
}  

local labelAllocine = getLabelWithoutLink( 'Q31165', 'AlloCiné' );  
local labelIBDb = getLabelWithoutLink( 'Q31964', 'Internet Broadway Database' );  
local labelISFDb = getLabelWithoutLink( 'Q2629164', 'Internet Speculative Fiction Database' );  
local labelMusicBrainz = getLabelWithoutLink( 'Q14005', 'MusicBrainz' );  

local themeProfilesProperties = {  
-- science  
{ getLabelWithoutLink( 'Q829984', 'Mathematics Genealogy Project' ), 'P549', genealogyAsmLink, categoryExternalLink( 'Математическая генеалогия' ) },  
{ getLabelWithoutLink( 'Q51044', 'ORCID' ), 'P496', orcidLink, categoryExternalLink( 'ORCID' ) },  
{ getLabelWithoutLink( 'Q7315186', 'ResearcherID' ), 'P1053', ridLink, categoryExternalLink( 'ResearcherID' ) },  
{ getLabelWithoutLink( 'Q371467', 'Scopus' ), 'P1153', scopusLink, categoryExternalLink( 'Scopus' ) },  
-- audio and video  
{ labelAllocine, 'P1265', allocineFilmLink, categoryExternalLink( 'AlloCiné' ) },  
{ labelAllocine, 'P1266', allocinePersonneLink, categoryExternalLink( 'AlloCiné' ) },  
{ labelAllocine, 'P1267', allocineSeriesLink, categoryExternalLink( 'AlloCiné' ) },  
{ getLabelWithoutLink( 'Q220509', 'Anime News Network' ), 'P1361', animenewsnetworkLink, categoryExternalLink( 'Anime News Network' ) },  
{ getLabelWithoutLink( 'Q223142', 'Box Office Mojo' ), 'P1237', boxofficemojoLink, categoryExternalLink( 'Box Office Mojo' ) },  
{ getLabelWithoutLink( 'Q2638147', 'FilmAffinity' ), 'P480', function(id) return 'http://www.filmaffinity.com/en/film' .. id .. '.html' end, categoryExternalLink( 'FilmAffinity' ) },  
{ labelIBDb, 'P1217', ibdbVenueLink, categoryExternalLink( 'IBDb' ) },  
{ labelIBDb, 'P1218', ibdbProductionLink, categoryExternalLink( 'IBDb' ) },  
{ labelIBDb, 'P1219', ibdbShowLink, categoryExternalLink( 'IBDb' ) },  
{ labelIBDb, 'P1220', ibdbPersonLink, categoryExternalLink( 'IBDb' ) },  
{ getLabelWithoutLink( 'Q37312', 'Internet Movie Database' ), 'P345', imdbLink, categoryExternalLink( 'IMDb' ) },  
{ getLabelWithoutLink( 'Q523660', 'International Music Score Library Project' ), 'P839', imslpLink, categoryExternalLink( 'IMSLP' ) },  
{ labelMusicBrainz, 'P434', musicBrainzArtistLink, categoryExternalLink( 'MusicBrainz' ) },  
{ labelMusicBrainz, 'P435', musicBrainzWorkLink, categoryExternalLink( 'MusicBrainz' ) },  
{ labelMusicBrainz, 'P436', musicBrainzReleazeGroupLink, categoryExternalLink( 'MusicBrainz' ) },  
{ getLabelWithoutLink( 'Q105584', 'Rotten Tomatoes' ), 'P1258', rottentomatoesLink, categoryExternalLink( 'Rotten Tomatoes' ) },  
-- literature  
{ labelISFDb, 'P1233', isfdbAuthorLink, categoryExternalLink( 'ISFDb' ) },  
{ labelISFDb, 'P1234', isfdbPublicationLink, categoryExternalLink( 'ISFDb' ) },  
{ labelISFDb, 'P1235', isfdbSeriesLink, categoryExternalLink( 'ISFDb' ) },  
{ labelISFDb, 'P1239', isfdbPublisherLink, categoryExternalLink( 'ISFDb' ) },  

{ getLabelWithoutLink( 'Q17299517', 'RKDartists' ), 'P650', rkdArtistsLink, categoryExternalLink( 'RKDartists' ) },  
{ getLabelWithoutLink( 'Q17299580', 'RKDimages' ), 'P350', rkdImagesLink, categoryExternalLink( 'RKDimages' ) },  
-- common  
{ getLabelWithoutLink( 'Q649227', 'Родовод' ), 'P1185', rodovidLink, categoryExternalLink( 'Родовод' ) },  
{ getLabelWithoutLink( 'Q41226', 'Open Directory Project' ), 'P998', dmozLink, categoryExternalLink( 'DMOZ' ) },  
{ getLabelWithoutLink( 'Q63056', 'Find a Grave' ), 'P535', findagraveLink, categoryExternalLink( 'Find a Grave' ) },  
}  

local authorityControl = {  
{ getLabelWithLink( 'Q213678', 'Bibliotheca Apostolica Vaticana', 'BAV'), 'P1017', bavLink, categoryAuthorityControl( 'BAV' ) },  
{ getLabelWithLink( 'Q4584301', '', 'BIBSYS'), 'P1015', bibsysLink, categoryAuthorityControl( 'BIBSYS' ) },  
{ getLabelWithLink( 'Q1200925', 'Biblioteca de Catalunya', 'BNC'), 'P1273', bncLink, categoryAuthorityControl( 'BNC' ) },  
{ getLabelWithLink( 'Q750403', 'Biblioteca Nacional de España', 'BNE'), 'P950', bneLink, categoryAuthorityControl( 'BNE' ) },  
{ getLabelWithLink( 'Q193563', 'Bibliothèque nationale de France', 'BNF'), 'P268', bnfLink, categoryAuthorityControl( 'BNF' ) },  
{ getLabelWithLink( 'Q1868372', 'Biografisch Portaal', 'BPN'), 'P651', bpnLink, categoryAuthorityControl( 'BPN' ) },  
{ getLabelWithLink( 'Q9384291', '中国高等教育文献保障系统', 'CALIS'), 'P270', calisLink, categoryAuthorityControl( 'CALIS' ) },  
{ getLabelWithLink( 'Q17299677', 'China Biographical Database Project', 'CBDB'), 'P497', cbdbLink, categoryAuthorityControl( 'CBDB' ) },  
{ getLabelWithLink( 'Q10726338', 'Citation Information by NII', 'CiNii'), 'P271', ciniiLink, categoryAuthorityControl( 'CiNii' ) },  
{ getLabelWithLink( 'Q16744133', 'CONOR', 'CONOR'), 'P1280', conorLink, categoryAuthorityControl( 'CONOR' ) },  
{ getLabelWithLink( 'Q501851', 'مكتبة الإسكندرية الجديدة', 'EGAXA'), 'P1309', egaxaLink, categoryAuthorityControl( 'EGAXA' ) },  
{ getLabelWithLink( 'Q36578', 'Gemeinsame Normdatei', 'GND'), 'P227', gndLink, categoryAuthorityControl( 'GND' ) },  
{ getLabelWithLink( 'Q3803707', 'Istituto Centrale per il Catalogo Unico', 'ICCU'), 'P396', iccuLink, categoryAuthorityControl( 'ICCU' ) },  
{ getLabelWithLink( 'Q423048', 'International Standard Name Identifier', 'ISNI'), 'P213', isniLink, categoryAuthorityControl( 'ISNI' ) },  
{ getLabelWithLink( 'Q620946', 'Library of Congress Control Number', 'LCCN'), 'P244', lccnLink, categoryAuthorityControl( 'LCCN' ) },  
{ getLabelWithLink( 'Q1133733', 'Latvijas Nacionālā bibliotēka', 'LNB'), 'P1368', lnbLink, categoryAuthorityControl( 'LNB' ) },  
{ getLabelWithLink( 'Q809830', 'Base Mérimée', 'Mérimée'), 'P380', merimeeLink,categoryAuthorityControl( 'Mérimée' ) },  
{ getLabelWithLink( 'Q618340', '國家圖書館 (中華民國)', 'NCL'), 'P1048', nclLink, categoryAuthorityControl( 'NCL' ) },  
{ getLabelWithLink( 'Q477675', '国立国会図書館', 'NDL'), 'P349', ndlLink, categoryAuthorityControl( 'NDL' ) },  
{ getLabelWithLink( 'Q732353', '中国国家图书馆', 'NLC'), 'P1213', nlcLink, categoryAuthorityControl( 'NLC' ) },  
-- NLI numbers seems unstable  
{ getLabelWithLink( 'Q1967876', 'Národní knihovna České republiky', 'NKC'), 'P691', nkcLink, categoryAuthorityControl( 'NKC' ) },  
{ getLabelWithLink( 'Q623578', 'National Library of Australia', 'NLA'), 'P409', nlaLink, categoryAuthorityControl( 'NLA' ) },  
{ getLabelWithLink( 'Q622012', 'Biblioteca Națională a României', 'NLR'), 'P1003', nlrLink, categoryAuthorityControl( 'NLR' ) },  
{ getLabelWithLink( 'Q631375', 'Nacionalna i sveučilišna knjižnica u Zagrebu', 'NSK'), 'P1375', nskLink, categoryAuthorityControl( 'NSK' ) },  
{ getLabelWithLink( 'Q1526131', 'Koninklijke Bibliotheek', 'NTA'), 'P1006', ntaLink, categoryAuthorityControl( 'NTA' ) },  
{ getLabelWithLink( 'Q1063819', 'Országos Széchényi Könyvtár', 'NSZL'), 'P951', nszlLink, categoryAuthorityControl( 'NSZL' ) },  
{ getLabelWithLink( 'Q11789729', 'Narodowy Uniwersalny Katalog Centralny', 'NUKAT'), 'P1207', nukatLink, categoryAuthorityControl( 'NUKAT' ) },  
{ getLabelWithLink( 'Q245966', 'Biblioteca Nacional de Portugal', 'PTBNP'), 'P1005', ptbnpLink, categoryAuthorityControl( 'PTBNP' ) },  
{ getLabelWithLink( 'Q1048694', 'Российская государственная библиотека', 'RSL'), 'P947', rslLink, categoryAuthorityControl( 'RSL' ) },  
{ getLabelWithLink( 'Q953058', 'Kungliga biblioteket', 'LIBRIS'), 'P906', selibrLink, categoryAuthorityControl( 'SELIBR' ) },  
{ getLabelWithLink( 'Q2597810', 'Système universitaire de documentation', 'SUDOC'), 'P269', sudocLink, categoryAuthorityControl( 'SUDOC' ) },  
{ getLabelWithLink( 'Q54919', 'Virtual International Authority File', 'VIAF'), 'P214', viafLink, categoryAuthorityControl( 'VIAF' ) },  
{ getLabelWithLink( 'Q2494649', 'Union List of Artist Names', 'ULAN' ), 'P245', ulanLink, categoryAuthorityControl( 'ULAN' ) },  
}  

function getQualifierSingleValue( statement, qualifierName )  
if (statement ~= nil  
and statement.qualifiers ~= nil  
and statement.qualifiers[qualifierName] ~= nil  
and statement.qualifiers[qualifierName][0] ~= nil  
and statement.qualifiers[qualifierName][0].datavalue ~= nil  
and statement.qualifiers[qualifierName][0].datavalue.type ~= nil  
and statement.qualifiers[qualifierName][0].datavalue.value ~= nil  
) then  
local qualifier = statement.qualifiers[qualifierName][0];  
if ( qualifier.datavalue.type == "string" ) then  
return qualifier.datavalue.value;  
end  
if ( qualifier.datavalue.type == "wikibase-entityid" ) then  
return 'Q' .. qualifier.datavalue.value["numeric-id"];  
end  
mw.log( 'Unknown qualifier type: ' .. qualifier.datavalue.type )  
return qualifier.datavalue.value;  
end  
return nil;  
end  

function getQualifierValues( statement, qualifierName )  
local result = {}  
if (statement ~= nil  
and statement.qualifiers ~= nil  
and statement.qualifiers[qualifierName] ~= nil) then  
local qualifiers = statement.qualifiers[qualifierName];  
for _, qualifier in pairs( qualifiers ) do  
if (qualifier.datavalue ~= nil  
and qualifier.datavalue.type ~= nil  
and qualifier.datavalue.value ~= nil) then  

if ( qualifier.datavalue.type == "string" ) then  
result[#result+1] = qualifier.datavalue.value;  
elseif ( qualifier.datavalue.type == "wikibase-entityid" ) then  
result[#result+1] = 'Q' .. qualifier.datavalue.value["numeric-id"];  
else  
mw.log( 'Unknown qualifier type: ' .. qualifier.datavalue.type );  
result[#result+1] = 'Q' .. qualifier.datavalue.value;  
end  
end  
end  
end  
return result;  
end  

function collectLinks( configuration )  

local moduleLanguages  
if ( mw.title.makeTitle( 'Module', 'Languages' ).exists  
and mw.title.makeTitle( 'Module', 'Languages/data' ).exists  
and mw.title.makeTitle( 'Module', 'Wikidata/Language-codes' ).exists) then  
moduleLanguages = require('Module:Languages');  
else  
moduleLanguages = false;  
end  

--Create rows  
local elements = {}  
local data = {}  

local item = mw.wikibase.getEntity  
if item == nil or item.claims == nil then  
return elements  
end  

if ( item.claims['P553'] ~= nil ) then  
local claim = item.claims['P553']  
for _, statement in pairs( claim ) do  
if (statement ~= nil) then  
-- profile ID  
local rank = statement.rank or 'normal';  
if ( rank ~= 'deprecated' ) then  
local itemId = getQualifierSingleValue( statement, 'P554' );  
if (itemId ~= nil) then  
-- language  
local languages = getQualifierValues( statement, 'P407' );  
local resourceId = 'Q' .. statement.mainsnak.datavalue.value['numeric-id']  
if (data[resourceId] == nil) then  
data[resourceId] = {};  
end  
table.insert( data[resourceId], { itemId = itemId, languages = languages, rank = rank} )  
end  
end  
end  
end  
end  

if ( item.claims['P1343'] ~= nil ) then  
local claim = item.claims['P1343']  
for _, statement in pairs( claim ) do  
if (statement ~= nil) then  
local rank = statement.rank or 'normal';  
if ( rank ~= 'deprecated' ) then  
local resourceId = 'Q' .. statement.mainsnak.datavalue.value['numeric-id']  
local languages = getQualifierValues( statement, 'P407' );  

if ( titleBasedLinks[resourceId] ) then  
-- title-based  
local title = getQualifierSingleValue( statement, 'P357' );  
if (title ~= nil) then  
if (data[resourceId] == nil) then  
data[resourceId] = {};  
end  
table.insert( data[resourceId], { itemId = title, languages = languages, rank = rank} );  
end  
else  
-- URL to encyclopedia  
local url = getQualifierSingleValue( statement, 'P854' );  
if (url ~= nil) then  
if (data[resourceId] == nil) then  
data[resourceId] = {};  
end  
table.insert( data[resourceId], { itemId = url, languages = languages, rank = rank} );  
end  
end  
end  
end  
end  
end  

for _, params in pairs( configuration ) do  
local resourceId = params[2]  

local claim = item.claims[ resourceId ]  
if ( claim ) then  
for _, statement in pairs( claim ) do  
local rank = statement.rank or 'normal';  
if rank ~= 'deprecated' and statement.mainsnak.snaktype ~= 'novalue' then  
local itemId = statement.mainsnak.datavalue.value;  
local languages = getQualifierValues( statement, 'P407' );  
if (data[resourceId] == nil) then  
data[resourceId] = {};  
end  
table.insert( data[resourceId], { itemId = itemId, languages = languages, rank = rank} );  
end  
end  
end  
end  

for resourceId, resourceDatas in pairs( data ) do  
data[resourceId] = filterByRank( resourceDatas );  
end  

local hasNonOptionalLinks = false  

for _, params in pairs( configuration ) do  
local resourceLabel = params[1]  
local firstChar = mw.ustring.sub( resourceLabel, 1, 1 );  
local separateDesign = firstChar == '[' or firstChar == '<';  

local resourceId = params[2]  
local optional = params[5] or false;  

local resourceDatas = data[resourceId];  
if resourceDatas ~= nil then  
if ( not optional ) then  
hasNonOptionalLinks = true  
end  

local html = '';  
if ( separateDesign ) then  
html = html .. resourceLabel .. ':&nbsp;';  
end  
for index, resourceData in pairs(resourceDatas) do  
local itemId = resourceData.itemId;  
local languages = resourceData.languages;  
local link = params[3] ( itemId );  
local linkFirstChar;  
local interwiki;  
if ( link ) then  
linkFirstChar = mw.ustring.sub( link, 1, 1 );  
interwiki = linkFirstChar == ':'  
end  

if ( separateDesign ) then  
if ( index ~= 1 ) then  
html = html .. ',&nbsp;'  
end  
if ( link ) then  
if ( interwiki ) then  
html = html .. * .. itemId .. *;  
else  
html = html .. '[' .. link .. ' ' .. itemId .. ']';  
end  
else  
html = html .. itemId;  
end  
else  
if ( index ~= 1 ) then  
html = html .. ' · '  
end  
if ( link ) then  
if ( interwiki ) then  
html = html .. * .. resourceLabel .. *;  
else  
html = html .. '[' .. link .. ' ' .. resourceLabel .. ']';  
end  
else  
-- it should not happen  
html = html .. resourceLabel .. ':&nbsp;' .. itemId;  
end  

if ( moduleLanguages ) then  
if ( languages ~= nil and #languages > 0 ) then  
for langIndex, language in pairs(languages) do  
html = html .. '&nbsp;' .. moduleLanguages.getRefHtml( language )  
end  
end  
end  
end  
end  
if ( #params >= 4 and params[4] ) then  
html = html .. '[[Category:' .. params[4] .. ']]'  
end  
table.insert( elements, html )  
end  
end  

if ( not hasNonOptionalLinks ) then  
return {}  
end  

return elements  
end  

function contains( tableStructure, value )  
if ( tableStructure == nil or value == nil) then  
return true;  
end  
for index, line in pairs( tableStructure ) do  
if (line == value) then  
return true;  
end  
end  
return false;  
end  

function filterByRank( resourceDatas )  
-- itemId, languages. rank = rank  

local hasPreffered = false;  
for index, resourceData in pairs(resourceDatas) do  
if ( resourceData.rank == 'preferred' ) then  
hasPreffered = true;  
end  
end  

if (not hasPreffered) then  
return resourceDatas;  
end  

local result = {};  
for index, resourceData in pairs(resourceDatas) do  
if ( resourceData.rank == 'preferred' or contains(resourceData.languages, preferredLanguage) ) then  
table.insert(result, resourceData);  
end  
end  

return result;  
end  

function p.render  
local colorArg = '#CCF';  
if ( ~= nil ) then  
local parentArgs = :getParent.args  
colorArg = parentArgs[templateColorName] or parentArgs["color"] or parentArgs[1] or '#CCF';  
local firstChar = mw.ustring.sub( colorArg, 1, 1 );  
if ( firstChar ~= '#' ) then  
local byTemplate = colorByTitle( , colorArg );  
if ( byTemplate ) then  
colorArg = byTemplate;  
end  
end  
end  

local navboxData = {  
name = 'External links',  
navbox,  
body,  
group .. colorArg .. ';',  
};  
local rowIndex = 1  

local socialNetworksElements = collectLinks( socialNetworkProperties );  
if ( #socialNetworksElements > 0 ) then  
navboxData['group' .. rowIndex] = group1Label  
navboxData['list' .. rowIndex] = table.concat( socialNetworksElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

local textsElements = collectLinks( textsProperties );  
if ( #textsElements > 0 ) then  
navboxData['group' .. rowIndex] = group2Label  
navboxData['list' .. rowIndex] = table.concat( textsElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

local contentHostingElements = collectLinks( contentHostingProperties );  
if ( #contentHostingElements > 0 ) then  
navboxData['group' .. rowIndex] = group3Label  
navboxData['list' .. rowIndex] = table.concat( contentHostingElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

local themeProfilesElements = collectLinks( themeProfilesProperties );  
if ( #themeProfilesElements > 0 ) then  
navboxData['group' .. rowIndex] = group4Label  
navboxData['list' .. rowIndex] = table.concat( themeProfilesElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

local dictionaryElements = collectLinks( dictionaryProperties );  
if ( #dictionaryElements > 0 ) then  
navboxData['group' .. rowIndex] = group5Label  
navboxData['list' .. rowIndex] = table.concat( dictionaryElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

local authorityControlElements = collectLinks( authorityControl );  
if ( #authorityControlElements > 0 ) then  
navboxData['group' .. rowIndex] = group6Label  
navboxData['list' .. rowIndex] = table.concat( authorityControlElements , ' · ' )  
rowIndex = rowIndex + 1  
end  

if ( rowIndex == 1 ) then  
if ( mw.title.getCurrentTitle.namespace == 0 ) then  
if ( categoryTemplateEmpty ) then  
return ''  
end  
end  
else  
navboxData['group1'] = '<div><div></div>&nbsp;&nbsp;' .. navboxData['group1'] .. '</div>'  
end  

local navbox = moduleNavbox._navbox( navboxData )  
return navbox  
end  

function p.renderDocumentation  
local result = ''  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group1Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( socialNetworkProperties );  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group2Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( textsProperties );  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group3Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( contentHostingProperties );  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group4Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( themeProfilesProperties );  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group5Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( dictionaryProperties );  
result = result .. '|-\n'  
result = result .. '! colspan=4 | ' .. group6Label .. '\n'  
result = result .. '|-\n'  
result = result .. renderDocumentationCategory( authorityControl );  
return result;  
end  

function renderDocumentationCategory( links )  
local result = ''  

for _, params in pairs( links ) do  
local resourceLabel = params[1]  
local resourceId = params[2]  
local category = params[4]  
local optional  
if ( params[5] or false ) then  
optional = 'TRUE'  
else  
optional = 'FALSE'  
end  

result = result .. '| ' .. resourceLabel .. '\n'  
if string.match( resourceId, '^P' ) then  
result = result .. '| ' .. resourceId .. '\n'  
elseif string.match( resourceId, '^Q' ) then  
result = result .. '| P553 / P554 / ' .. resourceId .. '\n'  
else  
result = result .. '| &nbsp; \n'  
end  

if ( category ) then  
result = result .. '| ' .. category .. '\n'  
else  
result = result .. '| &nbsp; \n'  
end  
result = result .. '| ' .. optional .. '\n'  
result = result .. '|-\n'  
end  

return result;  
end  

return p