Module:Property documentation

From Wikidata
Jump to: navigation, search
-- require "Module:No globals"
local p = {}

local i18n = mw.loadData('Module:i18n/property documentation')
local entity, lang, namespace -- the documented property's data table
local fb = require('Module:Fallback')
local d = require('Module:Wikidata')
local datatypemod = require('Module:Datatype')
local linguistic = require('Module:Linguistic')

local function translate(str)
	return mw.language.new(lang):ucfirst(fb.translate(i18n, str, lang))
end

local function set(array)
	local zset = {}
	for _, l in ipairs(array) do zset[l] = true end
	return zset
end

-- list from  https://www.wikidata.org/wiki/Wikidata:Database_reports/List_of_properties/Top100
local freqproperties = set { "P31", "P143", "P248", "P17", "P813", "P21", "P131", "P625", "P569", "P735" }
local prop31279 = set { "P31", "P279" }

local maintenancestr = '' -- maintenance categories etc.
local function addcat(catname)
	if catname then
		maintenancestr = maintenancestr .. '[[Category:' .. catname .. ']]'
	end
end

local function highlightDollarInFormatter(value)
	local split = mw.text.split(value, '$1', true)
	for i = 1, #split do
		split[i] = mw.text.nowiki(split[i])
	end
	return table.concat(split, "'''$1'''")
end

local function showFieldAsEntity(field)
	return function(data)
		return d.showentity(data[field], lang)
	end
end

