Mô đun:Liên kết ngoài

local data = require('Module:Liên kết ngoài/data')
-- 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 = project .. ':Шаблон «Внешние ссылки» пуст'
local categoryWithWikimediaCommons = project .. ':Статьи со ссылками на Викисклад'
local templateLink = 'Hộp liên kết ngoài'
local group1Label = 'Mạng xã hội'
local group2Label = 'Тексты произведений'
local group3Label = 'Phương tiện'
local group4Label = 'Website chuyên đề'
local group5Label = 'Từ điển và bách khoa thư'
local group6Label = 'Phả hệ và некрополистика'
local group7Label = 'Phân loại học'
local group8Label = 'Kiểm soát tính nhất quán'
-- 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 = 'Q7737'; -- russian
local preferredLanguage = 'Q9199'; -- vietnamese
local templateColorName = 'цвет';
-- Some projects have "named" colors, defined by templates
function colorByTitle( frame, colorTitle )
	local templateName = 'Цвет/' .. 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
-- Feel free to correct labels and categories, or add/remove sources here
-- Non-localizable part (not need to localize )
local moduleNavbox = require('Module:Navbox')
local moduleLanguages -- accessed if necessary
local titleBasedLinks = { 'Q602358' = true, 'Q17290934' = true, 'Q1960551' = true }
local p = {}
function link( url )
	return url
end
function renderLabel( params )
	if type( params ) == 'string' then
		return params;
	end
	local id = params 1 ;
	local default = params 2 ;
	if #params >= 3 then
		local label = params 3 ;
		local link = mw.wikibase.sitelink( id );
		if ( link ~= nil ) then
			return  .. label .. ;
		end
		local title = mw.wikibase.label( id ) or default;
		return  .. label .. 
	end
	return mw.wikibase.label( id ) or default;
end
function getQualifierSingleValue( statement, qualifierName )
	if (statement ~= nil
			and statement.qualifiers ~= nil
			and statement.qualifiersqualifierName ~= nil) then
		for qualifierIndex, qualifier in pairs( statement.qualifiersqualifierName ) do
			if (qualifier.datavalue ~= nil
					and qualifier.datavalue.type ~= nil
					and qualifier.datavalue.value ~= nil) then
				if ( qualifier.datavalue.type == "monolingualtext" ) then
					return qualifier.datavalue.value.text;
				end
				if ( qualifier.datavalue.type == "string" ) then
					return qualifier.datavalue.value;
				end
				if ( qualifier.datavalue.type == "wikibase-entityid" ) then
					return qualifier.datavalue.value.id;
				end
				mw.log( 'Unknown qualifier type: ' .. qualifier.datavalue.type )
				return qualifier.datavalue.value;
			end
		end
	end
	return nil;
end
function getQualifierValues( statement, qualifierName )
	local result = {}
	if (statement ~= nil
			and statement.qualifiers ~= nil
			and statement.qualifiersqualifierName ~= nil) then
		local qualifiers = statement.qualifiersqualifierName;
		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  = qualifier.datavalue.value.id;
				else
					mw.log( 'Unknown qualifier type: ' .. qualifier.datavalue.type );
					result #result + 1  = qualifier.datavalue.value;
				end
			end
		end
	end
	return result;
