Module:Wikidata
Apparence
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/Lualocalwd={}-- creation of a subobject to store comparison funtions, used for sorting claims-- to be able to build more complex sorts like topological sortswd.compare={}localdatabases={}localmodules={}localdatabasesNames={-- modules de données statiques pouvant être appelés avec mw.loadData(), ne nécessitant pas require()i18n='Module:Wikidata/I18n',globes='Module:Wikidata/Globes',langhierarchy='Module:Wikidata/Hiérarchie des langues',langcodes='Module:Dictionnaire Wikidata/Codes langue',-- big, infrequently usedainvertedlangcodes='Module:Dictionnaire Wikidata/Codes langue/inversé'}localmodulesNames={reference='Module:Wikidata/Références',linguistic='Module:Linguistique',datemodule='Module:Date',formatDate='Module:Date complexe',formatNum='Module:Conversion',langmodule='Module:Langue',cite='Module:Biblio',weblink='Module:Weblink'}localfunctionloadDatabase(t,key)ifdatabasesNames[key]thenlocalm=mw.loadData(databasesNames[key])t[key]=mreturnmendendlocalfunctionloadModule(t,key)ifmodulesNames[key]thenlocalm=require(modulesNames[key])t[key]=mreturnmendendsetmetatable(databases,{__index=loadDatabase})setmetatable(modules,{__index=loadModule})-- ainsi le require() sera opéré seulement si nécessaire par modules.(nom du module)localdatequalifiers={'P585','P571','P580','P582','P1319','P1326'}-- === I18n ===localdefaultlang=mw.getContentLanguage():getCode()functionwd.translate(str,rep1,rep2)str=databases.i18n[str]orstrifrep1and(type(rep1)=='string')thenstr=str:gsub('$1',rep1)endifrep2and(type(rep2)=='string')thenstr=str:gsub('$2',rep2)endreturnstrendlocalfunctionaddCat(cat,sortkey)ifsortkeythenreturn'[[Category:'..cat..'|'..sortkey..']]'endreturn'[[Category:'..cat..']]'endlocalfunctionformatError(key,category,debug)ifdebugthenreturnerror(databases.i18n[key]orkey)endifcategorythenreturnaddCat(category,key)elsereturnaddCat('cat-unsorted-issue',key)endend-- functionwd.isSpecial(snak)return(snak.snaktype~='value')endfunctionwd.getId(snak)if(snak.snaktype=='value')thenreturn'Q'..snak.datavalue.value['numeric-id']endendfunctionwd.getNumericId(snak)if(snak.snaktype=='value')thenreturnsnak.datavalue.value['numeric-id']endendfunctionwd.getMainId(claim)returnwd.getId(claim.mainsnak)endfunctionwd.entityId(entity)iftype(entity)=='string'thenreturnentityelseiftype(entity)=='table'thenreturnentity.idendendfunctionwd.getEntityIdForCurrentPage()returnmw.wikibase.getEntityIdForCurrentPage()end-- function that returns true if the "qid" parameter is the qid -- of the item that is linked to the calling pagefunctionwd.isPageOfQId(qid)localself_id=mw.wikibase.getEntityIdForCurrentPage()returnself_id~=nilandqid==self_idendfunctionwd.getEntity(val)iftype(val)=='table'thenreturnvalendifval=='-'thenreturnnilendifval==''thenval=nilendreturnmw.wikibase.getEntity(val)endfunctionwd.splitStr(val)-- transforme en table les chaînes venant du Wikitexte qui utilisent des virgules de séparationiftype(val)=='string'thenval=mw.text.split(val,",")endreturnvalendfunctionwd.isHere(searchset,val,matchfunction)fori,jinpairs(searchset)doifmatchfunctionthenifmatchfunction(val,j)thenreturntrueendelseifval==jthenreturntrueendendendreturnfalseendlocalfunctionwikidataLink(entity)localname=':d:'iftype(entity)=='string'thenifentity:match("P[0-9]+")thenentity="Property:"..entityendreturnname..entityelseiftype(entity)=='table'thenifentity["type"]=="property"thenname=":d:Property:"endreturnname..entity.idelseiftype(entity)==nilthenreturnformatError('entity-not-found')endendfunctionwd.siteLink(entity,project,lang)-- returns 3 values: a sitelink (with the relevant prefix) a project name and a languagelang=langordefaultlangif(type(project)~='string')thenproject='wiki'endproject=project:lower()ifproject=='wikipedia'thenproject='wiki'endiftype(entity)=='string'and(project=='wiki')and((notlangorlang==defaultlang))then-- évite de charger l'élément entierlocallink=mw.wikibase.getSitelink(entity)iflinkthenlocaltest_redirect=mw.title.new(link)-- remplacement des redirections (retirer si trop coûteux)iftest_redirect.isRedirectandtest_redirect.redirectTargetthenlink=test_redirect.redirectTarget.fullTextendendreturnlink,'wiki',defaultlangendifproject=='wikidata'thenreturnwikidataLink(entity),'wikidata'endlocalprojects={-- nom = {préfixe sur Wikidata, préfix pour les liens sur Wikipédia, ajouter préfixe de langue}wiki={'wiki',nil,true},-- wikipediacommons={'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}}localentityid=entity.idorentitylocalprojectdata=projects[project:lower()]ifnotprojectdatathen-- defaultlink might be in the form "dewiki" rather than "project: 'wiki', lang: 'de' "fork,vinpairs(projects)doifproject:match(k..'$')andmw.language.isKnownLanguageTag(project:sub(1,#project-#k))thenlang=project:sub(1,#project-#k)project=project:sub(#lang+1,#project)projectdata=projects[project]breakendendifnotmw.language.isKnownLanguageTag(lang)thenreturn--formatError('invalid-project-code', projet or 'nil')endendifnotprojectdatathenreturn-- formatError('invalid-project-code', projet or 'nil')endlocallinkcode=projectdata[1]localprefix=projectdata[2]localmultiversion=projectdata[3]ifmultiversionthenlinkcode=lang..linkcodeendlocallink=mw.wikibase.getSitelink(entityid,linkcode)ifnotlinkthenreturnnilendifprefixthenlink=prefix..':'..linkendifmultiversionthenlink=':'..lang..':'..linkendreturnlink,project,langend-- add new values to a list, avoiding duplicatesfunctionwd.addNewValues(olditems,newitems,maxnum,stopval)ifnotnewitemsthenreturnolditemsendfor_,qidinpairs(newitems)doifstopvaland(qid==stopval)thentable.insert(olditems,qid)returnolditemsendifmaxnumand(#olditems>=maxnum)thenreturnolditemsendifnotwd.isHere(olditems,qid)thentable.insert(olditems,qid)endendreturnolditemsend--=== FILTER CLAIMS ACCORDING TO VARIOUS CRITERIA : FUNCTION GETCLAIMS et alii ===localfunctionnotSpecial(claim)localtypeifclaim.mainsnak~=nilthentype=claim.mainsnak.snaktypeelse-- condition respectée quand showonlyqualifier est un paramètre renseigné-- dans ce cas, claim n'est pas une déclaration entière, mais UNE snak qualifiée du main snaktype=claim.snaktypeendreturntype=='value'endlocalfunctionhasTargetValue(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 excludespeciallocalid=wd.getMainId(claim)localtargets=wd.splitStr(targets)returnwd.isHere(targets,id)orwd.isSpecial(claim.mainsnak)endlocalfunctionexcludeValues(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)returnwd.isSpecial(claim.mainsnak)ornot(hasTargetValue(claim,values))endlocalfunctionhasTargetClass(claim,targets,maxdepth)-- retourne true si la valeur est une instance d'une classe dans la liste des target, ou si c'est une valeur spéciale filtrée séparément par excludespeciallocalid=wd.getMainId(claim)localtargets=wd.splitStr(targets)localmaxdepth=maxdepthor10localmatchfunction=function(value,target)returnwd.isInstance(target,value,maxdepth)endreturnwd.isHere(targets,id,matchfunction)orwd.isSpecial(claim.mainsnak)endlocalfunctionexcludeClasses(claim,classes)-- true si la valeur n'est pas une instance d'une classe dans la liste, ou si c'est une valeur spéciale (filtrée à part par excludespecial)returnwd.isSpecial(claim.mainsnak)ornot(hasTargetClass(claim,classes,maxdepth))endlocalfunctionhasTargetSuperclass(claim,targets,maxdepth)-- retourne true si la valeur est une sous-classe d'une classe dans la liste des target, ou si c'est une valeur spéciale filtrée séparément par excludespeciallocalid=wd.getMainId(claim)localtargets=wd.splitStr(targets)localmaxdepth=maxdepthor10localmatchfunction=function(value,target)returnwd.isSubclass(target,value,maxdepth)endreturnwd.isHere(targets,id,matchfunction)orwd.isSpecial(claim.mainsnak)endlocalfunctionexcludeSuperclasses(claim,classes)-- true si la valeur n'est pas une sous-classe d'une classe dans la liste, ou si c'est une valeur spéciale (filtrée à part par excludespecial)returnwd.isSpecial(claim.mainsnak)ornot(hasTargetSuperclass(claim,classes,maxdepth))endlocalfunctionbestRanked(claims)ifnotclaimsthenreturnnilendlocalpreferred,normal={},{}fori,jinpairs(claims)doifj.rank=='preferred'thentable.insert(preferred,j)elseifj.rank=='normal'thentable.insert(normal,j)endendif#preferred>0thenreturnpreferredelsereturnnormalendendlocalfunctionwithRank(claims,target)iftarget=='best'thenreturnbestRanked(claims)endlocalnewclaims={}forpos,claiminpairs(claims)doiftarget=='valid'thenifclaim.rank~='deprecated'thentable.insert(newclaims,claim)endelseifclaim.rank==targetthentable.insert(newclaims,claim)endendreturnnewclaimsendfunctionwd.hasQualifier(claim,acceptedqualifs,acceptedvals,excludequalifiervalues)localclaimqualifs=claim.qualifiersif(notclaimqualifs)thenreturnfalseendacceptedqualifs=wd.splitStr(acceptedqualifs)acceptedvals=wd.splitStr(acceptedvals)localfunctionok(qualif)-- vérification pour un qualificatif individuelifnotclaimqualifs[qualif]thenreturnfalseendifnot(acceptedvals)then-- si aucune valeur spécifique n'est demandée, OKreturntrueendfori,wantedinpairs(acceptedvals)doforj,actualinpairs(claimqualifs[qualif])doifwd.getId(actual)==wantedthenreturntrueendendendendfori,qualifinpairs(acceptedqualifs)doifok(qualif)thenreturntrueendendreturnfalseendfunctionwd.hasQualifierNumber(claim,acceptedqualifs,acceptedvals,excludequalifiervalues)localclaimqualifs=claim.qualifiersif(notclaimqualifs)thenreturnfalseendacceptedqualifs=wd.splitStr(acceptedqualifs)acceptedvals=wd.splitStr(acceptedvals)localfunctionok(qualif)-- vérification pour un qualificatif individuelifnotclaimqualifs[qualif]thenreturnfalseendifnot(acceptedvals)then-- si aucune valeur spécifique n'est demandée, OKreturntrueendfori,wantedinpairs(acceptedvals)doforj,actualinpairs(claimqualifs[qualif])doifmw.wikibase.renderSnak(actual)==wantedthenreturntrueendendendendfori,qualifinpairs(acceptedqualifs)doifok(qualif)thenreturntrueendendreturnfalseendlocalfunctionhasSource(claim,targetsource,sourceproperty)sourceproperty=sourcepropertyor'P248'iftargetsource=="-"thenreturntrueendif(notclaim.references)thenreturnfalseendlocalcandidates=claim.references[1].snaks[sourceproperty]-- les snaks utilisant la propriété demandéeif(notcandidates)thenreturnfalseendif(targetsource=="any")then-- si n'importe quelle valeur est acceptée tant qu'elle utilise en ref la propriété demandéereturntrueendtargetsource=wd.splitStr(targetsource)for_,sourceinpairs(candidates)dolocals=wd.getId(source)fori,targetinpairs(targetsource)doifs==targetthenreturntrueendendendreturnfalseendlocalfunctionexcludeQualifier(claim,qualifier,qualifiervalues)returnnotwd.hasQualifier(claim,qualifier,qualifiervalues)endfunctionwd.hasDate(claim)ifnotclaimthenreturnfalse--error() ?endifwd.getDateFromQualif(claim,'P585')orwd.getDateFromQualif(claim,'P580')orwd.getDateFromQualif(claim,'P582')thenreturntrueendreturnfalseendlocalfunctionhasLink(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 çareturntrueendlocalid=wd.getMainId(claim)locallink=wd.siteLink(id,site,lang)iflinkthenreturntrueendendlocalfunctionisInLanguage(claim,lang)-- ne fonctionne que pour les monolingualtext / étendre aux autres types en utilisant les qualifiers ?iftype(lang)=='table'then-- si c'est une table de language séparées par des virgules, on les accepte toutesfori,linpairs(lang)dolocalv=isInLanguage(claim,l)ifvthenreturntrueendendendiftype(lang)~=('string')thenreturn--?endif(lang=='-')thenreturntrueendif(lang=='locallang')thenlang=mw.getContentLanguage():getCode()end-- pour les monolingual textlocalsnak=claim.mainsnakorclaimifsnak.snaktype=='value'andsnak.datavalue.type=='monolingualtext'thenifsnak.datavalue.value.language==langthenreturntrueendreturnfalseend-- pour les autres types de données : recherche dans les qualificatifsif(lang=='ht')thenlang='Q150'elseif(lang=='en')thenlang='Q1860'elselang=databases.invertedlangcodes[lang]endifclaim.qualifiersandclaim.qualifiers.P407thenifwd.hasQualifier(claim,{'P407'},{lang})thenreturntrueelsereturnfalseendendreturntrue-- si on ne ne sait pas la langue, on condière que c'est bonendlocalfunctionfirstVals(claims,numval)-- retourn les numval premières valeurs de la table claimslocalnumval=tonumber(numval)or0-- raise a error if numval is not a positive integer ?ifnotclaimsthenreturnnilendwhile(#claims>numval)dotable.remove(claims)endreturnclaimsendlocalfunctionlastVals(claims,numval2)-- retourn les valeurs de la table claims à partir de numval2localnumval2=tonumber(numval2)or0-- raise a error if numval is not a positive integer ?ifnotclaimsthenreturnnilendfori=1,numval2dotable.remove(claims,1)endreturnclaimsend-- retourne les valeurs de la table claims à partir de removedupesdate,-- sans les dates en doublons avec conversion entre les calendrier julien et grégorien,-- ou uniquement en catégorisant si le paramètre removedupesdate est égale à 'cat'localfunctionremoveDupesDate(claims,removedupesdate)ifnotclaimsor#claims<2thenreturnclaims,''endlocalcat=''localnewClaims={}localnewIsos={}localfunctionfindIndex(searchset,val)-- similaire à wd.isHere mais retourne l'index de la valeur trouvéefori,jinpairs(searchset)doifval==jthenreturniendendreturn-1endfor_,claiminipairs(claims)dolocalsnak=claim.mainsnakorclaimif(snak.snaktype=='value')and(snak.datatype=='time')andsnak.datavalue.value.precision>=11then-- s'il s'agit d'un time et que la précision est au moins l'annéelocaliso=snak.datavalue.value.time_,_,iso=string.find(iso,"(+%d+-%d+-%d+T)")localdeleteIfDuplicate=falseifsnak.datavalue.value.calendarmodel=='http://www.wikidata.org/entity/Q1985727'then-- si la date est grégorienneifmodules.formatDate.before('+1582',iso)then-- si avant 1582 on calcule la date julienne_,_,y,m,d=string.find(iso,"+(%d+)-(%d+)-(%d+)T")y,m,d=modules.datemodule.gregorianToJulian(y,m,d)ifm<10thenm='0'..mendifd<10thend='0'..dendiso='+'..y..'-'..m..'-'..d..'T'deleteIfDuplicate=trueendlocalindex=findIndex(newIsos,iso)ifindex>=0then-- si la date est déjà présentecat=cat..'[[Catégorie:Article avec des dates identiques venant de wikidata dans le code de l\'infobox]]'ifremovedupesdate=="cat"then-- ne faire que catégorisertable.insert(newIsos,iso)table.insert(newClaims,claim)elseifnotdeleteIfDuplicatethen-- supprimer l'autre date si la date courante n'a pas été convertienewClaims[index]=claimend-- sinon supprimer la date couranteelse-- pas de doublontable.insert(newIsos,iso)table.insert(newClaims,claim)endelseifsnak.datavalue.value.calendarmodel=='http://www.wikidata.org/entity/Q1985786'then-- si date julienneifnotmodules.formatDate.before('+1582',iso)then-- si après 1582 on calcule la date grégorienne_,_,y,m,d=string.find(iso,"+(%d+)-(%d+)-(%d+)T")y,m,d=modules.datemodule.julianToGregorian(y,m,d)ifm<10thenm='0'..mendifd<10thend='0'..dendiso='+'..y..'-'..m..'-'..d..'T'deleteIfDuplicate=trueendlocalindex=findIndex(newIsos,iso)ifindex>=0then-- si date déjà présentecat=cat..'[[Kategori:Atik avèk dat idantik ki soti nan wikidata nan kòd infobox]]'ifremovedupesdate=="cat"then-- ne faire que catégorisertable.insert(newIsos,iso)table.insert(newClaims,claim)elseifnotdeleteIfDuplicatethen-- supprimer l'autre date si la date courante n'a pas été convertienewClaims[index]=claimend-- sinon supprimer la date couranteelse-- pas de doublontable.insert(newIsos,iso)table.insert(newClaims,claim)endelse-- autre calendriertable.insert(newIsos,iso)table.insert(newClaims,claim)endelse-- précision insuffisantetable.insert(newIsos,iso)table.insert(newClaims,claim)endendreturnnewClaims,catendlocalfunctiontimeFromQualifs(claim,qualifs)localclaimqualifs=claim.qualifiersifnotclaimqualifsthenreturnnilendfori,qualifinipairs(qualifsordatequalifiers)dolocalvals=claimqualifs[qualif]ifvalsand(vals[1].snaktype=='value')thenreturnvals[1].datavalue.value.time,vals[1].datavalue.value.precisionendendendlocalfunctionatDate(claim,mydate)ifmydate=="today"thenmydate=os.date("!%Y-%m-%dT%TZ")end-- determines required precision depending on the atdate formatlocald=mw.text.split(mydate,"-")localmyprecisionifd[3]thenmyprecision=11-- dayelseifd[2]thenmyprecision=10-- monthelsemyprecision=9-- yearend-- with point in timelocald,storedprecision=timeFromQualifs(claim,{'P585'})ifdthenreturnmodules.formatDate.equal(mydate,d,math.min(myprecision,storedprecision))end-- with start or end date -- TODO: precision localmindate=timeFromQualifs(claim,{'P580'})localmaxdate=timeFromQualifs(claim,{'P582'})ifmodules.formatDate.before(mydate,mindate)andmodules.formatDate.before(maxdate,mydate)thenreturntrueendreturnfalseendlocalfunctioncheck(claim,condition)iftype(condition)=='function'then-- cas standardreturncondition(claim)endreturnformatError('invalid type','function',type(condition))endlocalfunctionminPrecision(claim,minprecision)localsnakifclaim.qualifiersthen-- si une date est donnée en qualificatif, c'est elle qu'on utilise de préférence au mainsnakfori,jinipairs(datequalifiers)doifclaim.qualifiers[j]thensnak=claim.qualifiers[j][1]breakendendendifnotsnakthensnak=claim.mainsnakorclaimendif(snak.snaktype=='value')and(snak.datatype=='time')and(snak.datavalue.value.precision<minprecision)thenreturnfalseendreturntrueendfunctionwd.sortClaims(claims,sorttype)ifnotclaimsthenreturnnilendifwd.isHere({'chronological','order','inverted','age','ageinverted'},sorttype)thenreturnwd.chronoSort(claims,sorttype)elseifsorttype=='ascending'thenreturnwd.quantitySort(claims)elseifsorttype=='descending'thenreturnwd.quantitySort(claims,true)elseiftype(sorttype)=='function'thentable.sort(claims,sorttype)returnclaimselseiftype(sorttype)=='string'andsorttype:sub(1,1)=='P'thenreturnwd.numericPropertySort(claims,sorttype)endreturnclaimsendfunctionwd.filterClaims(claims,args)--retire de la tables de claims celles qui sont éliminés par un des filters de la table des filterslocalfunctionfilter(condition,filterfunction,funargs)ifnotargs[condition]thenreturnendfori=#claims,1,-1doifnot(filterfunction(claims[i],args[funargs[1]],args[funargs[2]],args[funargs[3]]))thentable.remove(claims,i)endendendfilter('isinlang',isInLanguage,{'isinlang'})filter('excludespecial',notSpecial,{})filter('condition',check,{'condition'})ifclaims[1]andclaims[1].mainsnakthenfilter('targetvalue',hasTargetValue,{'targetvalue'})filter('targetclass',hasTargetClass,{'targetclass'})filter('targetsuperclass',hasTargetSuperclass,{'targetsuperclass'})filter('atdate',atDate,{'atdate'})filter('qualifier',wd.hasQualifier,{'qualifier','qualifiervalue'})filter('qualifiernumber',wd.hasQualifierNumber,{'qualifiernumber','qualifiernumbervalue'})filter('excludequalifier',excludeQualifier,{'excludequalifier','excludequalifiervalue'})filter('withsource',hasSource,{'withsource','sourceproperty'})filter('withdate',wd.hasDate,{})filter('excludevalues',excludeValues,{'excludevalues'})filter('excludeclasses',excludeClasses,{'excludeclasses'})filter('excludesuperclasses',excludeSuperclasses,{'excludesuperclasses'})filter('withlink',hasLink,{'withlink','linklang'})filter('minprecision',minPrecision,{'minprecision'})claims=withRank(claims,args.rankor'best')endif#claims==0thenreturnnilendifargs.sorttypethenclaims=wd.sortClaims(claims,args.sorttype)endifargs.numval2thenclaims=lastVals(claims,args.numval2)endifargs.numvalthenclaims=firstVals(claims,args.numval)endreturnclaimsendfunctionwd.loadEntity(entity,cache)iftype(entity)~='table'thenifcachethenifnotcache[entity]thencache[entity]=mw.wikibase.getEntity(entity)mw.log("cached")endreturncache[entity]elseifentity==''or(entity=='-')thenentity=nilendreturnmw.wikibase.getEntity(entity)endelsereturnentityendendfunctionwd.getClaims(args)-- returns a table of the claims matching some conditions given in argsifargs.claimsthen-- if claims have already been set, return themreturnargs.claimsendlocalproperties=args.propertyiftype(properties)=='string'thenproperties=wd.splitStr(string.upper(args.property))endifnotpropertiesthenreturnformatError('property-param-not-provided')end--Get entitylocalentity=args.entityiftype(entity)=='string'thenifentity==''thenentity=nilendelseiftype(entity)=='table'thenentity=entity.idendif(notentity)thenentity=mw.wikibase.getEntityIdForCurrentPage()endif(notentity)or(entity=='-')or(entity==wd.translate('somevalue'))or(entity==modules.linguistic.ucfirst(wd.translate('somevalue')))thenreturnnilendifargs.labelformatandargs.labelformat=='gendered'thenlocallonggender={m='male',f='female'}args.labelformat=longgender[wd.getgender(entity)]endlocalclaims={}if#properties==1thenclaims=mw.wikibase.getAllStatements(entity,properties[1])-- do not use mw.wikibase.getBestStatements at this stage, as it may remove the best ranked values that match other criteria in the queryelsefori,propinipairs(properties)dolocalnewclaims=mw.wikibase.getAllStatements(entity,prop)ifnewclaimsand#newclaims>0thenforj,claiminipairs(newclaims)dotable.insert(claims,claim)endendendendif(notclaims)or(#claims==0)thenreturnnilendreturnwd.filterClaims(claims,args)end--=== ENTITY FORMATTING ===functionwd.getLabel(entity,lang1,lang2)if(notentity)thenreturnnil-- ou option de gestion des erreurs ?endentity=entity.idor(type(entity)=="string"andentity)ifnot(type(entity)=='string')thenreturnnilendlang1=lang1ordefaultlanglocalstr,lang--str : texte rendu, lang : langue de celui-ciiflang1==defaultlangthen-- le plus économiquestr,lang=mw.wikibase.getLabelWithLang(entity)-- le libellé peut être en français ou en anglaiselsestr=mw.wikibase.getLabelByLang(entity,lang1)ifstrthenlang=lang1endendifstrand(lang==lang1orlang=="mul")then--pas de catégorie "à traduire" si on a obtenu un texte dans la langue désirée (normalement fr) ou multilinguereturnstrendiflang2then-- langue secondaire, avec catégorie "à traduire"str2=mw.wikibase.getLabelByLang(entity,lang2)ifstr2thenlang=lang2str=str2endendifnotstrthen--si ni lang1, ni lang2 ni l'anglais ne sont présents, parcours de la hiérarchie des languesfor_,trylanginipairs(databases.langhierarchy.codes)dostr=mw.wikibase.getLabelByLang(entity,trylang)ifstrthenlang=trylangbreakendendendifstrthenlocaltranslationCat=databases.i18n['to translate']translationCat=translationCat..(databases.langhierarchy.cattext[lang]or'')translationCat=addCat(translationCat)returnstr,translationCatendendfunctionwd.formatEntity(entity,params)if(notentity)thenreturnnil--formatError('entity-not-found')endlocalid=entityiftype(id)=='table'thenid=id.idendparams=paramsor{}locallang=params.langordefaultlanglocalspeciallabels=params.speciallabelslocaldisplayformat=params.displayformatlocallabelformat=params.labelformatlocallabelformat2=params.labelformat2localdefaultlabel=params.defaultlabeloridlocallinktype=params.linklocaldefaultlink=params.defaultlinklocaldefaultlinkquery=params.defaultlinkqueryifspeciallabelsandspeciallabels[id]then--speciallabels override the standard label + link combinationreturnspeciallabels[id]endifparams.displayformat=='raw'thenreturnidendifparams.labelformat=='male'thenlabelformat=function(objectid)returnwd.genderedlabel(objectid,'m')endendifparams.labelformat=='female'thenlabelformat=function(objectid)returnwd.genderedlabel(objectid,'f')endendlocallabel,translationCatiftype(labelformat)=='function'then-- sert à des cas particulierslabel,translationCat=labelformat(entity)endifnotlabelthenlabel,translationCat=wd.getLabel(entity,lang,params.wikidatalang)endiftype(labelformat2)=='function'andlabelthen-- sert à des cas particulierslabel=labelformat2(label)endtranslationCat=translationCator""-- sera toujours ajoutée au résultat mais sera vide si la catégorie de maintenance n'est pas nécessaireifnotlabelthenif(defaultlabel=='-')thenreturnnilendlocallink=wd.siteLink(id,'wikidata')return'[['..link..'|'..id..']]'..translationCat-- si pas de libellé, on met un lien vers Wikidata pour qu'on comprenne à quoi ça fait référenceend-- détermination du fait qu'on soit ou non en train de rendre l'élément sur la page de son articlelocalrendering_entity_on_its_page=wd.isPageOfQId(id)if(linktype=='-')orrendering_entity_on_its_pagethenreturnlabel..translationCatendlocallink=wd.siteLink(entity,linktype,lang)-- defaultlinkquery will try to link to another page on this Wikiif(notlink)anddefaultlinkquerytheniftype(defaultlinkquery)=='string'thendefaultlinkquery={property=defaultlinkquery}enddefaultlinkquery.excludespecial=truedefaultlinkquery.entity=entitylocalclaims=wd.getClaims(defaultlinkquery)ifclaimsthenfori,jinpairs(claims)dolocalid=wd.getMainId(j)link=wd.siteLink(id,linktype,lang)iflinkthenbreakendendendendiflinktheniflink:match('^Category:')orlink:match('^Kategori:')then-- attention, le « é » est multibyte-- lier vers une catégorie au lieu de catégoriserlink=':'..linkendreturn'[['..link..'|'..label..']]'..translationCatend-- if not link, you can use defaultlink: a sidelink to another Wikimedia projectif(notdefaultlink)thendefaultlink={'enwiki'}endifdefaultlinkand(defaultlink~='-')thenlocallinktypelocalsidelink,site,langcodeiftype(defaultlink)=='string'thendefaultlink={defaultlink}endfori,jinipairs(defaultlink)dosidelink,site,langcode=wd.siteLink(entity,j,lang)ifsidelinkthenbreakendendifnotsidelinkthensidelink,site=wd.siteLink(entity,'wikidata')endlocalicon,class,title=site,nil,nil-- le texte affiché du lienifsite=='wiki'thenicon,class,title=langcode,"indicateur-langue",wd.translate('see-another-language',mw.language.fetchLanguageName(langcode,defaultlang))elseifsite=='wikidata'thenicon,class,title='d',"indicateur-langue",wd.translate('see-wikidata')elsetitle=wd.translate('see-another-project',site)endlocalval='[['..sidelink..'|'..'<span class = "'..(classor'')..'" title = "'..(titleor'')..'">'..icon..'</span>]]'returnlabel..' <small>('..val..')</small>'..translationCatendreturnlabel..translationCatendfunctionwd.addTrackingCat(prop,cat)-- doit parfois être appelé par d'autres modulesiftype(prop)=='table'thenprop=prop[1]-- devrait logiquement toutes les ajouterendifnotpropandnotcatthenreturnformatError("property-param-not-provided")endifnotcatthencat=wd.translate('trackingcat',propor'P??')endreturnaddCat(cat)endlocalfunctionunknownValue(snak,label)localstr=labeliftype(str)=="function"thenstr=str(snak)endif(notstr)thenifsnak.datatype=='time'thenstr=wd.translate('sometime')elsestr=wd.translate('somevalue')endendiftype(str)~="string"thenreturnformatError(snak.datatype)endreturnstrendlocalfunctionnoValue(displayformat)ifnotdisplayformatthenreturnwd.translate('novalue')endiftype(displayformat)=='string'thenreturndisplayformatendreturnformatError()endlocalfunctiongetLangCode(entityid)returndatabases.langcodes[tonumber(entityid:sub(2))]endlocalfunctionshowLang(statement)-- retourne le code langue entre parenthèses avant la valeur (par exemple pour les biblios et liens externes)localmainsnak=statement.mainsnakifmainsnak.snaktype~='value'thenreturnnilendlocallanglist={}ifmainsnak.datavalue.type=='monolingualtext'thenlanglist={mainsnak.datavalue.value.language}elseif(notstatement.qualifiers)or(notstatement.qualifiers.P407)thenreturnelsefori,jinpairs(statement.qualifiers.P407)doifj.snaktype=='value'thenlocallangentity=wd.getId(j)locallangcode=getLangCode(langentity)table.insert(langlist,langcode)endendendif(#langlist>1)or(#langlist==1andlanglist[1]~=defaultlang)then-- si c'est en français, pas besoin de le direlanglist.maxLang=3returnmodules.langmodule.indicationMultilingue(langlist)endend-- === DATE HANDLING ===localfunctionfuzzydate(str,precision)-- ajoute le qualificatif "vers" à une dateifnotstrthenreturnnilendif(precision>=11)or(precision==7)or(precision==6)then--dates avec jour, siècles, millénairesreturn"vers le "..strendif(precision==8)then--décennies ("années ...")return"vers les "..strendreturn"vers "..strendfunctionwd.addStandardQualifs(str,statement,onlygeneral)-- qualificateurs de date ou de lieu approximatif ou d'info globalement incertaine ; onlygenereal=true pour rerstreindre à ces derniersif(notstatement)or(notstatement.qualifiers)thenreturnstrendifnotstrthenreturnerror()-- what's that ?endifstatement.qualifiers.P1480thenfori,jinpairs(statement.qualifiers.P1480)dolocalv=wd.getId(j)if(v=="Q21818619")andnotonlygeneralthen--"à proximité de"str=wd.translate('approximate-place',str)elseif(v=="Q18122778")or(v=="Q18912752")or(v=="Q56644435")or(v=="Q30230067")then--"présumé", "controversé", "probablement", "possible"str=wd.translate('uncertain-information',str)elseif(v=="Q5727902")andnotonlygeneralandstatement.mainsnak.datatype=='time'then--date approximativelocaldatevalue=statement.mainsnak.datavalueifdatevaluethenstr=fuzzydate(str,datevalue.value.precision)endendendendreturnstrendfunctionwd.getDateFromQualif(statement,qualif)if(notstatement)or(notstatement.qualifiers)ornot(statement.qualifiers[qualif])thenreturnnilendlocalv=statement.qualifiers[qualif][1]ifv.snaktype~='value'then-- que faire dans ce cas ?returnnilendreturnmodules.formatDate.dateObject(v.datavalue.value)endfunctionwd.getDate(statement)localperiod=wd.getDateFromQualif(statement,'P585')-- retourne un dateobjectifperiodthenreturnperiodendlocalbegin,ending=wd.getDateFromQualif(statement,'P580'),wd.getDateFromQualif(statement,'P582')ifbeginorendingthenreturnmodules.formatDate.rangeObject(begin,ending)-- retourne un rangeobject fait de deux dateobjectendreturnnilendfunctionwd.getFormattedDate(statement,params)ifnotstatementthenreturnnilendlocalstr--cherche la date avec les qualifs P580/P582localdatetable=wd.getDate(statement)ifdatetablethenstr=modules.formatDate.objectToText(datetable,params)end-- puis limite intérieur / supérieurifnotstrthenlocalstart,ending=wd.getDateFromQualif(statement,'P1319'),wd.getDateFromQualif(statement,'P1326')str=modules.formatDate.between(start,ending,params)endlocalfromqualif=falseifstrthenfromqualif=trueend--si la date est tirée des qualificateurs, on n'y ajoute pas l'éventuel "vers ..."-- sinon, le mainsnak, pour les données de type timeif(notstr)and(statement.mainsnak.datatype=='time')thenlocalmainsnak=statement.mainsnakif(mainsnak.snaktype=='value')or(mainsnak.snaktype=='somevalue')thenstr=wd.formatSnak(mainsnak,params)endendifstrandparamsand(params.addstandardqualifs~='-')thenstr=wd.addStandardQualifs(str,statement,fromqualif)endreturnstrendwd.compare.by_quantity=function(c1,c2)localv1=wd.getDataValue(c1.mainsnak)localv2=wd.getDataValue(c2.mainsnak)ifnot(v1andv2)thenreturntrueendreturnv1<v2end--[[ tri chronologique générique : retourne une fonction de tri de liste de déclaration en fonction d’une fonction qui calcule la clé de tri et d’une fonction qui compare les clés de tri paramètres nommés: (appel type wikidata.compare.chrono_key_sort{sortKey="nom clé"}) sortKey (optionnel) : chaine, le nom de la clé utilisée pour un tri (pour éviter de rentrer en collision avec "dateSortKey" utilisé par chronoSort au besoin) snak_key_get_function : fonction qui calcule la valeur de la clé à partir d’un snak ou d’une déclaration, (obligatoire) le résultat n’est calculé qu’une fois et est stocké en cache dans claim[sortKey] key_compare_function : fonction de comparaison des clés calculées par snak_key_get_function (optionnel)--]]functionwd.chrono_key_sort(arg)localsnak_key_get_function=arg.snak_key_get_functionlocalsortKey=arg.sortKeyor"dateSortKey"localkey_compare_function=arg.key_compare_functionorfunction(c1,c2)returnc1<c2endreturnfunction(claims)for_,claiminipairs(claims)doifnotclaim[sortKey]thenlocalkey=snak_key_get_function(claim)ifkeythenclaim[sortKey]=wd.compare.get_claim_date(key)elseclaim[sortKey]=0endendendtable.sort(claims,function(c1,c2)returnkey_compare_function(c1[sortKey],c2[sortKey])end)returnclaimsendendfunctionwd.quantitySort(claims,inverted)localfunctionsort(c1,c2)localv1=wd.getDataValue(c1.mainsnak)localv2=wd.getDataValue(c2.mainsnak)ifnot(v1andv2)thenreturntrueendifinvertedthenreturnv2<v1endreturnv1<v2endtable.sort(claims,sort)returnclaimsendfunctionwd.compare.get_claim_date(claim,datetype)-- rend une date au format numérique pour faire des comparaisonslocalsnak=claim.mainsnakorclaimifdatetypeanddatetype=='personbirthdate'then-- fonctionne avec un claim dont la valeur est une personne dont on va rendre la date de naissanceif(snak.snaktype=='value')and(snak.datatype=='wikibase-item')thenlocalpersonid=wd.getId(snak)localbirthclaims=wd.getClaims({entity=personid,property='P569',numval=1})ifbirthclaimsthenreturnwd.compare.get_claim_date(birthclaims[1]orbirthclaims)elsereturnmath.hugeendelsereturnmath.hugeend-- en cas de donnée manquante, valeur infinie qui entraîne le classement en fin de listeendlocaliso,datequalif,isonumberif(snak.snaktype=='value')and(snak.datatype=='time')theniso=snak.datavalue.value.timeelsefori,dqualifinipairs(datequalifiers)doiso=timeFromQualifs(claim,{dqualif})ifisothendatequalif=dqualifbreakendendifnotisothenreturnmath.hugeendend-- transformation en nombre (indication de la base car gsub retourne deux valeurs)isonumber=tonumber(iso:gsub('(%d)%D','%1'),10)-- ajustement de la date tenant compte du qualificatif dont elle est issue : un fait se terminant à une date est antérieur à un autre commençant à cette dateifdatequalif=='P582'then--date de finisonumber=isonumber-2elseifdatequalif=='P1326'then-- date au plus tardisonumber=isonumber-1elseifdatequalif=='P1319'then-- date au plus tôtisonumber=isonumber+1elseifdatequalif=='P571'ordatequalif=='P580'then-- date de début et date de créationisonumber=isonumber+2endreturnisonumberendfunctionwd.compare.chronoCompare(c1,c2)returnwd.compare.get_claim_date(c1)<wd.compare.get_claim_date(c2)end-- fonction pour renverser l’ordre d’une autre fonctionfunctionwd.compare.rev(comp_criteria)returnfunction(c1,c2)-- attention les tris en lua attendent des fonctions de comparaison strictement inférieur, on doit-- vérifier la non égalité quand on inverse l’ordre d’un critère, d’ou "and comp_criteria(c2,c1)"returnnot(comp_criteria(c1,c2))andcomp_criteria(c2,c1)endend-- 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.functionwd.chronoSort(claims,sorttype)for_,claiminipairs(claims)doifnotclaim.dateSortKeythenifsorttypeand(sorttype=='age'orsorttype=='ageinverted')thenclaim.dateSortKey=wd.compare.get_claim_date(claim,'personbirthdate')elseclaim.dateSortKey=wd.compare.get_claim_date(claim)endifsorttypeand(sorttype=='inverted'orsorttype=='ageinverted')andclaim.dateSortKey==math.hugethenclaim.dateSortKey=-math.huge-- quand la donnée est manquante on lui assigne la valeur qui entraîne le classement en fin de listeendendendtable.sort(claims,function(c1,c2)ifsorttypeand(sorttype=='inverted'orsorttype=='ageinverted')thenreturnc2.dateSortKey<c1.dateSortKeyendreturnc1.dateSortKey<c2.dateSortKeyend)returnclaimsendlocalfunctionget_numeric_claim_value(claim,propertySort)localvallocalclaimqualifs=claim.qualifiersifclaimqualifsthenlocalvals=claimqualifs[propertySort]ifvalsandvals[1].snaktype=='value'thenval=vals[1].datavalue.valueendendreturntonumber(valor0)endfunctionwd.compare.numeric(propertySort)returnfunction(c1,c2)returnget_numeric_claim_value(c1,propertySort)<get_numeric_claim_value(c2,propertySort)endend-- Fonction qui trie des Claims de type value selon l'ordre de la propriété fournit-- 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.functionwd.numericPropertySort(claims,propertySort)for_,claiminipairs(claims)doifnotclaim.dateSortKeythenlocalval=get_numeric_claim_value(claim,propertySort)claim.dateSortKey=tonumber(valor0)endendtable.sort(claims,function(c1,c2)returnc1.dateSortKey<c2.dateSortKeyend)returnclaimsend--[[test possible en console pour la fonction précédente : = p.formatStatements{entity = "Q375946", property = 'P50', sorttype = 'P1545', linkback = "true"}--]]-- ===================functionwd.getReferences(statement)localrefdata=statement.referencesifnotrefdatathenreturnnilendlocalrefs={}localhashes={}fori,refinpairs(refdata)dolocalslocalfunctionhasValue(prop)-- checks that the prop is here with valid valueifref.snaks[prop]andref.snaks[prop][1].snaktype=='value'thenreturntrueendreturnfalseendifref.snaks.P248then-- cas lorsque P248 (affirmé dans) est utilisé forj,sourceinpairs(ref.snaks.P248)doifsource.snaktype=='value'thenlocalpage,accessdate,quotationifhasValue('P304')then-- page page=wd.formatSnak(ref.snaks.P304[1])endifhasValue('P813')then-- date de consultationaccessdate=wd.formatSnak(ref.snaks.P813[1])endifhasValue('P1683')then-- citationquotation=wd.formatSnak(ref.snaks.P1683[1])endlocalsourceId=wd.getId(source)s=modules.reference.citeitem(sourceId,{['page']=page,['accessdate']=accessdate,['citation']=quotation})table.insert(refs,s)table.insert(hashes,ref.hash..sourceId)endendelseifhasValue('P8091')orhasValue('P854')then-- cas lorsque P8091 (Archival Resource Key) ou P854 (URL de la référence)est utilisélocalarkKey,url,title,author,publisher,accessdate,publishdate,publishlang,quotation,descriptionifhasValue('P8091')thenarkKey=wd.formatSnak(ref.snaks.P8091[1],{text="-"})url='https://n2t.net/'..arkKeyifhasValue('P1476')thentitle=wd.formatSnak(ref.snaks.P1476[1])elsetitle=arkKeyendelseifhasValue('P854')thenurl=wd.formatSnak(ref.snaks.P854[1],{text="-"})ifhasValue('P1476')thentitle=wd.formatSnak(ref.snaks.P1476[1])elsetitle=mw.ustring.gsub(url,'^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])','http%1://%3')endend--todo : handle multiple values for author, etc.ifhasValue('P1810')then-- sous le nomdescription='sous le nom '..wd.formatSnak(ref.snaks.P1810[1])endifhasValue('P813')then-- date de consultationaccessdate=wd.formatSnak(ref.snaks.P813[1])endifhasValue('P50')then-- author (item type)author=wd.formatSnak(ref.snaks.P50[1])elseifhasValue('P2093')then-- author (string type)author=wd.formatSnak(ref.snaks.P2093[1])endifhasValue('P123')then-- éditeurpublisher=wd.formatSnak(ref.snaks.P123[1])endifhasValue('P1683')then-- citationquotation=wd.formatSnak(ref.snaks.P1683[1])endifhasValue('P577')then-- date de publicationpublishdate=wd.formatSnak(ref.snaks.P577[1])endifhasValue('P407')then-- langue de l'œuvrelocalid=wd.getId(ref.snaks.P407[1])publishlang=getLangCode(id)ends=modules.cite.lienWeb{titre=title,url=url,auteur=author,editeur=publisher,langue=publishlang,['en ligne le']=publishdate,['consulté le']=accessdate,['citation']=quotation,['description']=description}table.insert(hashes,ref.hash)table.insert(refs,s)elseifref.snaks.P854andref.snaks.P854[1].snaktype=='value'thens=wd.formatSnak(ref.snaks.P854[1],{text="-"})table.insert(hashes,ref.snaks.P854[1].hash)table.insert(refs,s)endendif#refs>0thenif#hashes==#refsthenreturnrefs,hashesendreturnrefsendendfunctionwd.sourceStr(sources,hashes)ifnotsourcesor(#sources==0)thenreturnnilendlocaluseHashes=hashesand#hashes==#sourcesfori,jinipairs(sources)dolocalrefArgs={name='ref',content=j}ifuseHashesandhashes[i]~='-'thenrefArgs.args={name='wikidata-'..hashes[i]}endsources[i]=mw.getCurrentFrame():extensionTag(refArgs)endreturntable.concat(sources,'<sup class="reference cite_virgule">,</sup>')endfunctionwd.getDataValue(snak,params)ifnotparamsthenparams={}endlocalspeciallabels=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 çaifsnak.snaktype~='value'thenreturnnilendlocaldatatype=snak.datatypelocalvalue=snak.datavalue.valuelocaldisplayformat=params.displayformatiftype(displayformat)=='function'thenreturndisplayformat(snak,params)endifdatatype=='wikibase-item'thenreturnwd.formatEntity(wd.getId(snak),params)endifdatatype=='url'thenifparams.displayformat=='raw'thenreturnvalueelsereturnmodules.weblink.makelink(value,params.text)endendifdatatype=='math'thenreturnmw.getCurrentFrame():extensionTag("math",value)endifdatatype=='tabular-data'thenreturnmw.ustring.sub(value,6,100)-- returns the name of the file, without the "Data:" prefixendif(datatype=='string')or(datatype=='external-id')or(datatype=='commonsMedia')then-- toutes les données de type string sauf "math"ifparams.urlpatternthenlocalurlpattern=params.urlpatterniftype(urlpattern)=='function'thenurlpattern=urlpattern(value)end-- encodage de l'identifiant qui se retrouve dans le path de l'URL, à l'exception des slashes parfois rencontrés, qui sont des séparateurs à ne pas encoderlocalencodedValue=mw.uri.encode(value,'PATH'):gsub('%%2F','/')-- les parenthèses autour du encodedValue:gsub() sont nécessaires, sinon sa 2e valeur de retour est aussi passée en argument au mw.ustring.gsub() parentlocalurl=mw.ustring.gsub(urlpattern,'$1',(encodedValue:gsub('%%','%%%%')))value='['..url..' '..(params.textorvalue)..']'endreturnvalueendifdatatype=='time'then-- format example: +00000001809-02-12T00:00:00Zifdisplayformat=='raw'thenreturnvalue.timeelselocaldateobject=modules.formatDate.dateObject(value,{precision=params.precision})returnmodules.formatDate.objectToText(dateobject,params)endendifdatatype=='globe-coordinate'then-- retourne une table avec clés latitude, longitude, précision et globe à formater par un autre module (à changer ?)ifdisplayformat=='latitude'thenreturnvalue.latitudeelseifdisplayformat=='longitude'thenreturnvalue.longitudeelselocalcoordvalue=mw.clone(value)coordvalue.globe=databases.globes[value.globe]-- transforme l'ID du globe en nom anglais utilisable par geohackreturncoordvalue-- note : les coordonnées Wikidata peuvent être utilisée depuis Module:Coordinates. Faut-il aussi autoriser à appeler Module:Coordiantes ici ?endendifdatatype=='quantity'then-- todo : gérer les paramètres précisionlocalamount,unit=value.amount,value.unitifunitthenunit=unit:match('Q%d+')endifnotunitthenunit='dimensionless'endlocalrawifdisplayformat=="raw"thenraw=trueendreturnmodules.formatNum.displayvalue(amount,unit,{targetunit=params.targetunit,raw=raw,rounding=params.rounding,showunit=params.showunitor'short',showlink=params.showlink})endifdatatype=='monolingualtext'thenifvalue.language==defaultlangthenreturnvalue.textelsereturnmodules.langmodule.langue({value.language,value.text,nocat=true})endendreturnformatError('unknown-datavalue-type')endfunctionwd.stringTable(args)-- like getClaims, but get a list of string rather than a list of snaks, for easier manipulationlocalclaims=args.claimslocalcat=''ifnotclaimsthenclaims=wd.getClaims(args)endifnotclaimsorclaims=={}thenreturn{},{},catendifargs.removedupesdateand(args.removedupesdate~='-')thenclaims,cat=removeDupesDate(claims,args.removedupesdate)endlocalprops={}-- liste des propriétés associété à chaque string pour catégorisation et linkbackfori,jinpairs(claims)doclaims[i]=wd.formatStatement(j,args)table.insert(props,j.mainsnak.property)endifargs.removedupesand(args.removedupes~='-')thenclaims=wd.addNewValues({},claims)-- devrait aussi supprimer de props celles qui ne sont pas utiliséesendreturnclaims,props,catendfunctionwd.getQualifiers(statement,qualifs,params)ifnotstatement.qualifiersthenreturnnilendlocalvals={}iftype(qualifs)=='string'thenqualifs=wd.splitStr(qualifs)endfori,jinpairs(qualifs)doifstatement.qualifiers[j]thenfork,linpairs(statement.qualifiers[j])dotable.insert(vals,l)endendendif#vals==0thenreturnnilendreturnvalsendfunctionwd.getFormattedQualifiers(statement,qualifs,params)ifnotparamsthenparams={}endlocalqualiftable=wd.getQualifiers(statement,qualifs)ifnotqualiftablethenreturnnilendqualiftable=wd.filterClaims(qualiftable,params)or{}fori,jinpairs(qualiftable)doqualiftable[i]=wd.formatSnak(j,params)endreturnmodules.linguistic.conj(qualiftable,params.conjtype)endfunctionwd.showQualifiers(str,statement,args)localqualifs=args.showqualifiersifnotqualifsthenreturnstr-- or error ?endiftype(qualifs)=='string'thenqualifs=wd.splitStr(qualifs)endlocalqualifargs=args.qualifargsor{}-- formatage des qualificatifs = args commençant par "qualif", ou à défaut, les mêmes que pour la valeur principalequalifargs.displayformat=args.qualifdisplayformatorargs.displayformatqualifargs.labelformat=args.qualiflabelformatorargs.labelformatqualifargs.labelformat2=args.qualiflabelformat2orargs.labelformat2qualifargs.link=args.qualiflinkorargs.linkqualifargs.linktopic=args.qualiflinktopicorargs.linktopicqualifargs.conjtype=args.qualifconjtypequalifargs.precision=args.qualifprecisionqualifargs.targetunit=args.qualiftargetunitqualifargs.defaultlink=args.qualifdefaultlinkorargs.defaultlinkqualifargs.defaultlinkquery=args.qualifdefaultlinkqueryorargs.defaultlinkquerylocalformattedqualifsifargs.qualifformatandtype(args.qualifformat)=='function'thenformattedqualifs=args.qualifformat(statement,qualifs,qualifargs)elseformattedqualifs=wd.getFormattedQualifiers(statement,qualifs,qualifargs)endifformattedqualifsandformattedqualifs~=""thenstr=str.." ("..formattedqualifs..")"endreturnstrendfunctionwd.formatSnak(snak,params)ifnotparamsthenparams={}end-- pour faciliter l'appel depuis d'autres modulesifsnak.snaktype=='somevalue'thenreturnunknownValue(snak,params.unknownlabel)elseifsnak.snaktype=='novalue'thenreturnnoValue(params.novaluelabel)elseifsnak.snaktype=='value'thenreturnwd.getDataValue(snak,params)elsereturnformatError('unknown-snak-type')endendfunctionwd.formatStatement(statement,args)-- FONCTION A REORGANISER (pas très lisible)ifnotargsthenargs={}endifnotstatement.typeorstatement.type~='statement'thenreturnformatError('unknown-claim-type')endlocalprop=statement.mainsnak.propertylocalstr-- special displayformat fifargs.statementformatand(type(args.statementformat)=='function')thenstr=args.statementformat(statement,args)elseif(statement.mainsnak.datatype=='time')and(statement.mainsnak.dateformat~='-')thenifargs.displayformat=='raw'andstatement.mainsnak.snaktype=='value'thenstr=statement.mainsnak.datavalue.value.timeelsestr=wd.getFormattedDate(statement,args)endelseifargs.showonlyqualifierand(args.showonlyqualifier~='')thenstr=wd.getFormattedQualifiers(statement,args.showonlyqualifier,args)ifnotstrthenreturnnilendifargs.addstandardqualifs~='-'thenstr=wd.addStandardQualifs(str,statement,true)endelsestr=wd.formatSnak(statement.mainsnak,args)if(args.addstandardqualifs~='-')and(args.displayformat~='raw')thenstr=wd.addStandardQualifs(str,statement)endend-- ajouts diversifargs.showlang==truethenlocalindicateur=showLang(statement)ifindicateurthenstr=indicateur..' '..strendendifargs.showqualifiersthenstr=wd.showQualifiers(str,statement,args)endifargs.showdatethen-- when "showdate and chronosort are both set, date retrieval is performed twicelocalperiod=wd.getFormattedDate(statement,args,"-")-- 3 arguments indicate the we should not use additional qualifiers, already added by wd.formatStatementifperiodthenstr=str.." <small>("..period..")</small>"endendifargs.showsourceandargs.showsource~='-'andargs.showsource~="false"thenifargs.showsource=="only"thenstr=""end-- si showsource="only", alors ne montrer que la (les) source(s), -- sans la valeur qui, auparavant, était enregistrée dans str-- Utilisé par le modèle {{PH census}}localsources,hashes=wd.getReferences(statement)ifsourcesthenlocalsource=wd.sourceStr(sources,hashes)ifsourcethenstr=str..sourceendendendreturnstrendfunctionwd.addLinkBack(str,id,property)ifnotidorid==''thenid=wd.getEntityIdForCurrentPage()endifnotidthenreturnstrendiftype(property)=='table'thenproperty=property[1]endid=mw.text.trim(wd.entityId(id))localclass=''ifpropertythenclass='wd_'..string.lower(property)endlocalicon='[[File:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]'localtitle=wd.translate('see-wikidata-value')localurl=mw.uri.fullUrl('d:'..id,'uselang=ht')url.fragment=property-- ajoute une #ancre si paramètre "property" définiurl=tostring(url)localv=mw.html.create('span'):addClass(class):wikitext(str):tag('span'):addClass('noprint wikidata-linkback skin-invert'):wikitext(icon:format(title,url)):allDone()returntostring(v)endfunctionwd.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"--]]returntostring(mw.html.create('span'):attr('id',id):attr('class',"ouvrage"):wikitext(str))end--=== FUNCTIONS USING AN ENTITY AS ARGUMENT ===localfunctionformatStatementsGrouped(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)localclaims=wd.getClaims(args)ifnotclaimsthenreturnnilendlocalgroupedClaims={}-- regroupe les affirmations par valeur de mainsnaklocalfunctionaddClaim(claim)localid=wd.getMainId(claim)fori,jinpairs(groupedClaims)doif(j.id==id)thentable.insert(groupedClaims[i].claims,claim)returnendendtable.insert(groupedClaims,{id=id,claims={claim}})endfori,claiminpairs(claims)doaddClaim(claim)endlocalstringTable={}-- instructions ad hoc pour les paramètres concernant la mise en forme d'une déclaration individuellelocalfuns={{param="showqualifiers",fun=function(str,claims)localqualifs={}fori,claiminpairs(claims)dolocalnews=wd.getFormattedQualifiers(claim,args.showqualifiers,args)ifnewsthentable.insert(qualifs,news)endendlocalqualifstr=modules.linguistic.conj(qualifs,wd.translate("qualif-separator"))ifqualifstrandqualifstr~=""thenstr=str.." ("..qualifstr..")"endreturnstrend},{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)"localdates={}fori,statementinpairs(claims)dolocals=wd.getFormattedDate(statement,args,true)ifstatementthentable.insert(dates,s)endendlocaldatestr=modules.linguistic.conj(dates)ifdatestranddatestr~=""thenstr=str.." <small>("..datestr..")</small>"endreturnstrend},{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 foislocalsources={}localhashes={}localfunctiondupeRef(old,new)fori,jinpairs(old)doifj==newthenreturntrueendendendfori,claiminpairs(claims)dolocalrefs,refHashes=wd.getReferences(claim)ifrefsthenfori,jinpairs(refs)doifnotdupeRef(sources,j)thentable.insert(sources,j)localhash=(refHashesandrefHashes[i])or'-'table.insert(hashes,hash)endendendendreturnstr..(wd.sourceStr(sources,hashes)or"")end}}fori,groupinpairs(groupedClaims)do-- bricolage pour utiliser les arguments de formatStatementslocalstr=wd.formatEntity(group.id,args)ifnotstrthenstr='???'-- pour éviter erreur Lua si formatEntity a retourné nilendfori,funinpairs(funs)doifargs[fun.param]thenstr=fun.fun(str,group.claims,args)endendtable.insert(stringTable,str)endargs.valuetable=stringTablereturnwd.formatStatements(args)endfunctionwd.formatStatements(args)--Format statement and concat them cleanlyifargs.value=='-'thenreturnnilend-- If a value is already set: use it, except if it's the special value {{WD}} (use wikidata)ifargs.valueandargs.value~=''thenlocalvalueexpl=wd.translate("activate-query")ifargs.value~=valueexplthenreturnargs.valueend-- There is no value set, and args.expl disables wikidata on empty valueselseifargs.explthenreturnnilendifargs.groupedandargs.grouped~=''thenargs.grouped=falsereturnformatStatementsGrouped(args)endlocalvaluetable=args.valuetable-- dans le cas où les valeurs sont déjà formatéeslocalprops-- les propriétés réellement utilisées (dans certains cas, ce ne sont pas toutes celles de args.propertylocalcat=''ifnotvaluetablethen-- cas le plus courantvaluetable,props,cat=wd.stringTable(args)endifargs.ucfirst=='-'andargs.conjtype=='new line'thenargs.conjtype='lowercase new line'endlocalstr=modules.linguistic.conj(valuetable,args.conjtype)ifnotstrthenreturnargs.defaultendifnotpropsthenprops=wd.splitStr(args.property)[1]endifargs.ucfirst~='-'thenstr=modules.linguistic.ucfirst(str)endifargs.addcatand(args.addcat~='-')thenstr=str..wd.addTrackingCat(props)..catendifargs.linkbackand(args.linkback~='-')thenstr=wd.addLinkBack(str,args.entity,props)endifargs.returnnumberofvaluesthenreturnstr,#valuetableendreturnstrendfunctionwd.formatAndCat(args)ifnotargsthenreturnnilendargs.linkback=args.linkbackortrueargs.addcat=trueifargs.valuethen-- do not ignore linkback and addcat, as formatStatements doifargs.value=='-'thenreturnnilendlocalval=args.value..wd.addTrackingCat(args.property)val=wd.addLinkBack(val,args.entity,args.property)returnvalendreturnwd.formatStatements(args)endfunctionwd.getTheDate(args)localclaims=wd.getClaims(args)ifnotclaimsthenreturnnilendlocalformattedvalues={}fori,jinpairs(claims)dolocalv=wd.getFormattedDate(j,args)ifvthentable.insert(formattedvalues,v)endendlocalval=modules.linguistic.conj(formattedvalues)ifnotvalthenreturnnilendifargs.addcat==truethenval=val..wd.addTrackingCat(args.property)endval=wd.addLinkBack(val,args.entity,args.property)returnvalendfunctionwd.keyDate(event,item,params)params=paramsor{}params.entity=itemiftype(event)=='table'thenfori,jinpairs(event)doparams.targetvalue=nil-- réinitialisation barbare des paramètres modifiéslocals=wd.keyDate(j,item,params)ifsthenreturnsendendelseiftype(event)~='string'thenreturnformatError('invalid-datatype',type(event),'string')elseifstring.sub(event,1,1)=='Q'then-- on demande un élément utilisé dans P:P793 (événement clé)params.property='P793'params.targetvalue=eventparams.addcat=params.addcatortruereturnwd.getTheDate(params)elseifstring.sub(event,1,1)=='P'then-- on demande une propriétéparams.property=eventreturnwd.formatAndCat(params)elsereturnformatError('invalid-entity-id',event)endendfunctionwd.mainDate(entity)-- essaye P580/P582localargs={entity=entity,addcat=true}args.property='P580'localstartpoint=wd.formatStatements(args)args.property='P582'localendpoint=wd.formatStatements(args)localstrif(startpointorendpoint)thenstr=modules.formatDate.daterange(startpoint,endpoint,params)str=wd.addLinkBack(str,entity,'P582')returnstrend-- défaut : P585args.property={'P585','P571'}args.linkback=truereturnwd.formatStatements(args)end-- ==== Fonctions sur le genre ====functionwd.getgender(id)localvals={['Q6581072']='f',-- féminin['Q6581097']='m',-- masculin['Q1052281']='f',-- femme transgenre['Q2449503']='m',-- homme transgenre['Q17148251']='f',-- en:Travesti (gender identity)['Q43445']='f',-- femelle['Q44148']='m',-- mâledefault='?'}localgender=wd.formatStatements{entity=id,property='P21',displayformat='raw',numval=1}returnvals[gender]orvals.defaultend-- catégories de genre/nombrefunctionwd.getgendernum(claims)localpersonid,genderlocalanym=falselocalanyf=falselocalanyunknown=falsefori,claiminpairs(claims)dolocalsnak=claim.mainsnakorclaimif(snak.snaktype=='value')and(snak.datatype=='wikibase-item')thenpersonid=wd.getId(snak)gender=wd.getgender(personid)anym=anymor(gender=='m')anyf=anyfor(gender=='f')anyunknown=anyunknownor(gender=='?')elseanyunknown=trueendendlocalgendernumif#claims>1thenifanyunknownthengendernum='p'elseifanymandnotanyfthengendernum='mp'endifanyfandnotanymthengendernum='fp'endifanymandanyfthengendernum='mixtep'endendelsegendernum='s'ifanymthengendernum='ms'endifanyfthengendernum='fs'endendreturngendernumend-- récupération des libellés genrés de Wikidatafunctionwd.genderedlabel(id,labelgender)locallabelifnotlabelgenderthenreturnnilendiflabelgender=='f'then-- femme : chercher le libellé dans P2521 (libellé féminin)label=wd.formatStatements{entity=id,property='P2521',isinlang='ht',numval=1,ucfirst='-'}elseiflabelgender=='m'then-- homme : chercher le libellé dans P3321 (libellé masculin)label=wd.formatStatements{entity=id,property='P3321',isinlang='ht',numval=1,ucfirst='-'}endifnotlabelthenlabel=wd.getLabel(id)endreturnlabelend-- === FUNCTIONS FOR TRANSITIVE PROPERTIES ===functionwd.getIds(item,query)query.excludespecial=truequery.displayformat='raw'query.entity=itemquery.addstandardqualifs='-'returnwd.stringTable(query)end-- recursively adds a list of qid to an existing list, based on the results of a queryfunctionwd.addVals(list,query,maxdepth,maxnodes,stopval)maxdepth=tonumber(maxdepth)or10maxnodes=tonumber(maxnodes)or100if(maxdepth<0)thenreturnlistendifstopvalandwd.isHere(list,stopval)thenreturnlistendlocalorigsize=#listfori=1,origsizedo-- tried a "checkpos" param instead of starting to 1 each time, but no impact on performancelocalcandidates=wd.getIds(list[i],query)list=wd.addNewValues(list,candidates,maxnodes,stopval)iflist[#list]==stopvalthenreturnlistendif#list>=maxnodesthenreturnlistendendif(#list==origsize)thenreturnlistendreturnwd.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)functionwd.transitiveVals(item,query,maxdepth,maxnodes,stopval)maxdepth=tonumber(maxdepth)or5iftype(query)=="string"thenquery={property=query}end-- récupération des valeurslocalvals=wd.getIds(item,query)ifnotvalsthenreturnnilendlocalv=wd.addVals(vals,query,maxdepth-1,maxnodes,stopval)ifnotvthenreturnnilend-- réarrangement des valeursifquery.valorder=="inverted"thenlocala={}fori=#v,1,-1doa[#a+1]=v[i]endv=aendreturnvend-- returns true if an item is the value of a query, transitivelyfunctionwd.inTransitiveVals(searchedval,sourceval,query,maxdepth,maxnodes)localvals=wd.transitiveVals(sourceval,query,maxdepth,maxnodes,searchedval)if(notvals)thenreturnfalseendfor_,valinipairs(vals)doif(val==searchedval)thenreturntrueendendreturnfalseend-- returns true if an item is a superclass of another, based on P279functionwd.isSubclass(class,item,maxdepth)localquery={property='P279'}ifclass==itemthen-- item is a subclass of itself iff it is a classifwd.getIds(item,query)thenreturntrueendreturnfalseendreturnwd.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 datefunctionwd.isInstance(targetclass,item,maxdepth)maxdepth=maxdepthor10localdirectclasses=wd.transitiveVals(item,{property='P31'},1)ifnotdirectclassesthenreturnfalseendfori,classinpairs(directclasses)doifwd.isSubclass(targetclass,class,maxdepth-1)thenreturntrueendendreturnfalseend-- 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 Canadafunctionwd.findVal(sourceitem,targetclass,query,recursion,instancedepth)iftype(query)=="string"thenquery={property=query}endlocalcandidates=wd.getIds(sourceitem,query)ifcandidatesthenfori,jinpairs(candidates)doifwd.isInstance(targetclass,j,instancedepth)thenreturnjendendifnotrecursionthenrecursion=3elserecursion=recursion-1endifrecursion<0thenreturnnilendfori,candidateinpairs(candidates)doreturnwd.findVal(candidate,targetclass,query,recursion,instancedepth)endendend-- === VARIA ===functionwd.getDescription(entity,lang)lang=langordefaultlanglocaldescriptioniflang==defaultlangthenreturnmw.wikibase.description(qid)endifnotentity.descriptionsthenreturnwd.translate('no description')endlocaldescriptions=entity.descriptionsifnotdescriptionsthenreturnnilendifdescriptions[lang]thenreturndescriptions[delang].valueendreturnentity.idendfunctionwd.Dump(entity)entity=wd.getEntity(entity)ifnotentitythenreturnformatError("entity-param-not-provided")endreturn"<pre>"..mw.dumpObject(entity).."</pre>"endfunctionwd.frameFun(frame)localargs=frame.argslocalfunname=args[1]table.remove(args,1)returnwd[funname](args)endreturnwd