local rows = {
--[[
		label = name of the message for the header in Module:i18n/property documentation,
		value = value of the line (by default, it gets the value of the parameter with the name of the label),
		query = property to be retrieved from item, or complex query from item,
		required = boolean,
		missingcat     = categorization in case some template data are missing,
		duplicatecat   = categorization in case some template data duplicate property statement data,
		conversioncat  = categorization in case some template data need to be moved to property statement data,
		converttoprop  = property to be used as replacement for template parameter value (defaults to param 'query' if it's a string),
		maintenancecat = categorization in case some other issue gets detected
]]--
	{
		label = 'description',
	},
	{
		label = 'subject item',
		value = showFieldAsEntity('subject item'),
		query = 'P1629',
		missingcat = 'Property documentation missing a subject item',
		duplicatecat = 'Property with duplicated subject item',
		conversioncat = 'Property with subject item to move to statement',
	},
	{
		label = 'associated item',
		query = function(data)
			return d.formatStatements{
				conjtype = 'comma',
				displayformat = 'wikidatastyle',
				entity = entity,
				lang = lang,
				property = {'P2378',  -- "issued by"
						    'P1875',  -- "represented by"
						    'P137' ,  -- "operator"
						    'P126' ,  -- "maintained by"
						    'P127' ,  -- "owned by"
						    'P749' }, -- "parent organization"
				rank = 'valid',
			}
		end,
		maintenancecat = function(data)
			if data['associated item'] then
				return "Property documentation using 'associated item'"
			end
			return nil
		end,
	},
	{
		label = 'has quality',
		query = 'P1552',
	},
	{
		label = 'datatype',
		value = function(data)
			local datatype = data.datatype
			if datatype then
				return datatypemod.display(datatype, lang)
			end
			return nil
		end,
		query = function() return datatypemod.display(entity.datatype, lang) end,
		duplicatecat = 'Property with duplicated datatype',
	},
	{
		label = 'corresponding template',
		query = 'P2667',
	},
	{
		label = 'infobox parameter',
		maintenancecat = function(data)
			if data['infobox parameter'] then
				return "Property documentation using 'infobox parameter'"
			end
			return nil
		end,
	},
	{
		label = 'domain',
	},
	{
		label = 'allowed values',
		query = function()
			if entity.datatype == 'string' or entity.datatype == 'url' or entity.datatype == 'monolingualtext' or
				entity.datatype == 'commonsMedia' or entity.datatype == 'external-id' then
				return d.formatStatements{
					conjtype = '<br />',
					entity = entity,
					lang = lang,
					property = 'P1793',   -- format as a regular expression
					showqualifiers = {'P2315','P2916','P17'}   -- comment, syntax clarif, country
				}
			-- elseif entity.datatype == 'quantity' then --P2312, P2313
			end
			return nil
		end,
		duplicatecat = function()
			if entity.datatype == 'external-id' then
				return 'Property (external-id) with duplicated allowed values'
			else
				return 'Property with duplicated allowed values'
			end
		end,
		conversioncat = function()
			if entity.datatype == 'external-id' then
				return 'Property (external-id) with allowed values to move to statement'
			elseif entity.datatype == 'string' or entity.datatype == 'url' or
				   entity.datatype == 'monolingualtext' or entity.datatype == 'commonsMedia' then
				-- Everything else that uses regex P1793
				return 'Property (string) with allowed values to move to statement'
			else
				return 'Property with allowed values to move to statement'
			end
		end,
		converttoprop = function()
			if entity.datatype == 'external-id' then
				return 'P1793'   -- format as a regular expression
			else
				return nil
			end
		end,
	},
	{
		label = 'allowed units',
		query = function()
			local s = ''
			local units = d.formatStatements{
				entity = entity,
				lang = lang,
				property = 'P2237',
			}
			local unittypes = d.formatStatements{
				entity = entity,
				lang = lang,
				property = 'P2876',
			}
			if unittypes then
			    s = s .. translate('instances of') .. unittypes
			    if units then
			    	s = s .. '<br />'
			    end
			end
			if units then
				s = s .. units
			end
			if s == '' then
				return nil
			else
				return s
			end
		end,
		converttoprop = {'P2237','P2876'},  -- units or types of units
	},
	{
		label = 'usage notes',
		query = function()
			for _, language in ipairs(fb.fblist(lang, true)) do
				local value = d.formatStatements{
					conjtype = '<br />',
					entity = entity,
					isinlanguage = language,
					property = {'P2315','P2559'},   -- comment, Wikidata usage instructions
					rank = 'best',
				}
				if value then
					return value
				end
			end
			return d.formatStatements{
				conjtype = '<br />', entity = entity, rank = 'best',
				property = {'P2315','P2559'},
			}
		end,
		converttoprop = 'P2559',  -- Wikidata usage instructions
	},
	{
		label = 'preferred rank',
		value = showFieldAsEntity('preferred rank'),
		maintenancecat = function(data)
			if data['preferred rank'] then
				return "Property documentation using 'preferred rank'"
			end
			return nil
		end,
	},
	{
		label = 'example',
		query = function()
			local pattern, urlpattern
			if entity.datatype == 'commonsMedia' then -- they all have the same one
				urlpattern = 'https://commons.wikimedia.org/wiki/File:$1'
			elseif entity.datatype == 'string' or entity.datatype == 'external-id' then -- check first whether we need it
				urlpattern = d.formatStatements{ entity = entity, property = 'P1630', rank = 'best', numval = 1 }
			end
			if urlpattern then
				local rdf = d.formatStatements{ entity = entity, property = 'P1921', rank = 'best', numval = 1 }
				if rdf then
					pattern = mw.ustring.format('[%s $1] ([%s %s])', urlpattern, rdf, translate('rdf'))
					urlpattern = nil
				end
			end
			local delimiter = '&#32;' .. mw.getLanguage(lang):getArrow('forwards') .. '&#32;'
			return d.formatStatements{
				conjtype = '<br />',
				delimiter = delimiter,
				displayformat = 'wikidatastyle',
				entity = entity,
				lang = lang,
				pattern = pattern,
				property = {'P1855','P2271'},
				showqualifiers = {entity.id},
				urlpattern = urlpattern,
			}
		end,
		converttoprop = {'P1855','P2271'},  -- property example
		required = true,
		missingcat = 'Property documentation missing an example',
		duplicatecat = 'Property with duplicated example',
		conversioncat = 'Property with example to move to statement',
	},
	{
		label = 'filter',
		value = function(data)
			local arg = data.filter
			if arg then
				local num = tonumber(arg)
				if num and num < 100 then
					local formatNum = require('Module:Formatnum')
					return mw.ustring.format('[[Special:AbuseFilter/%s|%s]]', num,
						mw.ustring.format(translate('abuse filter'), formatNum.formatNum(num, lang)))
				else
					return arg
				end
			end
			return nil
		end,		
		maintenancecat = function(data)
			if data.filter then
				if string.len(data.filter) <= 30 then
					return "Property documentation using 'filter'"
				else
					return "Property documentation using long 'filter'"
				end
			end
			return nil
		end,
	},
	{
		label = 'source',
		query = function()
			local claims = d.getClaims{
				entity = entity,
				property = 'P1896', -- source website
				rank = 'valid',
			}
			if not claims then
				return nil
			end
			for i, statement in ipairs(claims) do
				local showntext = d.getFormattedQualifiers(statement,
					{'P1476'}, -- title
					{ lang = lang })
				claims[i] = d.formatStatement(statement, {
					displayformat = 'weblink',
					lang = lang,
					showntext = showntext,
					showqualifiers = {'P2315'} -- comment
				})
			end
			return linguistic.conj(claims, lang, '<br />')
		end,
		converttoprop = 'P1896',  -- source website
		duplicatecat = 'Property with duplicated source',
		conversioncat = 'Property with source to move to statement',
	},
	{
		label = 'formatter URL',
		value = function(data)
			local val = data['formatter URL']
			if val then
				local append = ''
				if not mw.ustring.match( val, '^https?://' ) then
					append = append .. translate('wrong format')
				end
				if not mw.ustring.match( val, '$1', 7, true ) then
					if append ~= '' then
						append = append .. ', '
					end
					append = append .. mw.ustring.format(translate('missing stuff'), '$1')
				end
				if append ~= '' then
					append = ' – <span style="color: red;">' .. append .. '</span>'
					addcat('Invalid formatter URL')
				end
				return highlightDollarInFormatter(val) .. append
			end
		end,
		query = function()
			if entity.datatype == 'commonsMedia' then
				return highlightDollarInFormatter('https://commons.wikimedia.org/wiki/File:$1')
			end
			local claims = d.getClaims{
				entity = entity,
				property = 'P1630',
				rank = 'valid',
				sorttype = function(first, second)
					return first.rank == 'preferred' and second.rank ~= 'preferred'
				end
			}
			if not claims then
				return nil
			end
			for i, statement in ipairs(claims) do
				claims[i] = d.formatStatement(statement, {})
				claims[i] = highlightDollarInFormatter(claims[i])
				local comment = d.getFormattedQualifiers(statement, {'P2315','P2916'}, { lang = lang })  -- comment, syntax clarif
				local regex = d.getFormattedQualifiers(statement, {'P1793'}, {})
				if comment or regex then
					if regex then
						regex = '[[Q185612|' .. translate('regex') .. ']]' .. linguistic.colon(lang) .. '<code>' .. regex .. '</code>'
					end
					if comment and regex then
						claims[i] = claims[i] .. linguistic.inparentheses(comment .. translate('semicolon') .. regex, lang)
					else
						claims[i] = claims[i] .. linguistic.inparentheses(comment or regex, lang)
					end
				end
			end
			return linguistic.conj(claims, lang, '<br />')
		end,
		converttoprop = 'P1630',  -- formatter URL
		duplicatecat = 'Property with duplicated formatter URL',
		conversioncat = 'Property with formatter URL to move to statement',
	},
	{
		label = 'embed URL',
		value = function(data)
			local val = data['embed URL']
			if val then
				local append = ''
				if not mw.ustring.match( val, '^https?://' ) then
					append = append .. translate('wrong format')
				end
				if not mw.ustring.match( val, '$1', 7, true ) then
					if append ~= '' then
						append = append .. ', '
					end
					append = append .. mw.ustring.format(translate('missing stuff'), '$1')
				end
				if append ~= '' then
					append = ' – <span style="color: red;">' .. append .. '</span>'
					addcat('Invalid formatter URL')
				end
				return highlightDollarInFormatter(val) .. append
			end
		end,
		query = function()
			if entity.datatype == 'commonsMedia' then
				return highlightDollarInFormatter('https://commons.wikimedia.org/wiki/File:$1')
			end
			local claims = d.getClaims{
				entity = entity,
				property = 'P2720',
				rank = 'valid',
				sorttype = function(first, second)
					return first.rank == 'preferred' and second.rank ~= 'preferred'
				end
			}
			if not claims then
				return nil
			end
			for i, statement in ipairs(claims) do
				claims[i] = d.formatStatement(statement, {})
				claims[i] = highlightDollarInFormatter(claims[i])
				local comment = d.getFormattedQualifiers(statement, {'P2315','P2916'}, { lang = lang })
				local regex = d.getFormattedQualifiers(statement, {'P1793'}, {})
				if comment or regex then
					if regex then
						regex = '[[Q185612|' .. translate('regex') .. ']]' .. linguistic.colon(lang) .. '<code>' .. regex .. '</code>'
					end
					if comment and regex then
						claims[i] = claims[i] .. linguistic.inparentheses(comment .. translate('semicolon') .. regex, lang)
					else
						claims[i] = claims[i] .. linguistic.inparentheses(comment or regex, lang)
					end
				end
			end
			return linguistic.conj(claims, lang, '<br />')
		end,
		converttoprop = 'P2720',  -- embed URL
		duplicatecat = 'Property with duplicated formatter URL',
		conversioncat = 'Property with formatter URL to move to statement',
	},
	{
		label = 'robot and gadget jobs',
		maintenancecat = function(data)
			if data['robot and gadget jobs'] then
				if string.len(data['robot and gadget jobs']) <= 30 then
					return "Property documentation using 'robot and gadget jobs'"
				else
					return "Property documentation using long 'robot and gadget jobs'"
				end
			end
			return nil
		end,
	},
	{
		label = 'track same cat',
		value = showFieldAsEntity('track same cat'),
		query = 'P3734',  -- category for value same as Wikidata
	},
	{
		label = 'track diff cat',
		value = showFieldAsEntity('track diff cat'),
		query = 'P3709',  -- category for value different from Wikidata
	},
	{
		label = 'track usage cat',
		value = showFieldAsEntity('track usage cat'),
		query = 'P2875',  -- property usage tracking category
	},
	{
		label = 'track local no-WD yes',
		value = showFieldAsEntity('track local no-WD yes'),
	},
	{
		label = 'track local yes-WD no',
		value = showFieldAsEntity('track local yes-WD no'),
		query = 'P3713',  -- category for value not in Wikidata
	},
	{
		label = 'track local no-WD no',
		value = showFieldAsEntity('track local no-WD no'),
	},
	{
		label = 'track avail both cat',
		value = showFieldAsEntity('track avail both cat'),
	},
	{
		label = 'related2country',
		query = function(data)
			local country = d.formatStatements{ entity = entity, property = 'P17', lang = lang, displayformat = 'wikidatastyle', conjtype = 'comma' }
			local jurisdiction = d.formatStatements{ entity = entity, property = 'P1001', lang = lang, displayformat = 'wikidatastyle', conjtype = 'comma' }
			if country and jurisdiction then
				country = country .. linguistic.inparentheses(jurisdiction, lang)
			end
			return country
		end,
		converttoprop = {'P17','P1001'},  -- country, jurisdiction
	},
	{
		label = 'seealso',
		query = 'P1659',
	},
	{
		label = 'lists',
		value = function(data)
			-- Use template field, if set
			local append = data.lists or ''
			-- Get P2354 "has list" property, if any
			local val = d.formatStatements{ entity = entity, lang = lang, displayformat = 'wikidatastyle', conjtype = '<br />', property = 'P2354' }
			if val then
				append = append .. '\n*' .. val
			end

			local linkText = translate("items with novalue claims")
			local linkURL = "https://query.wikidata.org/#%23Items%20with%20statements%20where%20property%20" .. entity.id .. "%20uses%20the%20novalue%20special%20value%0A%23by%20Jura1%2C%202015-02-27%0ASELECT%20%09%0A%09%3Fitem%20%3FitemLabel%20%0A%09%28GROUP_CONCAT%28%3FinstanceLabel%3B%20separator%3D%22%2C%20%22%29%20as%20%3FinstanceLabels%29%0AWHERE%20%09%0A{%0A%09%3Fitem%20p%3A" .. entity.id .. "%2Fa%20wdno%3A" .. entity.id .. "%0A%09OPTIONAL%20{%3Fitem%20wdt%3AP31%20%3Finstance}%0A%09SERVICE%20wikibase%3Alabel%20{%20%09bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%2Cru%2Cja%2Czh%22%20.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%3Fitem%20rdfs%3Alabel%20%3FitemLabel%20.%20%3Finstance%20rdfs%3Alabel%20%3FinstanceLabel%20}%0A}%0AGROUP%20BY%20%3Fitem%20%3FitemLabel%0ALIMIT%20100"
			append = append .. '\n* [' .. linkURL .. ' ' .. linkText .. ']'

			linkText = translate("items with somevalue claims")
			linkURL = "https://query.wikidata.org/#%23Items%20with%20statements%20where%20property%20" .. entity.id .. "%20uses%20the%20somevalue%2Fanyvalue%20special%20value%0ASELECT%20%09%0A%09%3Fitem%20%3FitemLabel%20%0A%09%28GROUP_CONCAT%28%3FinstanceLabel%3B%20separator%3D%22%2C%20%22%29%20as%20%3FinstanceLabels%29%0AWHERE%20%09%0A{%0A%20%20%09%3Fitem%20wdt%3A" .. entity.id .. "%20%3Fvalue%20.%20%0A%20%20%09FILTER%20%28isBlank%28%3Fvalue%29%29%20%20%20%20%20%20%20%20%20%20%20%0A%09OPTIONAL%20{%3Fitem%20wdt%3AP31%20%3Finstance}%0A%09SERVICE%20wikibase%3Alabel%20{%20%09bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%2Cru%2Cja%2Czh%22%20.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%3Fitem%20rdfs%3Alabel%20%3FitemLabel%20.%20%3Finstance%20rdfs%3Alabel%20%3FinstanceLabel%20}%0A}%0AGROUP%20BY%20%3Fitem%20%3FitemLabel%0ALIMIT%20100"
			append  = append .. '\n* [' .. linkURL .. ' ' .. linkText .. ']'

			if entity.datatype == 'time' then
				linkText = translate("future dates")
				linkURL = "https://query.wikidata.org/#SELECT%20%3Fsubject%20%3FsubjectLabel%20%3Finstance%20%3FinstanceLabel%20%28year%28%3Fdate%29%20as%20%3Fyear%29%20%3Fdate%20%20WHERE%20{%20%0A%20%20%20%3Fsubject%20p%3A" .. entity.id .. "%2Fpsv%3A" .. entity.id .. "%20%3Fdate_node%20.%0A%20%20%20%3Fdate_node%20wikibase%3AtimeValue%20%3Fdate%20.%0A%20%20%20FILTER%20%28%28%3Fdate%29%20%3E%3D%20%28now%28%29%29%29%20.%20%20%0A%20%20%20%3Fsubject%20wdt%3AP31%20%3Finstance%20.%0A%20%20SERVICE%20wikibase%3Alabel%20{%0A%20%20%20%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20.%0A%20%20}%0A}%0AORDER%20BY%20DESC%28%3Fdate%29%20%20%20%20%20%0ALIMIT%20100"
				append = append .. '\n* [' .. linkURL .. ' ' .. linkText .. ']'
			
				linkText = translate("dates in Gregorian calendar before 1582")
				linkURL = "https://query.wikidata.org/#%23Dates%20before%201582%20in%20Gregorian%20calendar%20%28date%20precision%20%3E%209%29%0A%23added%202016-02-26%2C%20based%20on%20a%20query%20by%20Mbch331%0ASELECT%20%3Fitem%20%3FitemLabel%20%3Fdate%20%0A{%0A%09{%09SELECT%20%3Fitem%20%3Fdate%20%0A%09%09{%0A%09%09%09%3Fitem%20p%3A" .. entity.id .. "%2Fpsv%3A" .. entity.id .. "%20%3Fdatevalue%20.%0A%20%20%20%20%09%09%3Fdatevalue%20wikibase%3AtimeValue%20%3Fdate%20.%20%20%20%20%20%20%20%20%20%20%20%0A%09%09%09FILTER%28%3Fdate%20%3C%20%22%2B1582-10-15T00%3A00%3A00Z%22^^xsd%3AdateTime%29%0A%09%09%09%3Fdatevalue%20wikibase%3AtimePrecision%20%3Fdateprecision%20.%20%0A%09%09%09FILTER%28%3Fdateprecision%20%3E%209%29%0A%09%09%09%3Fdatevalue%20wikibase%3AtimeCalendarModel%20wd%3AQ1985727%20.%0A%09%09}%0A%20%20%20%20%20%20%20%20LIMIT%205000%0A%20%20%20%20}%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20}%0A}"
				append = append .. '\n* [' .. linkURL .. ' ' .. linkText .. ']'
				
				linkText = translate("dates before year 1")
				linkURL = "https://query.wikidata.org/#%23Dates%20before%20year%201%20with%20precision%20%3E8%3A%20year%2C%20month%2C%20day%0A%23added%202016-08-07%2C%20Jura1%0ASELECT%20%3Fitem%20%3FitemLabel%20%28%3Fdate%20as%20%3FGregorianDate%29%20%28CONCAT%28str%281%2BYEAR%28%3Fdate%29%2a-1%29%2C%20%22%20BC%22%29%20as%20%3FyearBC%29%20%3Fdateprec%20%3FdateprecisionLabel%20%3FinputcalendarmodelLabel%0A%7B%0A%09%7B%09SELECT%20%3Fitem%20%3Fdate%20%28xsd%3Adecimal%28%3Fprecision%29%20as%20%3Fdateprec%29%20%3Finputcalendarmodel%0A%09%09%7B%0A%09%09%09%3Fitem%20p%3A" .. entity.id .. "%20%3Fd%20.%20%0A%20%20%20%20%20%20%20%20%20%20%09%3Fd%20psv%3A" .. entity.id .. "%20%3Fdatevalue%20.%0A%20%20%20%20%09%09%3Fdatevalue%20wikibase%3AtimeValue%20%3Fdate%20.%20%20%20%20%20%20%20%20%20%20%20%09FILTER%28%3Fdate%20%3C%20%22%2B1-00-00T00%3A00%3A00Z%22%5E%5Exsd%3AdateTime%29%0A%09%09%09%3Fdatevalue%20wikibase%3AtimePrecision%20%3Fprecision%20.%20%09%09FILTER%28%3Fprecision%20%3E%208%29%0A%09%09%09%3Fd%20wikibase%3Arank%20%3Frank%20.%09%09%09%09%09%09%09FILTER%28%3Frank%20%21%3D%20wikibase%3ADeprecatedRank%29%0A%09%09%09%3Fdatevalue%20wikibase%3AtimeCalendarModel%20%3Finputcalendarmodel%20.%0A%09%09%7D%0A%20%20%20%20%20%20%20%20LIMIT%205000%0A%20%20%20%20%7D%0A%20%20%09%3Fdateprecision%20wdt%3AP2803%20%3Fdateprec%0A%09SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%2Cla%22%20%7D%0A%7D%0AORDER%20BY%20DESC%28%3Fdate%29"
				append = append .. '\n* [' .. linkURL .. ' ' .. linkText .. '] ([[Help:Dates#Years BC]])'
			end

			linkURL = d.formatStatements{
				entity = entity,
				property = 'P2264',
				showntext = translate('mixnmatch'),
				urlpattern = 'https://tools.wmflabs.org/mix-n-match/?mode=catalog_details&catalog=$1'
			}
			if linkURL then
				append = append .. '\n* ' .. linkURL
			end

			local frame = mw.getCurrentFrame()

			append = append
				.. frame:preprocess('{{#ifexist:Wikidata:Database_reports/Recent_deaths/missing/{{PAGENAME}}|* [[Wikidata:Database_reports/Recent_deaths/missing/{{PAGENAME}}|Database reports/Recent_deaths/missing/{{PAGENAME}}]]}}')
				.. frame:preprocess('{{#ifexist:User:Laboramus/Units/{{PAGENAME}}|* [[User:Laboramus/Units/{{PAGENAME}}|User:Laboramus/Units/{{PAGENAME}}]]' .. linguistic.inparentheses(translate('units used'), lang) .. '}}')
				.. frame:preprocess('{{#ifexist:Wikidata:Database_reports/Complex_constraint_violations/{{PAGENAME}}|* [[Wikidata:Database_reports/Complex_constraint_violations/{{PAGENAME}}|Database reports/Complex constraint violations/{{PAGENAME}}]]}}')
				.. frame:preprocess('{{#ifexist:Wikidata:Database_reports/Humans_with_missing_claims/{{PAGENAME}}|* [[Wikidata:Database reports/Humans with missing claims/{{PAGENAME}}|Database reports/Humans with missing claims/{{PAGENAME}}]]}}')
				.. frame:preprocess('{{#ifexist:Wikidata:Database_reports/Constraint_violations/{{PAGENAME}}|* [[Wikidata:Database_reports/Constraint_violations/{{PAGENAME}}|Database reports/Constraint violations/{{PAGENAME}}]]}}')

			return append
		end,
		maintenancecat = function(data)
			if data.lists then
				return "Property documentation using 'lists'"
			end
			return nil
		end,
	},
	{
		label = 'proposal discussion',
		value = function(data)
			local arg = data['proposed by'] or data.subpage
			if arg then
				if string.lower(arg) == 'none' then
					return translate('no discussion')
				end
				local link = 'Property proposal/'
				if tonumber(arg) then
					link = link .. 'Archive/' .. arg .. '#' .. entity.id
				else
					link = link .. arg
				end
				if not mw.title.new(link, 'Wikidata') then
					return arg
				end
				return '[[Wikidata:' .. link .. '|' .. link .. ']]'
			end
			return arg
		end,
		maintenancecat = function(data)
			if data['proposed by'] and data.subpage then
				return 'Property documentation with unclear link to its proposal discussion'
			end
			local arg = data['proposed by'] or data.subpage
			if arg then
				if string.lower(arg) == 'none' then
					return 'Property originally created without a formal discussion'
				end
				local link
				if tonumber(arg) then
					link = 'Property proposal/Archive/' .. arg
				else
					link = 'Property proposal/' .. arg
				end
				local title = mw.title.new(link, 'Wikidata')
				if not title or not title.exists then
					return 'Property documentation with malformed link to its proposal discussion'
				end
			end
			return nil
		end,
		required = true,
		missingcat = 'Property documentation missing a link to its proposal discussion',
	},
	{
		label = 'current uses',
		value = function()
			local frame = mw.getCurrentFrame()
			local value = tonumber( frame:expandTemplate{ title = 'Property uses', args = { string.sub(entity.id, 2) } } )
			if value and value > 0 then
				addcat(mw.ustring.format('Properties used on %s+ items', 10 ^ math.floor(math.log10(value))))
				local formatNum = require('Module:Formatnum')
				return formatNum.formatNum(value, lang)
			end
			addcat('Unused properties')
			return nil
		end,
	},
}

local function buildHeaderLinksString(id, forQualifierUse)
	local queries = {}
	local linkText, linkURL

	if not forQualifierUse then
		linkText = translate("basic item query")
		linkURL = "https://query.wikidata.org/#PREFIX%20wd%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fentity%2F%3E%0APREFIX%20wdt%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fdirect%2F%3E%0APREFIX%20wikibase%3A%20%3Chttp%3A%2F%2Fwikiba.se%2Fontology%23%3E%0APREFIX%20p%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2F%3E%0APREFIX%20ps%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fstatement%2F%3E%0APREFIX%20pq%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fqualifier%2F%3E%0APREFIX%20rdfs%3A%20%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0A%23Sample%20query%20to%20start%20a%20list%20of%20values%20for%20property%20" .. id .. "%0A%23Remove%20some%20of%20the%20%22%23%22%20below%20to%20see%20if%20it%20helps%20you%0A%0ASELECT%20%3Fitem%20%3FitemLabel%20%3Fvalue%20%3FvalueLabel%20%0A%23sample%20variables%20defined%20below%20%28but%20commented%20out%29%0A%3Fdob%20%3Fdod%20%3Fcountry%0AWHERE%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Fvalue%20.%0A%23%09%3Fitem%20wdt%3AP569%20%3Fdob%20.%20%0A%23%09OPTIONAL%20{%3Fitem%20wdt%3AP570%20%3Fdod%20}%20.%20%0A%23%09%3Fitem%20wdt%3AP17%20%3Fcountry%20.%20%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20%20}%20%20%20%20%0A}%0ALIMIT%2010"
		table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

		linkText = "Current uses"
		linkURL = "https://query.wikidata.org/#SELECT%20%3Fitem%20%3FitemLabel%20%3Fvalue%20%3FvalueLabel%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Fvalue%20.%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20%20}%20%20%20%20%0A}%0ALIMIT%201000"
		table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

		if not prop31279[id] then
			linkText = translate("counts by class")
			linkURL = "https://query.wikidata.org/#%23top%2050%20for%20P31%20and%20P279%20of%20items%20using%20" .. id .. "%0ASELECT%20%3Fclass%20%3FclassLabel%20%3Fcount%20%3Fuse_as_Label%0A{%09{%09SELECT%20%3Fclass%20%28COUNT%28*%29%20AS%20%3Fcount%29%20%28wd%3AP31%20as%20%3Fuse_as_%29%0A%09%09{%09%3Fa%09wdt%3A" .. id .. "%09%3Fp%09%3B%20wdt%3AP31%09%3Fclass}%0A%20%20%20%20%20%20%20%20GROUP%20BY%20%3Fclass%20ORDER%20BY%20DESC%28%3Fcount%29%20LIMIT%2050%0A%20%20%09}%0A%20%20%09UNION%0A%09{%09SELECT%20%3Fclass%20%28COUNT%28*%29%20AS%20%3Fcount%29%20%28wd%3AP279%20as%20%3Fuse_as_%29%0A%09%09{%09%3Fa%09wdt%3A" .. id .. "%09%3Fp%09%3B%20wdt%3AP279%09%3Fclass}%0A%20%20%20%20%20%20%20%20GROUP%20BY%20%3Fclass%20ORDER%20BY%20DESC%28%3Fcount%29%20LIMIT%2050%0A%20%20%09}%0A%20%20%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20}%0A}%0AORDER%20BY%20DESC%28%3Fcount%29%20%3Fclass"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'wikibase-item' then
			linkText = translate("value list")
			linkURL = "https://query.wikidata.org/#SELECT%20%3Fcid%20%3Fvalue%20%3Fcount%20WHERE%20%7B%0A%20%20%7B%0A%20%20%20%20SELECT%20%3Fcid%20(count(*)%20as%20%3Fcount)%20WHERE%20%7B%0A%20%20%20%20%20%20%3Fpid%20wdt%3A" .. id .. "%20%3Fcid%20.%0A%20%20%20%20%7D%0A%20%20%20%20GROUP%20BY%20%3Fcid%0A%20%20%7D%20.%0A%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fcid%20rdfs%3Alabel%20%3Fvalue%20filter%20(lang(%3Fvalue)%20%3D%20%22" .. lang .. "%22)%20.%0A%20%20%7D%0A%7D%0AORDER%20BY%20DESC(%3Fcount)%20ASC(%3Fvalue)%0ALIMIT%201000"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'time' then
			linkText = translate("by century")
			linkURL = "https://query.wikidata.org/#%23Number%20of%20dates%20per%20period%20of%20100%20years%0A%23by%20Jura1%2C%202016-01-26%0A%0ASELECT%20%3Fcentury%20%28COUNT%28%3Fitem%29%20as%20%3Fcount%29%0AWHERE%20%0A{%09%0A%20%20%3Fitem%20wdt%3A" .. id .. "%20%3Fdate%20.%0A%20%20BIND%28ROUND%28YEAR%28%3Fdate%29%2F100%29*100%20as%20%3Fcentury%29%0A}%20%0AGROUP%20BY%20%3Fcentury%0AORDER%20BY%20DESC%28%3Fcentury%29"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

			linkText = translate("date precisions")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202016-05-04%0ASELECT%20%3Fcount%20%3Fdatetime_precision_label%20%3Fdatetime_precision%20%0A{%0A%09{%0A%09%09SELECT%20%3Fdatetime_precision%20%28count%28DISTINCT%28%3Fnode%29%29%20as%20%3Fcount%29%0A%09%09{%09%0A%20%20%09%09%09%3Fnode%20psv%3A" .. id .. "%2Fwikibase%3AtimePrecision%20%3Fdatetime_precision%0A%09%09}%20%0A%09%09GROUP%20BY%20%3Fdatetime_precision%0A%09}%0A%09%3Fitem%20wdt%3AP2803%20%3Fvalue%0A%09FILTER%20%28%3Fdatetime_precision%20%3D%20%3Fvalue%29%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20.%20%3Fitem%20rdfs%3Alabel%20%3Fdatetime_precision_label%20%20}%20%20%20%20%0A}%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2010"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

			linkText = translate("calendars")
			linkURL = "https://query.wikidata.org/#SELECT%20%3Fcalendar%20%28count%28*%29%20as%20%3Fcount%29%0AWHERE%20{%09%0A%20%20%3Fdateproperty%20psv%3A" .. id .. "%2Fwikibase%3AtimeCalendarModel%20%3Fcalendar.%0A}%20%0AGROUP%20BY%20%3Fcalendar%0AORDER%20BY%20DESC%28%3Fcount%29"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'external-id' or entity.datatype == 'string' or entity.datatype == 'monolingualtext' then
			linkText = translate("string lengths")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202016-01-24%0A%0ASELECT%20%3Fstringlength%20%28COUNT%28DISTINCT%28%3Fstringvalue%29%29%20AS%20%3Fcount%29%20%0AWHERE%20%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Fstringvalue%20.%0A%20%20%20%20BIND%28strlen%28%3Fstringvalue%29%20as%20%3Fstringlength%29%0A}%0AGROUP%20BY%20%3Fstringlength%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2010"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'monolingualtext' then
			linkText = translate("languages of strings")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202016-01-24%0A%0ASELECT%20%3Flang%20%28COUNT%28DISTINCT%28%3Fmonolingualstring%29%29%20as%20%3Fcount%29%20%20%0AWHERE%20%0A{%20%0A%20%20%3Fitem%20wdt%3A" .. id .. "%20%3Fmonolingualstring%20.%20%0A%20%20BIND%28lang%28%3Fmonolingualstring%29%20as%20%3Flang%29%20%0A}%20%0AGROUP%20BY%20%3Flang%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2050"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'quantity' then
			linkText = translate("units")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202016-01-24%0A%0ASELECT%20%3Funit%20%3FunitLabel%20%3Fcount%0AWHERE%0A{%0A%09{%0A%20%20%09%09SELECT%20%3Funit%20%28count%28DISTINCT%28%3Fitem%29%29%20as%20%3Fcount%29%0A%09%09WHERE%20%0A%09%09{%09%0A%20%20%09%09%3Fitem%20psv%3A" .. id .. "%2Fwikibase%3AquantityUnit%20%3Funit%0A%09%09}%20%0A%09%09GROUP%20BY%20%3Funit%0A%09}%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20}%0A}%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2010%0A"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

			linkText = translate("scale of values")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202015-01-25%0A%23scales%3A%20%3C1%3D%3C1%2C%201%3D1-9%2C%202%3D10-99%2C%203%3D100-999%2C%20etc.%0A%0ASELECT%20%3Fscale%20%28COUNT%28%3Fquantityvalue%29%20AS%20%3Fcount%29%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Fquantityvalue%20.%0A%20%20%20%20BIND%28strlen%28STR%28ROUND%28%3Fquantityvalue%29%29%29%20as%20%3Flength%29%0A%20%20%20%20BIND%28IF%28%3Fquantityvalue%3C1%2C%22%3C1%22%2C%3Flength%29%20%09as%20%3Fscale%29%0A}%0AGROUP%20BY%20%3Fscale%0AORDER%20BY%20%3Fscale%0ALIMIT%20100"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'url' then
			linkText = translate("protocol")
			linkURL = "https://query.wikidata.org/#SELECT%20%3Fprotocol%20%28COUNT%28%3Fitem%29%20as%20%3Fcount%29%20%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fcountdistinct%29%0AWHERE%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Fvalue%20.%0A%20%20%09BIND%28strbefore%28%20str%28%3Fvalue%29%2C%20%22%3A%22%29%20as%20%3Fprotocol%29%0A}%0AGROUP%20BY%20%3Fprotocol%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2010"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		if entity.datatype == 'commonsMedia' then
			linkText = translate("file extensions")
			linkURL = "https://query.wikidata.org/#%23by%20Jura1%2C%202016-01-24%0A%0ASELECT%20%3Fextension%20%28COUNT%28DISTINCT%28%3Ffilename%29%29%20AS%20%3Fcount%29%20WHERE%20%0A{%0A%09%3Fitem%20wdt%3A" .. id .. "%20%3Ffilename%20.%0A%20%20%20%20BIND%28fn%3Alower-case%28REPLACE%28str%28%3Ffilename%29%2C%20%27%28.%2B%3F%29.%28\\u005B^.\\u005D*%24%29%27%2C%20%22%242%22%29%29%20AS%20%3Fextension%29%0A}%0AGROUP%20BY%20%3Fextension%0AORDER%20BY%20DESC%28%3Fcount%29%0ALIMIT%2010"
			table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
		end

		linkText = translate("qualifiers")
		linkURL = "https://query.wikidata.org/#SELECT%20%3Fqual%20%3FqualLabel%20%3Fcount%20WHERE%20%7B%0A%20%20%7B%0A%20%20%20%20SELECT%20%3Fqual%20(COUNT(DISTINCT%20%3Fitem)%20AS%20%3Fcount)%20WHERE%20%7B%0A%20%20%20%20%20%20%20%20%20hint%3AQuery%20hint%3Aoptimizer%20%22None%22%20.%0A%20%20%20%20%20%20%20%20%20%3Fitem%20p%3A" .. id .. "%20%3Fstatement%20.%0A%20%20%20%20%20%20%20%20%20%3Fstatement%20%3Fpq_qual%20%3Fpq_obj%20.%0A%20%20%20%20%20%20%20%20%20%3Fqual%20wikibase%3Aqualifier%20%3Fpq_qual%20.%0A%20%20%20%20%7D%20%20GROUP%20BY%20%3Fqual%0A%20%20%7D%20.%0A%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fqual%20rdfs%3Alabel%20%3FqualLabel%20filter%20(lang(%3FqualLabel)%20%3D%20%22" .. lang .. "%22)%20.%0A%20%20%7D%0A%7D%0AORDER%20BY%20DESC(%3Fcount)%20ASC(%3FqualLabel)"
		table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')
	else
		--- for qualifiers

		linkText = translate("basic item query")
		linkURL = "https://query.wikidata.org/#PREFIX%20wd%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fentity%2F%3E%0APREFIX%20wdt%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fdirect%2F%3E%0APREFIX%20wikibase%3A%20%3Chttp%3A%2F%2Fwikiba.se%2Fontology%23%3E%0APREFIX%20p%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2F%3E%0APREFIX%20ps%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fstatement%2F%3E%0APREFIX%20pq%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fqualifier%2F%3E%0APREFIX%20rdfs%3A%20%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0A%23Sample%20query%20to%20start%20a%20list%20of%20statements%20using%20the%20qualifer%20" .. id .. "%0A%0ASELECT%20%3Fitem%20%3FitemLabel%20%3Fproperty%20%3FpropertyLabel%20%3Fvalue%20%3FvalueLabel%20%3Fqualifier" .. id .. "value%0AWHERE%0A{%0A%20%20%20%20%3Fprop%20pq%3A" .. id .. "%20%3Fqualifier" .. id .. "value%20.%0A%20%20%09hint%3AQuery%20hint%3Aoptimizer%20%22None%22%20.%09%0A%09%3Fitem%20%3Fp%20%3Fprop%20.%20%0A%09%3Fproperty%20wikibase%3Aclaim%20%3Fp%20.%20%20%0A%20%20%09%3Fproperty%20wikibase%3AstatementProperty%20%3Fps%20.%0A%20%20%20%20%3Fprop%20%3Fps%20%3Fvalue%20.%20%20%20%20%20%20%0A%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22" .. lang .. "%2Cen%22%20%20}%20%20%20%20%0A}%0ALIMIT%2020"
		table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

		linkText = translate("properties using this qualifier")
		linkURL = "https://query.wikidata.org/#%23Number%20of%20items%2Fstatements%20using%20qualifer%20" .. id .. "%20for%20each%20property%0A%23added%202016-02-24%20by%20Jura1%20%0A%0ASELECT%20%3Fproperty%20%3FpropertyLabel%20%3Fitems%20%3Fstatements%0AWHERE%0A{%0A%09{%0A%09%09SELECT%20%3Fproperty%20%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems%29%20%28COUNT%28%3Fvalue%29%20as%20%3Fstatements%29%0A%09%09WHERE%0A%09%09{%0A%20%20%20%20%09%09%3Fprop%20pq%3A" .. id .. "%20%3Fqualifier" .. id .. "value%20.%0A%20%20%09%09%09hint%3AQuery%20hint%3Aoptimizer%20%22None%22%20.%09%0A%09%09%09%3Fitem%20%3Fp%20%3Fprop%20.%20%0A%09%09%09%3Fproperty%20wikibase%3Aclaim%20%3Fp%20.%20%20%0A%20%20%09%09%09%3Fproperty%20wikibase%3AstatementProperty%20%3Fps%20.%0A%20%20%20%20%09%09%3Fprop%20%3Fps%20%3Fvalue%20.%20%20%20%20%20%20%0A%09%09}%0A%09%09GROUP%20BY%20%3Fproperty%20%0A%09%09ORDER%20BY%20DESC%28%3Fitems%29%20DESC%28%3Fstatements%29%0A%09%09LIMIT%2025%0A%09}%0A%09SERVICE%20wikibase%3Alabel%20{%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%2Cen%22%20%20}%20%20%20%20%0A}%0AORDER%20BY%20DESC%28%3Fitems%29%20DESC%28%3Fstatements%29%0A%0A%0A"
		table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

	end

	linkText = translate("counts")

	if freqproperties[id] then
		linkURL = "https://query.wikidata.org/#%23Uses%20of%20" .. id .. "%3A%09as%20property%20%28any%20rank%2Fbest%20rank%29.%20For%20performance%20reasons%2C%20detailed%20counts%20by%20rank%20are%20not%20included.%0A%23%09%09%09%09as%20qualifier%0A%23%09%09%09%09in%20references%0A%23by%20Jura1%2C%20rev%202016-03-03%0ASELECT%09%3Fuse%20%3Frank%20%3Fitems_with_property%09%3Fuses_of_property%0AWHERE{%09{%09%09SELECT%20%09%28wikibase%3AstatementProperty%20as%20%3Fuse%29%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%09%09%09%09WHERE%09{%3Fitem%20p%3A" .. id .. "%20%3Fvalue}}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3AstatementProperty%20as%20%3Fuse%29%09%28wikibase%3ABestRank%20as%20%3Frank%29%09%28COUNT%28DISTINCT%28%3Fitem%29%29%09as%20%3Fitems_with_property%29%09%28COUNT%28%3Fbestvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20wdt%3A" .. id .. "%20%3Fbestvalue%20}%20}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3Areference%20as%20%3Fuse%29%09%09%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20pr%3A" .. id .. "%20%3Fvalue%20}}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3Aqualifier%20as%20%3Fuse%29%09%09%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20pq%3A" .. id .. "%20%3Fvalue%20}}%0A}%0AORDER%20BY%20DESC%28%3Fuse%29%20DESC%28%3Fitems_with_property%29%20%3Frank%0A%0A%23PLEASE%20NOTE%3A%20Deleted%20items%20appear%20in%20counts%20for%20some%20ranks%2C%20but%20not%20in%20others."
	else
		linkURL = "https://query.wikidata.org/#%23Uses%20of%20" .. id .. "%3A%09as%20property%20%28any%20rank%2Fbest%20rank%2Fnormal%20rank%2Fpreferred%20rank%2Fdeprecated%20rank%29%0A%23%09%09%09%09as%20qualifier%0A%23%09%09%09%09in%20references%0A%23by%20Jura1%2C%20rev%202016-03-03%0ASELECT%09%3Fuse%20%3Frank%20%3Fitems_with_property%09%3Fuses_of_property%0AWHERE{%09{%09%09SELECT%20%09%28wikibase%3AstatementProperty%20as%20%3Fuse%29%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%09%09%09%09WHERE%09{%3Fitem%20p%3A" .. id .. "%20%3Fvalue}}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3AstatementProperty%20as%20%3Fuse%29%09%28wikibase%3ABestRank%20as%20%3Frank%29%09%28COUNT%28DISTINCT%28%3Fitem%29%29%09as%20%3Fitems_with_property%29%09%28COUNT%28%3Fbestvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20wdt%3A" .. id .. "%20%3Fbestvalue%20}%20}%0AUNION%20%09{%09%09SELECT%20%20%28wikibase%3AstatementProperty%20as%20%3Fuse%29%09%3Frank%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%28%3Fstatement%29%29%20as%20%3Fuses_of_property%29%20%0A%09%09%09%09WHERE%09{%3Fitem%20p%3A" .. id .. "%20%3Fstatement%20.%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Fstatement%20wikibase%3Arank%20%3Frank%20}%0A%09%09%09%09%09%09GROUP%20BY%20%3Frank%20}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3Areference%20as%20%3Fuse%29%09%09%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20pr%3A" .. id .. "%20%3Fvalue%20}}%0AUNION%09{%09%09SELECT%20%09%28wikibase%3Aqualifier%20as%20%3Fuse%29%09%09%09%28COUNT%28DISTINCT%28%3Fitem%29%29%20as%20%3Fitems_with_property%29%09%28COUNT%28%3Fvalue%29%20as%20%3Fuses_of_property%29%0A%20%20%20%20%20%09%09%09WHERE%20%09{%3Fitem%20pq%3A" .. id .. "%20%3Fvalue%20}}%0A}%0AORDER%20BY%20DESC%28%3Fuse%29%20DESC%28%3Fitems_with_property%29%20%3Frank%0A%0A%23PLEASE%20NOTE%3A%20Deleted%20items%20appear%20in%20counts%20for%20some%20ranks%2C%20but%20not%20in%20others."
	end
	table.insert(queries, '[' .. linkURL .. ' ' .. linkText .. ']')

	return '<span class="plainlinks">' .. table.concat(queries, ' – ') .. '</span>'