end
function collectLinks( configuration, elementId )
	--Create rows
	local elements = {}
	local data = {}
	local item = mw.wikibase.getEntity( elementId )
	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 = statement.mainsnak.datavalue.value.id;
						if (dataresourceId == nil) then
							dataresourceId = {};
						end
						table.insert( dataresourceId, { itemId = itemId, languages = languages, rank = rank} );
					end
				end
			end
		end
	end
	for _, params in pairs( configuration ) do
		local resourceId = params2
		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.datavalue) then
					local itemId = statement.mainsnak.datavalue.value;
					local languages = getQualifierValues( statement, 'P407' );
					if (dataresourceId == nil) then
						dataresourceId = {};
					end
					table.insert( dataresourceId, { itemId = itemId, languages = languages, rank = rank} );
				end
			end
		end
	end
	for resourceId, resourceDatas in pairs( data ) do
		dataresourceId = filterByRank( resourceDatas );
	end
	local hasNonOptionalLinks = false
	for _, params in pairs( configuration ) do
		local resourceId = params2
		local optional = params5 or false;
		local resourceDatas = dataresourceId;
		if resourceDatas ~= nil then
			if ( not optional ) then
				hasNonOptionalLinks = true
			end
			local resourceLabel = renderLabel( params1 );
			local firstChar = mw.ustring.sub( resourceLabel, 1, 1 );
			local separateDesign = firstChar ==  or firstChar == ' 0 ) then
						if moduleLanguages ~= false then -- not false, but maybe nil
							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
						end
						
						if ( moduleLanguages ) then
							for langIndex, language in pairs(languages) do
								html = html .. ' ' .. moduleLanguages.getRefHtml( language )
							end
						end
					end
				end
				preitemId = resourceData.itemId;
			end
			if ( #params >= 4 and params4 ) then
				html = html .. 'Category:' .. params4 .. 
			end
			table.insert( elements, html )
		end
	end
	if ( not hasNonOptionalLinks ) then
		return {}
	end
	return elements
end
function collectDictionaryLinks( elementId )
	--Create rows
	local elements = {}
	local item = mw.wikibase.getEntity( elementId );
	if ( item == nil or item.claims == nil) then
		return elements
	end
	local sourceToElementLinks = {};
	local claim = item.claims'P1343'
	if ( claim ) then
		for _, statement in pairs( claim ) do
			if (statement ~= nil) then
				local rank = statement.rank or 'normal';
				if ( rank ~= 'deprecated' ) then
					local resourceId = statement.mainsnak.datavalue.value.id;
					local languages = getQualifierValues( statement, 'P407' );
					-- Wikisource link ?
					local entityId = getQualifierSingleValue( statement, 'P805' ) or getQualifierSingleValue( statement, 'P248' );
					if ( entityId ) then
						if (sourceToElementLinksresourceId == nil) then
							sourceToElementLinksresourceId = {};
						end
						table.insert( sourceToElementLinksresourceId, { entityId = entityId, languages = languages, rank = rank } );
					end
					-- URL to encyclopedia
					local url = getQualifierSingleValue( statement, 'P953' );
					if (url == nil) then
						-- no longer recommend, but widely used
						url = getQualifierSingleValue( statement, 'P854' ); 
					end
					if ( url ~= nil ) then
						if (sourceToElementLinksresourceId == nil) then
							sourceToElementLinksresourceId = {};
						end
						table.insert( sourceToElementLinksresourceId, { url = url, languages = languages, rank = rank } );
					end
				end
			end
		end
	end
	for _, description in pairs( data.dictionaries ) do
		if ( description.linkF ) then
			local claim = item.claims description.id ;
			if ( claim ) then
				for _, statement in pairs( claim ) do
					local rank = statement.rank or 'normal';
					if ( rank ~= 'deprecated' and statement.mainsnak.datavalue) then
						local value = statement.mainsnak.datavalue.value;
						local url = description.linkF( value );
						local languages = getQualifierValues( statement, 'P407' );
						if ( sourceToElementLinksdescription.id == nil) then
							sourceToElementLinksdescription.id = {};
						end
						table.insert( sourceToElementLinksdescription.id, { url = url, languages = languages, rank = rank} );
					end
				end
			end
		end
	end
	local html = ;
	for _, description in pairs( data.dictionaries ) do
		local links = sourceToElementLinks description.id ;
		if ( links ) then
			for _, link in pairs( links ) do
				if ( link.url ) then
					table.insert( elements,  .. link.url .. ' ' .. description.title ..  );
				end
				if ( link.entityId ) then
					local sitelink = mw.wikibase.getSitelink( link.entityId, description.project );
					if ( sitelink ) then
						table.insert( elements,  .. description.title ..  );
					end
				end
			end
		end
	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 = ;
	local elementId = nil;
	if ( frame ~= nil ) then
		local parentArgs = frame:getParent().args
		colorArg = parentArgstemplateColorName or parentArgs'color' or parentArgs1 or ;
		if parentArgs'from' and parentArgs'from' ~=  then
			elementId = string.upper( parentArgs'from' );
		elseif parentArgs'd' and parentArgs'd' ~=  then
			elementId = string.upper( parentArgs'd' );
		end
		if ( colorArg ~=  ) then
			local firstChar = mw.ustring.sub( colorArg, 1, 1 );
			if ( firstChar ~= '#' ) then
				local byTemplate = colorByTitle( frame, colorArg );
				if ( byTemplate ) then
					colorArg = byTemplate;
				end
			end
		end
	end
	local navboxData = {
		name  = 'Hộp liên kết ngoài',
		navboxclass = 'navbox ruwikiArticleExternalLinksTable',
		bodyclass = 'hlist',
	};
	if colorArg and colorArg ~=  then
		navboxData.groupstyle = 'background: ' .. colorArg .. ';';
	end
	local rowIndex = 1;
	local socialNetworksElements = collectLinks( data.socialNetworkProperties, elementId );
	if ( #socialNetworksElements > 0 ) then
		navboxData'group' .. rowIndex = group1Label;
		navboxData'list' .. rowIndex = table.concat( socialNetworksElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local textsElements = collectLinks( data.textsProperties, elementId );
	if ( #textsElements > 0 ) then
		navboxData'group' .. rowIndex = group2Label;
		navboxData'list' .. rowIndex = table.concat( textsElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local contentHostingElements = collectLinks( data.contentHostingProperties, elementId );
	if ( #contentHostingElements > 0 ) then
		navboxData'group' .. rowIndex = group3Label;
		navboxData'list' .. rowIndex = table.concat( contentHostingElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local themeProfilesElements = collectLinks( data.themeProfilesProperties, elementId );
	if ( #themeProfilesElements > 0 ) then
		navboxData'group' .. rowIndex = group4Label;
		navboxData'list' .. rowIndex = table.concat( themeProfilesElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local dictionaryElements = collectDictionaryLinks( elementId );
	if ( #dictionaryElements > 0 ) then
		navboxData'group' .. rowIndex = group5Label;
		navboxData'list' .. rowIndex = table.concat( dictionaryElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local geniElements = collectLinks( data.geniGraves, elementId );
	if ( #geniElements > 0 ) then
		navboxData'group' .. rowIndex = group6Label;
		navboxData'list' .. rowIndex = table.concat( geniElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
	local taxElements = collectLinks( data.taxons, elementId );
	if ( #taxElements > 0 ) then
		navboxData'group' .. rowIndex = group7Label;
		navboxData'list' .. rowIndex = table.concat( taxElements , ' · ' );
		rowIndex = rowIndex + 1;
	end
-- Hide Authority control line
	-- local authorityControlElements = collectLinks( data.authorityControl, elementId );
	-- local authorityControlExtElements = collectLinks( data.authorityControlExt, elementId );
	-- if ( #authorityControlElements > 0 ) then
	-- 	navboxData'group' .. rowIndex = group8Label;
	-- 	if ( #authorityControlExtElements > 0 ) then
	-- 		navboxData'list' .. rowIndex = table.concat( authorityControlElements , ' · ' ) .. ' · ' .. table.concat( authorityControlExtElements , ' · ' );
	-- 	else
	-- 		navboxData'list' .. rowIndex = table.concat( authorityControlElements , ' · ' );
	-- 	end
	-- 	if ( #authorityControlElements > 5 ) then
	-- 		navboxData'group' .. rowIndex = nil;
	-- 		package.loaded'Module:Navbox' = nil;
	-- 		-- Шаблон:Навигационная таблица/styles.css
	-- 		local templateStyles = frame:extensionTag{ name = 'templatestyles', args = { src = 'Bản mẫu:Hộp điều hướng/styles.css' } };
	-- 		local collapsibleNavbox = require('Module:Navbox')._navbox( { title = group8Label, list1 = navboxData'list' .. rowIndex,
	-- 			border = 'subgroup', navbar = 'plain', state = 'collapsed', titleclass = 'ts-navbox-plaintitle', bodyclass = 'authoritycontrol',
	-- 			titlestyle = navboxData.groupstyle, bodystyle = 'text-align: left;' } );
	-- 		navboxData'list' .. rowIndex = templateStyles .. collapsibleNavbox;
	-- 	end
	-- 	rowIndex = rowIndex + 1;
	-- end
	if ( rowIndex == 1 ) then
		if ( mw.title.getCurrentTitle().namespace == 0 ) then
			return ;
		end
	else
		if navboxData'group1' then
			navboxData'group1' =  ..
				frame:expandTemplate{ title = 'tnavbar-view', args = { templateLink } } .. '  ' ..
				navboxData'group1' .. ;
		else
			navboxData'group1' =  ..
				frame:expandTemplate{ title = 'tnavbar-view', args = { templateLink } } .. ;
		end
	end
	local navbox = moduleNavbox._navbox( navboxData )
	return navbox
end
function p.renderDocumentation()
	local result = 
	result = result .. '
	result = result .. '! colspan=4 | ' .. group1Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.socialNetworkProperties );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group2Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.textsProperties );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group3Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.contentHostingProperties );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group4Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.themeProfilesProperties );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group5Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.dictionaries );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group6Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.geniGraves );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group7Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.taxons );
	result = result .. '
	result = result .. '! colspan=4 | ' .. group8Label .. '\n';
	result = result .. '
	result = result .. renderDocumentationCategory( data.authorityControl );
	return result;
end
function renderDocumentationCategory( links )
	local result = ;
	for _, params in pairs( links ) do
		local resourceLabel = renderLabel( params 1  or params.title );
		local resourceId = params 2  or params.id;
		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 .. '| ' .. resourceId .. '\n';
		else
			result = result .. '|   \n';
		end
		if ( category ~= nil and category ~= false ) then
			result = result .. '| ' .. category .. '\n';
		else
			result = result .. '|   \n';
		end
		result = result .. '| ' .. optional .. '\n';
		result = result .. '
	end
	return result;
end
return p