La documentation pour ce module peut être créée à Module:Wikidata/doc

--script that retrieves basic data stored in Wikidata, for the datamodel, see https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua  local wd = {}  local modules = { } local modulesNames = { 	reference = 'Module:Wikidata/Références', 	i18n = 'Module:Wikidata/I18n', 	globes = 'Module:Wikidata/Globes', 	langcodes = 'Module:Dictionnaire Wikidata/Codes langue', -- big, infrequently useda 	invertedlangcodes = 'Module:Dictionnaire Wikidata/Codes langue/inversé',  	linguistic = 'Module:Linguistique', 	formatDate = 'Module:Date complexe', 	formatNum = 'Module:Conversion', 	langmodule = 'Module:Langue', 	cite = 'Module:Biblio', 	weblink = 'Module:Weblink' }  local function loadModule( t, key ) 	if modulesNames[key] then 		local m = require( modulesNames[key] ) 		t[key] = m 		return m 	end end setmetatable( modules, { __index = loadModule } )  local datequalifiers = {'P585', 'P571', 'P580', 'P582', 'P1319', 'P1326'}  -- === I18n === local defaultlang = mw.getContentLanguage():getCode()  function wd.translate(str, rep1, rep2) 	str = modules.i18n[str] or str 	if rep1 and (type (rep1) == 'string') then 		str = str:gsub('$1', rep1) 	end 	if rep2 and (type (rep2) == 'string')then 		str = str:gsub('$2', rep2) 	end 	return str end  local function addCat(cat, sortkey) 	if sortkey then 		return  '[[Category:' .. cat .. '|' .. sortkey .. ']]' 	end 	return '[[Category:' .. cat  .. ']]' end  local function formatError( key , category, debug)     if debug then         return error(modules.i18n[key] or key)     end     if category then         return addCat(category, key)     else         return addCat('cat-unsorted-issue', key)     end end  --   function wd.isSpecial(snak) 	return (snak.snaktype ~= 'value') end  function wd.getId(snak) 	if (snak.snaktype == 'value') then 		return 'Q' .. snak.datavalue.value['numeric-id'] 	end end  function wd.getNumericId(snak) 	if (snak.snaktype == 'value') then 		return snak.datavalue.value['numeric-id'] 	end end  function wd.getMainId(claim) 	return wd.getId(claim.mainsnak) end  function wd.entityId(entity) 	if type(entity) == 'string' then 		return entity 	end 	return entity.id end  function wd.getEntityIdForCurrentPage() 	return mw.wikibase.getEntityIdForCurrentPage() end  -- function that returns true if the "qid" parameter is the qid  -- of the item that is linked to the calling page function wd.isPageOfQId(qid)  	local entity_on_its_page = false 	local self_entity = mw.wikibase.getEntity() 	if self_entity ~= nil and qid == wd.entityId(self_entity) then 		entity_on_its_page = true 	end 	return entity_on_its_page end  function wd.getEntity( val )  	if type(val) == 'table' then 		return val 	end 	if val == '-' then 		return nil 	end 	if val == '' then 		val = nil 	end 	return mw.wikibase.getEntity(val) end  function wd.splitStr(val) -- transforme en table les chaînes venant du Wikitexte qui utilisent des virgules de séparatin 	if type(val) == 'string' then 		val = mw.text.split(val, ",") 	end 	return val end  function wd.isHere(searchset, val) 	for i, j in pairs(searchset) do 		if val == j then 			return true 		end 	end 	return false end   local function wikidataLink(entity) 	local name =':d:' 	 	if type(entity) == 'string' then 		if entity:match("P[0-9+]") then 			entity = "Property:" .. entity 		end 		return name .. entity 	elseif type(entity) == 'table' then 		if entity["type"] == "property" then 			name = ":d:Property:" 		end 		return name .. entity.id 	elseif type(entity) == nil then 		return formatError('entity-not-found') 	end end  function wd.siteLink(entity, project, lang) 	-- returns 3 values: a sitelink (with the relevant prefix) a project name and a language 	lang = lang or defaultlang 	if (type(project) ~= 'string') then 		project = 'wiki' 	end 	project = project:lower() 	if project == 'wikipedia' then 		project = 'wiki' 	end 	if type(entity) == 'string' and (project == 'wiki') and ( (not lang or lang == defaultlang) ) then -- évite de charger l'élément entier 		return  mw.wikibase.sitelink(entity), 'wiki', defaultlang 	end 	if project == 'wikidata' then 		return wikidataLink(entity), 'wikidata' 	end 	local projects = { 		-- nom = {préfixe sur Wikidata, préfix pour les liens sur Wikipédia, ajouter préfixe de langue} 		wiki = {'wiki', nil, true}, -- wikipedia 		commons = {'commonswiki', 'commons', false}, 		commonswiki = {'commonswiki', 'commons', false}, 		wikiquote = {'wikiquote', 'q', true}, 		wikivoyage = {'wikivoyage', 'voy', true}, 		wikibooks = {'wikibooks', 'b', true}, 		wikinews = {'wikinews', 'n', true}, 		wikiversity = {'wikiversity', 'v', true}, 		wikisource = {'wikisource', 's', true}, 		wiktionary = {'wiktionary', 'wikt', true}, 		specieswiki = {'specieswiki', 'species', false}, 		metawiki = {'metawiki', 'm', false}, 		incubator = {'incubator', 'incubator', false}, 		outreach = {'outreach', 'outreach', false}, 		mediawiki = {'mediawiki', 'mw', false} 	}  	entity = wd.getEntity(entity) 	if not entity then 		return nil 	end  	local projectdata = projects[project:lower()] 	if not projectdata then -- defaultlink might be in the form "dewiki" rather than "project: 'wiki', lang: 'de' " 		for k, v in pairs(projects) do 			if project:match( k .. '$' )  				and mw.language.isKnownLanguageTag(project:sub(1, #project-#k)) 			then 				lang = project:sub(1, #project-#k) 				project = project:sub(#lang + 1, #project) 				projectdata = projects[project] 				break 			end 		end 		if not mw.language.isKnownLanguageTag(lang) then 			return --formatError('invalid-project-code', projet or 'nil') 		end 	end 	if not projectdata then 		return -- formatError('invalid-project-code', projet or 'nil') 	end 	 	local linkcode = projectdata[1] 	local prefix = projectdata[2] 	local multiversion = projectdata[3] 	if multiversion then 		linkcode = lang .. linkcode 	end 	local link = entity:getSitelink(linkcode) 	if not link then 		return nil 	end 	 	if prefix then 		link = prefix .. ':' .. link 	end 	if multiversion then 		link = ':' .. lang .. ':' .. link 	end 	return link, project, lang end  -- add new values to a list, avoiding duplicates function wd.addNewValues(olditems, newitems, maxnum, stopval) 	if not newitems then 		return olditems 	end 	for _, qid in pairs(newitems) do 		if stopval and (qid == stopval) then 			table.insert(olditems, qid) 			return olditems 		end 		if maxnum and (#olditems >= maxnum) then 			return olditems 		end 		if not wd.isHere(olditems, qid) then 			table.insert(olditems, qid) 		end 	end 	return olditems end  --=== FILTER CLAIMS ACCORDING TO VARIOUS CRITERIA : FUNCTION GETCLAIMS et alii ===  local function notSpecial(claim) 	local snack = claim.mainsnak or snack 	return snack.snaktype == 'value' end  local function hasTargetValue(claim, targets) -- retourne true si la valeur est dans la liste des target, ou si c'est une valeur spéciale filtrée séparément par excludespecial 	local id = wd.getMainId(claim) 	local targets = wd.splitStr(targets) 	return wd.isHere(targets, id) or wd.isSpecial(claim.mainsnak) end  local function excludeValues(claim, values) -- true si la valeur n'est pas dans la liste, ou si c'est une valeur spéciale (filtrée à part par excludespecial) 	return wd.isSpecial(claim.mainsnak) or not ( hasTargetValue(claim, values) ) end  local function bestRanked(claims) 	if not claims then 		return nil 	end 	local preferred, normal = {}, {} 	for i, j in pairs(claims) do 		if j.rank == 'preferred' then 			table.insert(preferred, j) 		elseif j.rank == 'normal' then 			table.insert(normal, j) 		end 	end 	if #preferred > 0 then 		return preferred 	else 		return normal 	end end  local function withRank(claims, target) 	if target == 'best' then 		return bestRanked(claims) 	end 	local newclaims = {} 	for pos, claim in pairs(claims)  do 		if target == 'valid' then 			if claim.rank ~= 'deprecated' then 				table.insert(newclaims, claim) 			end 		elseif claim.rank == target then 			table.insert(newclaims, claim) 		end 	end 	return newclaims end  function wd.hasQualifier(claim, acceptedqualifs, acceptedvals, excludequalifiervalues) 	local claimqualifs = claim.qualifiers 	 	if (not claimqualifs) then 		return false 	end  	acceptedqualifs = wd.splitStr(acceptedqualifs) 	acceptedvals = wd.splitStr( acceptedvals)   	local function ok(qualif) -- vérification pour un qualificatif individuel 		if not claimqualifs[qualif] then 			return false 		end 		if not (acceptedvals) then  -- si aucune valeur spécifique n'est demandée, OK 			return true 		end 		for i, wanted in pairs(acceptedvals) do 			for j, actual in pairs(claimqualifs[qualif]) do 				if wd.getId(actual) == wanted then 					return true 				end 			end 		end 	end  	for i, qualif in pairs(acceptedqualifs) do 		if ok(qualif) then 			return true 		end 	end 	return false end  function wd.getSiteLink(frame) 	local qid = frame.args.qid 	if qid == "" then qid = nil end 	local f = mw.text.trim( frame.args[1] or "") 	local entity = mw.wikibase.getEntity(qid) 	if not entity then 		return 	end 	local link = entity:getSitelink( f ) 	if not link then 		return 	end 	return link end  local function hasSource(claim, targetsource, sourceproperty) 	sourceproperty = sourceproperty or 'P248' 	if targetsource == "-" then 		return true 	end 	if (not claim.references) then return 		false 	end 	local candidates = claim.references[1].snaks[sourceproperty] -- les snaks utilisant la propriété demandée 	if (not candidates) then 		return false 	end 	if (targetsource == "any") then -- si n'importe quelle valeur est acceptée tant qu'elle utilise en ref la propriété demandée 		return true 	end 	targetsource = wd.splitStr(targetsource) 	for _, source in pairs(candidates) do 		local s = wd.getId(source) 		for i, target in pairs(targetsource) do 			if s == target then return true end 		end 	end 	return false end  local function excludeQualifier(claim, qualifier, qualifiervalues) 	return not wd.hasQualifier(claim, qualifier, qualifiervalues) end  local function hasDate(claim) 	local claimqualifs = claims.qualifiers 	if not claimqualifs then 		return false 	end 	for _, qualif in pairs(claimqualifs) do 		if claimsqualifs[qualif] and claimsqualifs[qualif][1].snaktype == 'value' then 			return true 		end 	end 	return false end  local function hasLink(claim, site, lang) 	if (claim.mainsnak.snaktype ~= 'value') then -- ne pas supprimer les valeurs spéciales, il y a une fonction dédiée pour ça 		return true 	end 	local id = wd.getMainId(claim) 	local link = wd.siteLink(id, site, lang) 	if link then 		return true 	end end  local function isInLanguage(claim, lang) -- ne fonctionne que pour les monolingualtext / étendre aux autres types en utilisant les qualifiers ? 	if type(lang) == 'table' then -- si c'est une table de language séparées par des virgules, on les accepte toutes 		for i, l in pairs(lang) do 			local v = isInLanguage(claim, l) 			if v then 				return true 			end 		end 	end 	if type(lang) ~= ('string') then 		return --? 	end  	if (lang == '-') then 		return true 	end 	if (lang == 'locallang') then 		lang =  mw.getContentLanguage():getCode() 	end 	 	-- pour les monolingual text 	local snak = claim.mainsnak or claim 	if snak.snaktype == 'value' and snak.datavalue.type == 'monolingualtext' then 		if snak.datavalue.value.language == lang then 			return true 		end 		return false 	end  	-- pour les autres types de données : recherche dans les qualificatifs 	if (lang == 'fr') then 		lang = 'Q150' 	elseif (lang == 'en') then 		lang = 'Q1860' 	else 		lang = invertedlangcodes[lang] 	end 	if claim.qualifiers and claim.qualifiers.P407 then 		if wd.hasQualifier(claim, {'P407'}, {lang}) then 			return true 		else 			return false 		end 	end  	return true -- si on ne ne sait pas la langue, on condière que c'est bon end  local function firstVals(claims, numval) -- retourn les numval premières valeurs de la table claims     local numval = tonumber(numval) or 0 -- raise a error if numval is not a positive integer ?     if not claims then     	return nil     end     while (#claims > numval) do     	table.remove(claims)     end     return claims end  local function timeFromQualifs(claim, qualifs) 	local claimqualifs = claim.qualifiers 	if not claimqualifs then 		return nil 	end 	for i, qualif in pairs(qualifs or timequalifiers) do 		local vals = claimqualifs[qualif] 		if vals and (vals[1].snaktype == 'value') then 			return vals[1].datavalue.value.time 		end 	end end  local function atDate(claim, mydate) 	if mydate == "today" then 		mydate = os.date("!%Y-%m-%dT%TZ") 	end	 	local newclaims = {} 	local mindate = timeFromQualifs(claim, {'P580'})  	local maxdate = timeFromQualifs(claim, {'P582'}) 	if modules.formatDate.before(mydate, mindate) and  modules.formatDate.before(maxdate, mydate) then 		return true 	end end  local function check(claim, condition) 	if type(condition) == 'function' then -- cas standard 		return condition(claim) 	end 	return formatError('invalid type', 'function', type(condition))  end  local function minPrecision(claim, minprecision) 	local snack 	if claim.qualifiers then -- si une date est donnée en qualificatif, c'est elle qu'on utilise de préférence au mainsnak 		for i, j in ipairs(datequalifiers) do 			if claim.qualifiers[j] then 				snack = claim.qualifiers[j][1]  				break 			end 		end 	end 	if not snack then 		snack = claim.mainsnak or claim 	end 	if (snack.snaktype == 'value') and (snack.datatype == 'time') and (snack.datavalue.value.precision < minprecision) then 		return false 	end 	return true end  function wd.sortClaims(claims, sorttype) 	if not claims then 		return nil 	end 	if sorttype == 'chronological' then 		return wd.chronoSort(claims) 	elseif sorttype == 'inverted' then 		return wd.chronoSort(claims, true) 	elseif type(sorttype) == 'function' then 		table.sort(claims, sorttype) 		return claims 	end 	return claims end local alreadyFiltered = false function wd.filterClaims(claims, args) --retire de la tables de claims celles qui sont éliminés par un des filters de la table des filters  	local function filter(condition, filterfunction, funargs) 		if not args[condition] then 			return 		end 		for i = #claims, 1, -1 do 			if not( filterfunction(claims[i], args[funargs[1]], args[funargs[2]], args[funargs[3]]) ) then 				table.remove(claims, i) 			end 		end 	end 	filter('isinlang', isInLanguage, {'isinlang'} ) 	filter('excludespecial', notSpecial, {} ) 	filter('condition', check, {'condition'} ) 	if claims[1] and claims[1].mainsnak then 		filter('targetvalue', hasTargetValue, {'targetvalue'} ) 		filter('atdate', atDate, {'atdate'} ) 		filter('qualifier', wd.hasQualifier, {'qualifier', 'qualifiervalue'} ) 		filter('excludequalifier', excludeQualifier, {'excludequalifier', 'excludequalifiervalue'} ) 		filter('withsource', hasSource, {'withsource', 'sourceproperty'} ) 		filter('withdate', hasDate, {} ) 		filter('excludevalues', excludeValues, {'excludevalues'}) 		filter('withlink', hasLink, {'withlink', 'linklang'} ) 		filter('minprecision', minPrecision, {'minprecision'} ) 		claims = withRank(claims, args.rank or 'best') 	end 	if args.sorttype then 		claims = wd.sortClaims(claims, args.sorttype) 	end 	if #claims == 0 then 		return nil 	end 	if args.numval then 		claims = firstVals(claims, args.numval) 	end 	return claims  end  function wd.loadEntity(entity, cache) 	if type(entity) ~= 'table' then 		if cache then 			if not cache[entity] then  				cache[entity] = mw.wikibase.getEntity(entity) 				mw.log("cached")      		end 			return cache[entity]         else 			if entity == '' or (entity == '-') then 				entity = nil 			end         	return mw.wikibase.getEntity(entity)         end     else      	return entity     end end   function wd.getClaims( args ) -- returns a table of the claims matching some conditions given in args 	if args.claims then -- if claims have already been set, return them 		return args.claims 	end 	local properties = wd.splitStr(args.property)  	if not properties then 		return formatError( 'property-param-not-provided' ) 	end  	--Get entity 	local entity = args.entity  	entity = wd.loadEntity(args.entity, args.cache)      	if (not entity) or (not entity.claims) then 		return nil 	end 	local claims = {} 	for i, prop in pairs(properties) do 		prop = string.upper(prop) 		for j, claim in pairs(entity.claims[prop] or {}) do 			table.insert(claims, claim) 		end 	end  	if (#claims == 0) then 		return nil 	end 	return wd.filterClaims(claims, args) end  --=== ENTITY FORMATTING ===  function wd.getLabel(entity, lang, labelformat) 	if (not entity) then 		return nil -- ou option de gestion des erreurs ? 	end  	lang = lang or defaultlang  	if type(labelformat) == 'function' then 		return labelformat(entity) 	end 	 	if (type(entity) == 'string') and (lang == defaultlang) then -- le plus économique 		local str = mw.wikibase.label(entity) 		if str then -- mw.wikibase.label() ne fonctionne pas avec les redirect https://phabricator.wikimedia.org/T157868 			return str 		end 	end  	if type(entity) == 'string' then 		entity = mw.wikibase.getEntity(entity) 	end 	 	if entity and entity.labels and entity.labels[lang] then 		return entity.labels[lang].value, true 	end end  function wd.formatEntity( entity, params )  	if (not entity) then 		return nil --formatError('entity-not-found') 	end 	local id = entity 	if type(id) == 'table' then 		id = id.id 	end  	params = params or {} 	local lang = params.lang or defaultlang 	local speciallabels = params.speciallabels 	local displayformat = params.displayformat 	local labelformat = params.labelformat 	local defaultlabel = params.defaultlabel or id 	local linktype = params.link 	local defaultlink = params.defaultlink 	local defaultlinkquery = params.defaultlinkquery  	if speciallabels and speciallabels[id] then --speciallabels override the standard label + link combination 		return speciallabels[id] 	end 	if params.displayformat == 'raw' then 		return id 	end  	local link, label 	local str = '' -- l'intégralité du text à retourner	 	 	 	label = wd.getLabel(entity, lang, labelformat) 	 	-- détermination du fait qu'on soit ou non en train de rendre l'élément sur la page de son article 	local rendering_entity_on_its_page = wd.isPageOfQId(id) 		  	if not label then 		if (defaultlabel == '-') then  			return nil 		end 		link = wd.siteLink(id, 'wikidata') 		return str .. '[[' .. link .. '|' .. id .. ']]' .. addCat(modules.i18n['to translate']) -- si pas de libellé, on met un lien vers Wikidata pour qu'on comprenne à quoi ça fait référence 	end  	if (linktype == '-') or rendering_entity_on_its_page then 		return str .. label 	end  	local link = wd.siteLink(entity, linktype, lang)  	-- defaultlinkquery will try to link to another page on this Wiki 	if (not link) and defaultlinkquery then 		if type(defaultlinkquery) == 'string' then 				defaultlinkquery = {property = defaultlinkquery} 		end 		defaultlinkquery.excludespecial = true 		defaultlinkquery.entity = entity 		local claims = wd.getClaims(defaultlinkquery) 		if claims then 			for i, j in pairs(claims) do 				local id = wd.getMainId(j) 				link = wd.siteLink(id, linktype, lang) 				if link then 					break 				end 			end 		end	 	end  	if link then  		return str .. '[[' .. link .. '|' .. label .. ']]' 	end  	-- if not link, you can use defaultlink: a sidelink to another Wikimedia project 	if (not defaultlink) then 		defaultlink = {'enwiki'} 	end 	if defaultlink and (defaultlink ~= '-') then 		local linktype 		local sidelink, site, langcode 	 		if type(defaultlink) == 'string' then 			defaultlink = {defaltlink} 		end 		for i, j in ipairs(defaultlink) do 			sidelink, site, langcode = wd.siteLink(entity, j, lang) 			if sidelink then 				break 			end 		end 		if not sidelink then 			sidelink, site = wd.siteLink(entity, 'wikidata') 		end 		 		local icon, class, title = site, nil, nil -- le texte affiché du lien 		if site == 'wiki' then 			icon, class, title = langcode, "indicateur-langue", wd.translate('see-another-language', mw.language.fetchLanguageName(langcode, defaultlang))	 		elseif site == 'wikidata' then 			icon, class, title = 'd',  "indicateur-langue", wd.translate('see-wikidata')		 		else 			title = wd.translate('see-another-project', site) 		end 		local val = '[[' .. sidelink .. '|' .. '<span class = "' .. (class or '').. '" title = "' .. (title or '') .. '">' .. icon .. '</span>]]' 		return str  .. label .. '<small>&nbsp;(' .. val .. ')</small>' 	end  	return str .. label end  function wd.pageId(frame) 	local entity = mw.wikibase.getEntityObject() 	if not entity then return nil else return entity.id end end  function wd.addTrackingCat(prop, cat) -- doit parfois être appelé par d'autres modules 	if type(prop) == 'table' then 		prop = prop[1] -- devrait logiquement toutes les ajouter 	end 	if not prop and not cat then 		return formatError("property-param-not-provided") 	end 	if not cat then 		cat = wd.translate('trackingcat', prop or 'P??') 	end 	return addCat(cat ) end  local function unknownValue(snak, label) 	local str = label  	if type(str) == "function" then 		str = str(snak) 	end  	if (not str) then 		if snak.datatype == 'time' then 			str = wd.translate('sometime') 		else 			str = wd.translate('somevalue') 		end 	end  	if type(str) ~= "string" then 		return formatError(snak.datatype) 	end 	return str end  local function noValue(displayformat) 	if not displayformat then 		return wd.translate('novalue') 	end 	if type(displayformat) == 'string' then 		return displayformat 	end 	return formatError() end  local function getLangCode(entityid) 	return modules.langcodes[tonumber(entityid:sub(2))] end  local function showLang(statement) -- retourne le code langue entre parenthèse avant la valeur (par exemple pour les biblios et liens externes) 	local mainsnak = statement.mainsnak 	if mainsnak.snaktype ~= 'value' then 		return nil 	end 	local langlist = {} 	if mainsnak.datavalue.type == 'monolingualtext' then 		langlist = {mainsnak.datavalue.value.language} 	elseif (not statement.qualifiers) or (not statement.qualifiers.P407) then 		return 	else 		for i, j in pairs( statement.qualifiers.P407 ) do 			if  j.snaktype == 'value' then 				local langentity = wd.getId(j) 				local langcode =  getLangCode(langentity) 				table.insert(langlist, langcode) 			end 		end 	end 	if (#langlist > 1) or (#langlist == 1 and langlist[1] ~= defaultlang) then -- si c'est en français, pas besoin de le dire 		return modules.langmodule.indicationMultilingue(langlist) 	end end   -- === DATE HANDLING ===  function wd.addStandardQualifs(str, statement) 	if (not statement) or (not statement.qualifiers) then 		return str 	end 	if not str then 		return error()-- what's that ? 	end  	if statement.qualifiers.P1480 then 		for i, j in pairs(statement.qualifiers.P1480) do 			local v = wd.getId(j) 			if (v == "Q21818619") then 				str = wd.translate('approximate-place', str) 			elseif (v == "Q18122778") or (v == "Q18912752") then 				str = wd.translate('uncertain-information', str) 			elseif (v == "Q5727902") then 				if (statement.mainsnak.datatype == 'time') then 					str = modules.formatDate.fuzzydate(str) 				else 					str = wd.translate('approximate-value', str) 				end 			end			 		end 	end 	return str end  local function rangeObject(begin, ending, params) 	--[[ 		objet comportant un timestamp pour le classement chronologique et deux dateobject (begin et ending) 	]]--  	local timestamp 	if begin then 		timestamp = begin.timestamp 	else 		timestamp = ending.timestamp 	end 	return {begin = begin, ending = ending, timestamp = timestamp, type = 'rangeobject'} end  local function dateObject(orig, params) 	--[[ transforme un snak en un nouvel objet utilisable par Module:Date complexe 		{type = 'dateobject', timestamp = str, era = '+' ou '-', year = number, month = number, day = number, calendar = calendar} 	]]--  	if not params then 		params = {} 	end 	 	local newobj = modules.formatDate.splitDate(orig.time, orig.calendarmodel) 	 	newobj.precision = params.precision or orig.precision 	newobj.type = 'dateobject' 	return newobj end  local function objectToText(obj, params) 	if obj.type == 'dateobject' then 		return modules.formatDate.simplestring(obj, params) 	elseif obj.type == 'rangeobject' then 		return modules.formatDate.daterange(obj.begin, obj.ending, params) 	end end  local function getDateFromQualif(statement, qualif) 	if (not statement) or (not statement.qualifiers) or not (statement.qualifiers[qualif]) then 		return nil 	end 	local v = statement.qualifiers[qualif][1] 	if v.snaktype ~= 'value' then -- que faire dans ce cas ? 		return nil 	end 	return dateObject(v.datavalue.value) end  function wd.getDate(statement) 	local period = getDateFromQualif(statement, 'P585') -- retourne un dateobject 	if period then 		return period 	end 	local begin, ending = getDateFromQualif(statement, 'P580'),  getDateFromQualif(statement, 'P582') 	if begin or ending then 		return rangeObject(begin, ending) -- retourne un rangeobject fait de deux dateobject 	end end  function wd.getFormattedDate(statement, params) 	if not statement then 		return nil 	end 	local str   	--cherche la date avec les qualifs P580/P582 	local datetable = wd.getDate(statement) 	if datetable then 		str = objectToText(datetable, params) 	end 	 	-- puis limite intérieur / supérieur 	if not str then 		local start, ending = getDateFromQualif(statement, 'P1319'), getDateFromQualif(statement, 'P1326') 		str = modules.formatDate.between(start, ending, params) 	end  	-- sinon, le mainsnak, pour les données de type time 	if (not str) and (statement.mainsnak.datatype == 'time') then 		local mainsnak = statement.mainsnak 		if (mainsnak.snaktype == 'value') or (mainsnak.snaktype == 'somevalue') then 			str = wd.formatSnak(mainsnak, params) 		end 	end  	if str and params and (params.addstandardqualifs ~= '-') then 		str = wd.addStandardQualifs(str, statement) 	end 	return str end  -- Fonction qui trie des Claims de type time selon l'ordre chronologique -- Une clé de tri nomée « dateSortKey » est ajouté à chaque claim. -- Si des clés de tri de ce nom existent déjà, elles sont utilisées sans modification. function wd.chronoSort( claims, inverted ) 	for _, claim in ipairs( claims ) do 		if not claim.dateSortKey then 			local snack = claim.mainsnak or claim 			local iso 			if (snack.snaktype == 'value') and (snack.datatype == 'time') then 				iso = snack.datavalue.value.time 			else 				iso = timeFromQualifs(claim, datequalifiers) or '0' 			end 			-- transformation en nombre (indication de la base car gsub retourne deux valeurs) 			iso = tonumber( iso:gsub( '(%d)%D', '%1' ), 10 ) 			claim.dateSortKey = iso 		end 	end 	table.sort(  		claims, 		function ( c1, c2 ) 			if inverted then 				return c2.dateSortKey < c1.dateSortKey 			end 			return c1.dateSortKey < c2.dateSortKey 		end 	) 	return claims end   -- =================== function wd.getReferences(statement) 	local refdata = statement.references 	if not refdata then 		return nil 	end  	local refs = {} 	for i, ref in pairs(refdata) do 		local s 		local function hasValue(prop) -- checks that the prop is here with valid value 			if ref.snaks[prop] and ref.snaks[prop][1].snaktype == 'value' then 				return true 			end 			return false 		end		  		if ref.snaks.P248 then 			for j, source in pairs(ref.snaks.P248) do 				if source.snaktype == 'value' then 					local page, accessdate 					if hasValue('P304') then 						page = wd.formatSnak(ref.snaks.P304[1]) 					end 					if hasValue('P813') then 						accessdate = wd.formatSnak(ref.snaks.P813[1]) 					end 					s = modules.reference.citeitem(wd.getId(source), {['page'] = page, ['accessdate'] = accessdate}) 					table.insert(refs, s) 				end 			end 	 		elseif hasValue('P854') and hasValue('P1476') then 			local url, title, accessdate, publishdate, publishlang 			url, title = wd.formatSnak(ref.snaks.P854[1], {text = "-"}), wd.formatSnak(ref.snaks.P1476[1]) 			if hasValue('P813') then 				accessdate = wd.formatSnak(ref.snaks.P813[1]) 			end 			-- publishdate avec P577 ? (ne semble pas vraiment correspondre)  			if hasValue('P407') then 				local id = wd.getId(ref.snaks.P407[1]) 				publishlang = getLangCode(id) 			end 			s = modules.cite.lienWeb{titre = title, url = url, langue = publishlang, ['en ligne le'] = publishdate, ['consulté le'] = accessdate} 			table.insert(refs, s)			 		elseif ref.snaks.P854 and ref.snaks.P854[1].snaktype == 'value' then 			s = wd.formatSnak(ref.snaks.P854[1], {text = "-"}) 			table.insert(refs, s) 		end 	end 	if #refs > 0 then 		return refs 	end end  function wd.sourceStr(sources) 	if not sources or (#sources == 0) then 		return nil 	end 	for i, j in pairs(sources) do 		sources[i] = mw.getCurrentFrame():extensionTag( "ref", j) 	end 	return table.concat(sources, '<sup class="reference cite_virgule">,</sup>') end  function wd.getDataValue(snak, params) 	if not params then 		params = {} 	end 	local speciallabels = params.speciallabels -- parfois on a besoin de faire une liste d'éléments pour lequel le libellé doit être changé, pas très pratique d'utiliser une fonction pour ça  	if snak.snaktype ~= 'value' then 		return nil 	end  	local datatype = snak.datatype 	local value = snak.datavalue.value 	 	local displayformat = params.displayformat 	if type(displayformat) == 'function' then 		return displayformat(snak, params) 	end  	if datatype == 'wikibase-item' then 		return wd.formatEntity(wd.getId(snak), params) 	end  	if datatype == 'url' then 		return modules.weblink.makelink(value, params.text) 	end  	if datatype == 'math' then 		return mw.getCurrentFrame():extensionTag( "math", value) 	end  	if (datatype == 'string') or (datatype == 'external-id') or (datatype == 'commonsMedia') then -- toutes les données de type string sauf "math" 		if params.urlpattern then 			local urlpattern = params.urlpattern 			if type(urlpattern) == 'function' then 				urlpattern = urlpattern(value) 			end 			local url = mw.ustring.gsub(urlpattern, '$1', (value:gsub('%%', '%%%%'))):gsub(' ', '%%20') 			value = '[' .. url .. ' ' .. (params.text or value) .. ']' 		end 		return value 	end 	 	if datatype == 'time' then -- format example: +00000001809-02-12T00:00:00Z 		if displayformat == 'raw' then 			return value.time 		else 			local dateobject = dateObject(value, {precision = params.precision}) 			return objectToText(dateobject, params) 		end 	end  	if datatype == 'globe-coordinate' then 		-- retourne une table avec clés latitude, longitude, précision et globe à formater par un autre module (à changer ?) 		if displayformat == 'latitude' then 			return value.latitude 		elseif displayformat == 'longitude' then 			return value.longitude 		else 			local coordvalue = mw.clone( value ) 			coordvalue.globe = modules.globes[value.globe] -- transforme l'ID du globe en nom anglais utilisable par geohack 			return coordvalue -- note : les coordonnées Wikidata peuvent être utilisée depuis Module:Coordinates. Faut-il aussi autoriser à appeler Module:Coordiantes ici ? 		end 	end  	if datatype == 'quantity' then -- todo : gérer les paramètre précision 		local amount, unit = value.amount, value.unit  		if unit then 			unit = unit:match('Q%d+') 		end  		local raw	 		if displayformat == "raw" then 			raw = true 		end 		return modules.formatNum.displayvalue(amount, unit, 			{targetunit = params.targetunit, raw = raw, rounding = params.rounding, showunit = params.showunit or 'short', showlink = params.showlink} 		) 	end 	if datatype == 'monolingualtext' then 		if value.language == defaultlang then 			return value.text 		else 			return modules.langmodule.langue({value.language, value.text}) 		end 	end	 	return formatError('unknown-datavalue-type' )  end  function wd.stringTable(args) -- like getClaims, but get a list of string rather than a list of snaks, for easier manipulation 		local claims = args.claims 	if not claims then 		claims = wd.getClaims(args) 	end 	if not claims or claims == {} then 		return nil 	end 	local props = {} -- liste des propriétés associété à chaque string pour catégorisation et linkback 	for i, j in pairs(claims) do 		claims[i] = wd.formatStatement(j, args) 		table.insert(props, j.mainsnak.property) 	end 	if args.removedupes and (args.removedupes ~= '-') then 		claims = wd.addNewValues({}, claims) -- devrait aussi supprimer de props celles qui ne sont pas utilisées 	end 	return claims, props end  function wd.getQualifiers(statement, qualifs, params) 	if not statement.qualifiers then 		return nil 	end 	local vals = {} 	if type(qualifs) == 'string' then 		qualifs = wd.splitStr(qualifs) 	end 	for i, j in pairs(qualifs) do 		if statement.qualifiers[j] then 			for k, l in pairs(statement.qualifiers[j]) do 				table.insert(vals, l) 			end 		end 	end 	if #vals == 0 then 		return nil 	end 	return vals end  function wd.getFormattedQualifiers(statement, qualifs, params) 	if not params then params = {} end 	local qualiftable = wd.getQualifiers(statement, qualifs) 	if not qualiftable then 		return nil 	end 	qualiftable = wd.filterClaims(qualiftable, params) or {} 	for i, j in pairs(qualiftable) do 		qualiftable[i] = wd.formatSnak(j, params) 	end 	return modules.linguistic.conj(qualiftable, params.conjtype) end  function wd.showQualifiers(str, statement, args) 	local qualifs =  args.showqualifiers 	if not qualifs then 		return str -- or error ? 	end 	if type(qualifs) == 'string' then 			qualifs = wd.splitStr(qualifs) 	end 	local qualifargs = args.qualifargs or {} 	-- formatage des qualificatifs = args commençant par "qualif", ou à défaut, les mêmes que pour la valeur principale 	qualifargs.displayformat = args.qualifdisplayformat or args.displayformat 	qualifargs.labelformat = args.qualiflabelformat or args.labelformat 	qualifargs.link = args.qualiflink or args.link 	qualifargs.conjtype = args.qualifconjtype 			 	local formattedqualifs = wd.getFormattedQualifiers(statement, qualifs, qualifargs) 	if formattedqualifs and str then 		str = str .. modules.linguistic.inparentheses(formattedqualifs, defaultlang) 	end 	return str end   function wd.formatSnak( snak, params ) 	if not params then params = {} end -- pour faciliter l'appel depuis d'autres modules 	if snak.snaktype == 'somevalue' then 		return unknownValue(snak, params.unknownlabel) 	elseif snak.snaktype == 'novalue' then 		return noValue(params.novaluelabel) 	elseif snak.snaktype == 'value' then 		return wd.getDataValue( snak, params) 	else 		return formatError( 'unknown-snak-type' ) 	end end  function wd.formatStatement( statement, args ) 	if not args then 		args = {} 	end 	if not statement.type or statement.type ~= 'statement' then 		return formatError( 'unknown-claim-type' ) 	end 	local prop = statement.mainsnak.property  	local str  	-- special displayformat f 	if args.statementformat and (type(args.statementformat) == 'function') then 		str = args.statementformat(statement, args) 	elseif (statement.mainsnak.datatype == 'time') and (statement.mainsnak.dateformat ~= '-') then 		if args.displayformat == 'raw' and statement.mainsnak.snaktype == 'value' then 			str = statement.mainsnak.datavalue.value.time 		else 			str = wd.getFormattedDate(statement, args) 		end 	elseif args.showonlyqualifier and (args.showonlyqualifier ~= '') then 		str = wd.getFormattedQualifiers(statement, args.showonlyqualifier, args) 		if not str then 			return nil 		end 		if args.addstandardqualifs ~= '-' then 			str = wd.addStandardQualifs(str, statement) 		end 	else 		str = wd.formatSnak( statement.mainsnak, args ) 		if args.addstandardqualifs ~= '-' then 			str = wd.addStandardQualifs(str, statement) 		end 		 	end  	-- ajouts divers	 	if args.showlang == true then 		local indicateur = showLang(statement) 		if indicateur then 			str = indicateur .. '&nbsp;' .. str	 		end 	end 	if args.showqualifiers then 		str = wd.showQualifiers(str, statement, args) 	end  	if args.showdate then -- when "showdate and chronosort are both set, date retrieval is performed twice 	local period = wd.getFormattedDate(statement, args, "-") -- 3 arguments indicate the we should not use additional qualifiers, alrady added by wd.formatStatement 	if period then 		str = str .. " <small>(" .. period ..")</small>" 	end 	end  	if args.showsource then 		local sources = wd.getReferences(statement) 		if sources then 			local source = wd.sourceStr(sources) 			str = str .. (source or "") 		end 	end  	return str end  function wd.addLinkBack(str, id, property) 	if not id then 		id = wd.getEntity() 	end 	if not id then 		return str 	end 	if type(property) == 'table' then 		property = property[1] 	end 	if type(id) == 'table' then 		id = id.id 	end 	 	local class = '' 	if property then 		class = 'wd_' .. string.lower(property) 	end 	local icon = '[[File:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]' 	local title = wd.translate('see-wikidata-value') 	local url = mw.uri.fullUrl('d:' .. id, 'uselang=fr') 	url.fragment = property -- ajoute une #ancre si paramètre "property" défini 	url = tostring(url) 	local v = mw.html.create('span') 		:addClass(class) 		:wikitext(str) 		:tag('span') 			:addClass('noprint wikidata-linkback') 			:css('padding-left', '0.5em') 			:wikitext(icon:format(title, url)) 		:allDone() 	return tostring(v) end  function wd.addRefAnchor(str, id) --[[ 	Insère une ancre pour une référence générée à partir d'un élément wd. 	L'id Wikidata sert d'identifiant à l'ancre, à utiliser dans les modèles type "harvsp" --]] 	return tostring( 		mw.html.create('span') 			:attr('id', id) 			:attr('class', "ouvrage") 			:wikitext(str) 	) end  --=== FUNCTIONS USING AN ENTITY AS ARGUMENT === local function formatStatementsGrouped(args, type) 	-- regroupe les affirmations ayant la même valeur en mainsnak, mais des qualificatifs différents 	-- (seulement pour les propriétés de type élément)  	local claims = wd.getClaims(args) 	if not claims then 		return nil 	end 	local groupedClaims = {}  	-- regroupe les affirmations par valeur de mainsnak 	local function addClaim(claim) 		local id = wd.getMainId(claim) 		for i, j in pairs(groupedClaims) do  			if (j.id == id) then 				table.insert(groupedClaims[i].claims, claim) 				return 			end 		end 		table.insert(groupedClaims, {id = id, claims = {claim}}) 	end 	for i, claim in pairs(claims) do	 		addClaim(claim) 	end  	local stringTable = {}  	-- instructions ad hoc pour les paramètres concernant la mise en forme d'une déclaration individuelle 	local funs = { 		{param = "showqualifiers", fun = function(str, claims) 			local qualifs = {} 			for i, claim in pairs(claims) do 				local news = wd.getFormattedQualifiers(claim, args.showqualifiers, args) 				if news then 					table.insert(qualifs, news) 				end 			end 			local qualifstr = modules.linguistic.conj(qualifs, "qualif-separator") 			if not qualifstr then 				return str 			end 			return str .. " " .. modules.linguistic.inparentheses(qualifstr) 			end 		}, 		{param = "showdate", fun = function(str, claims) 			-- toutes les dates sont regroupées à l'intérieur des mêmes parenthèses ex "médaille d'or (1922, 1924)" 			local dates = {} 			for i, statement in pairs(claims) do 				local s = wd.getFormattedDate(statement, args, true) 				if statement then table.insert(dates, s) end 			end 			local datestr = modules.linguistic.conj(dates) 			if not datestr then 				return str 			end 			return str .. "<small>" .. modules.linguistic.inparentheses(datestr) .. "</small>" 			end 		}, 		{param = "showsource", fun = function(str, claims) 			-- les sources sont toutes affichées au même endroit, à la fin 			-- si deux affirmations ont la même source, on ne l'affiche qu'une fois 			local sources = {} 		 			local function dupeRef(old, new) 				for i, j in pairs(old) do 					if j == new then 						return true 					end 				end 			end 			for i, claim in pairs(claims) do 				local refs = wd.getReferences(claim) 				if refs then 					for i, j in pairs(refs) do 						if not dupeRef(sources, j) then 							table.insert(sources, j) 						end 					end 				end 			end 			return str .. (wd.sourceStr(sources) or "") 			end 		} 	}  	for i, group in pairs(groupedClaims) do -- bricolage pour utiliser les arguments de formatStatements 		local str = wd.formatEntity(group.id, args) 		for i, fun in pairs(funs) do 			if args[fun.param] then 				str = fun.fun(str, group.claims, args) 			end 		end 		table.insert(stringTable, str) 	end 				 	args.valuetable = stringTable 	return wd.formatStatements(args) end   function wd.formatStatements( args )--Format statement and concat them cleanly 	if args.value == '-' then 		return nil 	end 	local valueexpl = wd.translate("activate-query") 	--If a value is already set, use it 	if args.value and (args.value ~= '') and (args.value ~= valueexpl) then 		return args.value 	end 	-- if args.expl: return something only one if explicitly required in Wikitext 	if args.expl and (args.value ~= valueexpl) then 		return nil 	end 	args.entity = wd.getEntity(args.entity)  	if args.grouped and args.grouped ~= '' then 		args.grouped = false 		return formatStatementsGrouped(args) 	end 	local valuetable = args.valuetable -- dans le cas où les valeurs sont déjà formtées 	local props -- les prorpriétés réellement utilisées (dans certainse cas, ce ne sont pas toutes celles de ags.property 	if not valuetable then -- cas le plus courant 		valuetable, props = wd.stringTable(args) 	end  	local str = modules.linguistic.conj(valuetable, args.conjtype) 	if not str then 		return nil 	end 	if not props then 		props = wd.splitStr(args.property)[1] 	end 	if args.ucfirst ~= '-' then 		str = modules.linguistic.ucfirst(str) 	end  	if args.addcat and (args.addcat ~= '-') then 		str = str .. wd.addTrackingCat(props) 	end 	if args.linkback and (args.linkback ~= '-') then 		str = wd.addLinkBack(str, args.entity, props) 	end 	if args.returnnumberofvalues then 		return str, #valuetable 	end 	return str end  function wd.formatAndCat(args) 	if not args then 		return nil 	end 	args.linkback = args.linkback or true 	args.addcat = true 	if args.value then -- do not ignore linkback and addcat, as formatStatements do 		if args.value == '-' then 			return nil 		end 		local val = args.value .. wd.addTrackingCat(args.property) 		val = wd.addLinkBack(val, args.entity, args.property) 		return val 	end  	return wd.formatStatements( args ) end  function wd.getTheDate(args) 	local claims = wd.getClaims(args) 	if not claims then 		return nil 	end 	local formattedvalues = {} 	for i, j in pairs(claims) do 		local v = wd.getFormattedDate(j, args) 		if v then 			table.insert(formattedvalues, v ) 		end 	end 	local val = modules.linguistic.conj(formattedvalues) 	if not val then 		return nil 	end 	if args.addcat == true then 		val = val .. wd.addTrackingCat(args.property) 	end 	val = wd.addLinkBack(val, args.entity, args.property) 	return val end   function wd.keyDate (event, item, params) 	params = params or {} 	params.entity = item 	if type(event) == 'table' then 		for i, j in pairs(event) do 			params.targetvalue = nil -- réinitialisation barbare des paramètres modifiés 			local s = wd.keyDate(j, item, params) 			if s then 				return s 			end 		end 	elseif type(event) ~= 'string' then 		return formatError('invalid-datatype', type(event), 'string') 	elseif string.sub(event, 1, 1) == 'Q' then -- on demande un élément utilisé dans P:P793 (événement clé) 		params.property = 'P793' 		params.targetvalue = event 		params.addcat = params.addcat or true 		return wd.getTheDate(params) 	elseif string.sub(event, 1, 1) == 'P'  then -- on demande une propriété 		params.property = event 		return wd.formatAndCat(params) 	else 		return formatError('invalid-entity-id', event) 	end end  function wd.mainDate(entity)	 	-- essaye P580/P582 	local args = {entity = entity, addcat = true} 	 	args.property = 'P580' 	local startpoint = wd.formatStatements(args) 	args.property = 'P582' 	local endpoint = wd.formatStatements(args)  	local str 	if (startpoint or endpoint) then 		str = modules.formatDate.daterange(startpoint, endpoint, params) 		str = wd.addLinkBack(str, entity, 'P582') 		return str 	end  	-- défaut : P585 	args.property = {'P585', 'P571'} 	args.linkback = true 	return wd.formatStatements(args) end  -- === FUNCTIONS FOR TRANSITIVE PROPERTIES ===  function wd.getIds(item, query)  	query.excludespecial = true 	query.displayformat = 'raw' 	query.entity = item 	query.addstandardqualifs = '-' 	return wd.stringTable(query) end   -- recursively adds a list of qid to an existing list, based on the results of a query function wd.addVals(list, query, maxdepth, maxnodes, stopval) 	maxdepth = tonumber(maxdepth) or 10 	maxnodes = tonumber(maxnodes) or 100 	if (maxdepth < 0) then 		return list 	end 	if stopval and wd.isHere(list, stopval) then 		return list 	end 	local origsize = #list 	for i = 1, origsize do 		-- tried a  "checkpos" param instead of starting to 1 each time, but no impact on performance 		local candidates = wd.getIds(list[i], query) 		list = wd.addNewValues(list, candidates, maxnodes, stopval) 		if list[#list] == stopval then 			return list 		end 		if #list >= maxnodes then 			return list 		end 	  end 	if (#list == origsize) then 		return list 	end 	return wd.addVals(list, query, maxdepth - 1, maxnodes, stopval, origsize + 1) end  -- returns a list of items transitively matching a query (orig item is not included in the list)  function wd.transitiveVals(item, query, maxdepth, maxnodes, stopval) 	maxdepth = tonumber(maxdepth) or 5 	if type(query) == "string" then 		query = {property = query} 	end  	-- récupération des valeurs 	local vals = wd.getIds(item, query) 	if not vals then 		return nil 	end 	local v = wd.addVals(vals, query, maxdepth - 1, maxnodes, stopval)  	if not v then 		return nil 	end  	-- réarrangement des valeurs 	if query.valorder == "inverted" then 		local a = {} 		for i, j in pairs(v) do 			table.insert(a, 1, j) 		end 		v = a 	end  	return v end  -- returns true if an item is the value of a query, transitively function wd.inTransitiveVals(searchedval, sourceval, query, maxdepth, maxnodes ) 	local vals = wd.transitiveVals(sourceval, query, maxdepth, maxnodes, searchedval ) 	if (not vals) then  		return false 	end 	for _, val in ipairs(vals) do 		if (val == searchedval) then 			return true 		end 	end 	return false end  -- returns true if an item is a superclass of another, based on P279 function wd.isSubclass(class, item, maxdepth) 	local query = {property = 'P279'} 	if class == item then -- item is a subclass of itself iff it is a class 		if wd.getIds(item, query) then 			return true 		end 		return false 	end 	return wd.inTransitiveVals(class, item, query, maxdepth ) end  -- returns true if one of the best ranked P31 values of an item is the target or a subclass of the target -- rank = 'valid' would seem to make sense, but it would need to check for date qualifiers as some P31 values have begin or end date function wd.isInstance(targetclass, item, maxdepth) 	maxdepth = maxdepth or 10 	local directclasses = wd.transitiveVals(item, {property = 'P31'}, 1) 	if not directclasses then 		return false 	end 	for i, class in pairs(directclasses) do 		if wd.isSubclass(targetclass, class, maxdepth - 1) then 			return true 		end 	end 	return false end  -- return the first value in a transitive query that belongs to a particular class. For instance find a value of P131 that is a province of Canada function wd.findVal(sourceitem, targetclass, query, recursion, instancedepth) 	if type(query) == "string" then 		query = {property = query} 	end 	local candidates = wd.getIds(sourceitem, query) 	if candidates then 		for i, j in pairs(candidates) do 			if wd.isInstance(targetclass, j,  instancedepth) then 				return j 			end 		end 		if not recursion then 			recursion = 3 		else 			recursion = recursion - 1 		end 		if recursion < 0 then 			return nil 		end 		for i, candidate in pairs(candidates) do 			return wd.findVal(candidate, targetclass, query, recursion, instancedepth) 		end 	end end   -- === VARIA === function wd.getDescription(entity, lang) 	lang = lang or defaultlang  	local description 	if lang == defaultlang then 		return  mw.wikibase.descriptionl(qid) 	end 	if not entity.descriptions then 		return wd.translate('no description') 	end 	local descriptions = entity.descriptions 	if not descriptions then 		return nil 	end 	if descriptions[lang] then 		return descriptions[delang].value 	end 	return entity.id end   function wd.Dump(entity) 	entity = wd.getEntity(entity) 	if not entity then 		return formatError("entity-param-not-provided") 	end 	return "<pre>"..mw.dumpObject(entity).."</pre>" end  function wd.frameFun(frame) 	local args = frame.args 	local funname = args[1] 	table.remove(args, 1) 	return wd[funname](args) end   return wd