end

local function makerow(rowparams, data)
	local label = rowparams.label
	if not label then
		return error("No label defined")
	end

	-- get value from template
	local templateval
	local templatequery = rowparams.value
	if templatequery and type(templatequery) == 'function' then
		templateval = templatequery(data)
	else
		templateval = data[label] -- by default parameter name = label name
	end

	-- get value from item properties
	local itemval, itemquery
	if entity then
		itemquery = rowparams.query
		if type(itemquery) == 'string' then
			itemval = d.formatStatements{ entity = entity, property = itemquery, lang = lang, displayformat = 'wikidatastyle', conjtype = 'comma' }
		elseif type(itemquery) == 'function' then
			itemval = itemquery()
		end
	end

	local val = templateval or itemval
	if templateval then
		if itemval then
			-- Warn that info in the template parameter duplicates info from some property statement
			val = '<div>' .. translate('local data') .. '\n' .. templateval
				.. '</div>\n<div>' .. translate('property data') .. '<br />' .. itemval
				.. '</div>\n<b>' .. translate('notice') .. '</b>'
			local dupcat = 'Property with duplicated information'
			if rowparams.duplicatecat then
				if type(rowparams.duplicatecat) == 'function' then
					dupcat = rowparams.duplicatecat()
				else
					dupcat = rowparams.duplicatecat
				end
			end
			addcat(dupcat)
		elseif itemquery then
			-- Warn that template parameter needs to be ported to some statement of the property
			-- Look for a property to use as a destination for the info currently held by the template parameter
			local toprop
			if rowparams.converttoprop then
				if type(rowparams.converttoprop) == 'function' then
					toprop = rowparams.converttoprop(data)
				else
					toprop = rowparams.converttoprop
				end
			end
			if not toprop and type(itemquery) == 'string' then
				toprop = itemquery
			end
			if toprop then
				local topropstr
				if type(toprop) == 'table' then
					local toproptable = {}
					for i, j in ipairs(toprop) do
						toproptable[i] = d.showentity(j, lang)
					end
					topropstr = linguistic.conj(toproptable, lang, 'or')
				else
					topropstr = d.showentity(toprop, lang)
				end
				val = val .. '\n' .. mw.ustring.format(translate('to move with prop'), topropstr)
			else
				val = val .. '\n' .. translate('to move')
			end
			local convcat = 'Property documentation with data to be moved to statements'
			if rowparams.conversioncat then
				if type(rowparams.conversioncat) == 'function' then
					convcat = rowparams.conversioncat()
				else
					convcat = rowparams.conversioncat
				end
			end
			addcat(convcat)
		end
	end

	if not val or val == '-' then
		if not rowparams.required then
			return nil
		end
		val = '<span style="color: red;">' .. translate('missing') .. '</span>' -- maintenance for missing parameters
		addcat(rowparams.missingcat or 'Property documentation with missing information')
	end

	if rowparams.maintenancecat then
		addcat(rowparams.maintenancecat(data))
	end

	if string.find(val, '^[*#:;]') then
		val = '\n' .. val
	end

	local row = mw.html.create('tr')
		:css{['vertical-align'] = 'text-top'}
		:tag('th')
			:css{['text-align'] = 'left'}
			:attr('width', '20%')
			:wikitext(translate(label))
			:done()
		:tag('td')
			:wikitext(val)
			:allDone()
	return row
