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 = '[[' .. linksPrefix .. 'Social networking service|Social networks]]'
 local group2Label = 'Texts'
 local group3Label = 'Audio, photo and video'
 local group4Label = 'Profiles and catalogs'
 local group5Label = 'Dictionaries and enciclopedias'
 local group6Label = '[[' .. linksPrefix .. 'Authority control|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 &quot;named&quot; colors, defined by templates
 function colorByTitle( frame, colorTitle )
 	local templateName = 'Color/' .. colorTitle;
 	local templateTitle = mw.title.makeTitle( 'Template', templateName );
 	if ( templateTitle == nil or not templateTitle.exists ) then
 		return false;
 	end
 	return frame: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=&amp;kilde=biblio&amp;cql=bs.autid+%3D+' .. id .. '&amp;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&amp;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&amp;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&amp;base=CONOR&amp;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&amp;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&amp;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&amp;REQUEST=' .. id .. '&amp;find_code=SYS&amp;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&amp;request=' .. id .. '000354872&amp;find_code=SYS&amp;adjacent=Y&amp;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&amp;database=ChoiceArtists&amp;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&amp;find_code=SYS&amp;adjacent=Y&amp;local_base=RSL11&amp;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=&amp;role=&amp;nation=&amp;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 '[[' .. link .. '|' .. label .. ']]';
 	end
 	local title = mw.wikibase.label( id ) or defaultTitle;
 	return '&lt;span title=&quot;' .. title .. '&quot; style=&quot;border-bottom: 1px dotted; cursor: help;&quot;&gt;' .. label .. '&lt;/span&gt;'
 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 == &quot;string&quot; ) then
 				return qualifier.datavalue.value;
 			end
 			if ( qualifier.datavalue.type == &quot;wikibase-entityid&quot; ) then
 				return 'Q' .. qualifier.datavalue.value[&quot;numeric-id&quot;];
 			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 == &quot;string&quot; ) then
 					result[#result+1] = qualifier.datavalue.value;
 				elseif ( qualifier.datavalue.type == &quot;wikibase-entityid&quot; ) then
 					result[#result+1] = 'Q' .. qualifier.datavalue.value[&quot;numeric-id&quot;];
 				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 == '&lt;';
  
 		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 .. ':&amp;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 .. ',&amp;nbsp;'
 					end
 					if ( link ) then
 						if ( interwiki ) then
 							html = html .. '[[' .. link .. '|' .. 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 .. '[[' .. link .. '|' .. resourceLabel .. ']]';
 						else
 							html = html .. '[' .. link .. ' ' .. resourceLabel .. ']';
 						end
 					else
 						-- it should not happen
 						html = html .. resourceLabel .. ':&amp;nbsp;' .. itemId;
 					end
  
 					if ( moduleLanguages ) then
 						if ( languages ~= nil and #languages &gt; 0 ) then
 							for langIndex, language in pairs(languages) do
 								html = html .. '&amp;nbsp;' .. moduleLanguages.getRefHtml( language )
 							end
 						end
 					end
 				end
 			end
 			if ( #params &gt;= 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( frame )
 	local colorArg = '#CCF';
 	if ( frame ~= nil ) then
 	    local parentArgs = frame:getParent().args
 	    colorArg = parentArgs[templateColorName] or parentArgs[&quot;color&quot;] or parentArgs[1] or '#CCF';
 	    local firstChar = mw.ustring.sub( colorArg, 1, 1 );
 	    if ( firstChar ~= '#' ) then
 	    	local byTemplate = colorByTitle( frame, colorArg );
 	    	if ( byTemplate ) then
 	    		colorArg = byTemplate;
 	    	end
 	    end
     end
  
 	local navboxData = {
         name  = 'External links',
         navboxclass = 'navbox ruwikiArticleExternalLinksTable',
         bodyclass = 'hlist',
         groupstyle = 'background: ' .. colorArg .. ';',
     };
    	local rowIndex = 1
  
 	local socialNetworksElements = collectLinks( socialNetworkProperties );
 	if ( #socialNetworksElements &gt; 0 ) then
 		navboxData['group' .. rowIndex] = group1Label
 		navboxData['list' .. rowIndex] = table.concat( socialNetworksElements , ' · ' )
 		rowIndex = rowIndex + 1
 	end
  
 	local textsElements = collectLinks( textsProperties );
 	if ( #textsElements &gt; 0 ) then
 		navboxData['group' .. rowIndex] = group2Label
 		navboxData['list' .. rowIndex] = table.concat( textsElements , ' · ' )
 		rowIndex = rowIndex + 1
 	end
  
 	local contentHostingElements = collectLinks( contentHostingProperties );
 	if ( #contentHostingElements &gt; 0 ) then
 		navboxData['group' .. rowIndex] = group3Label
 		navboxData['list' .. rowIndex] = table.concat( contentHostingElements , ' · ' )
 		rowIndex = rowIndex + 1
 	end
  
 	local themeProfilesElements = collectLinks( themeProfilesProperties );
 	if ( #themeProfilesElements &gt; 0 ) then
 		navboxData['group' .. rowIndex] = group4Label
 		navboxData['list' .. rowIndex] = table.concat( themeProfilesElements , ' · ' )
 		rowIndex = rowIndex + 1
 	end
  
 	local dictionaryElements = collectLinks( dictionaryProperties );
 	if ( #dictionaryElements &gt; 0 ) then
 		navboxData['group' .. rowIndex] = group5Label
 		navboxData['list' .. rowIndex] = table.concat( dictionaryElements , ' · ' )
 		rowIndex = rowIndex + 1
 	end
  
 	local authorityControlElements = collectLinks( authorityControl );
 	if ( #authorityControlElements &gt; 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 '[[Category:' .. categoryTemplateEmpty .. ']]'
 			end
 		end
 	else
 		navboxData['group1'] = '&lt;div style=&quot;padding: 0px 18px 0px 0px; width: 100%;&quot;&gt;&lt;div style=&quot;float: left; padding-left: 4px;&quot;&gt;[[File:Searchtool.svg|14px|' .. templateLink .. ']]&lt;/div&gt;&amp;nbsp;&amp;nbsp;' .. navboxData['group1'] .. '&lt;/div&gt;'
 	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 .. '| [[:d:Property:' .. resourceId .. '|' .. resourceId .. ']]\n'
 		elseif string.match( resourceId, '^Q' ) then
 			result = result .. '| [[:d:Property:P553|P553]] / [[:d:Property:P554|P554]] / [[:d:' .. resourceId .. '' .. '|' .. resourceId .. ']]\n'
 		else 
 			result = result .. '| &amp;nbsp; \n'
 		end
  
 		if ( category ) then
 			result = result .. '| [[:Category:' .. category .. '|' .. category .. ']]\n'
 		else
 			result = result .. '| &amp;nbsp; \n'
 		end
 		result = result .. '| ' .. optional .. '\n'
 		result = result .. '|-\n'
     end
  
 	return result;
 end