end

function p.main(args)
	local id = args.id
	entity = d.getEntityFromId(id)
	if not entity then
		return mw.getCurrentFrame():preprocess("{{d|Talk page of a deleted property}}")
	end
	local header1, header2 = '', ''
	-- Top-left: Label <br/> Description
	local label = d._getLabel(entity, lang) or ''
	local description = d._getDescription(entity, lang) or ''
	header1 = '<b>' .. label .. '</b><br />' .. description .. '<br />'

	local forQualifierUse = false
	if entity.claims and entity.claims.P31 then
		for _, statement in ipairs(entity.claims.P31) do
			if d.getmainid(statement) == 'Q15720608' then
				forQualifierUse = true
				break
			end
		end
	end
	local linksStr = buildHeaderLinksString(id, forQualifierUse)
	header2 = '<div style="float: right;">' .. linksStr .. '</div>'

	local obj = mw.html.create('div')
		:css{
			["background-color"] = '#DDFFFF',
			border = '3px solid #CDDDDD',
			direction = mw.getLanguage(lang):getDir()
		}
		:tag('div')
			:css{["background-color"] = '#DDFFFF', outline = '3px solid #CDDDDD', padding = '4px'}
			:tag('div')
				:wikitext(header2)
				:done()
			:tag('div')
				:wikitext(header1)
				:allDone()

	local maindiv = mw.html.create('div'):tag('table')

	for _, row in ipairs(rows) do
		maindiv:node(makerow(row, args))
	end
	obj:node(maindiv)
	obj:allDone()

	addcat('All Properties')
	addcat('Properties with ' .. entity.datatype .. '-datatype')
	return tostring(obj) .. maintenancestr
end

function p.makedoc(frame)
	local cleanargs = {}
	namespace = frame:preprocess("{{NAMESPACE}}")

	for i, j in pairs(frame:getParent().args) do
		if j ~= '' then cleanargs[i] = j end
	end

	if not cleanargs.id then
		cleanargs.id = frame:preprocess("{{BASEPAGENAME}}")
	end
	lang = cleanargs.lang or frame:preprocess('{{int:lang}}')

	return p.main(cleanargs)
end

return p