| Jangan ubah modul ini dengan salin tempel dari en:Module:Wikidata. Modul ini digunakan untuk templat-templat infobox Wikidata. Selalu gunakan bak pasir untuk uji coba. |
| Versi lain modul Wikidata yang lebih baru (dari Wikipedia bahasa Inggris) : Module:WikidataIB atau Module:Wd, Versi lama (legacy) dari modul ini: Module:Wikidata/Legacy = en:Module:Wikidata (fungsi dipertahankan untuk templat-templat yang masih menggunakannya) |
| Modul Lua ini digunakan pada 162.000+ halaman. Untuk mencegah suntingan mengganggu skala besar dan beban peladen, setiap perubahan harus diuji di subhalaman /bak pasir atau /kasus uji Modul:Wikidata, atau bak pasir modul Anda. Perubahan yang telah diuji kemudian dapat ditambahkan ke halaman ini dalam satu suntingan. Pertimbangkan untuk mendiskusikan perubahan di halaman pembicaraan sebelum mengimplementasikannya. |
Dokumentasi di atas ditransklusikan dari Modul:Wikidata/doc. (sunting | riwayat)
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
-- version 20260211 from master @cawiki -- changes from previous version: -- new function sitelinks localp={} -- Initialization of variables -------------------- locali18n={-- internationalisation at subpage /i18n ["errors"]={ ["property-not-found"]="Property not found.", ["qualifier-not-found"]="Qualifier not found.", }, ["datetime"]={ -- $1 is a placeholder for the actual number ["beforenow"]="$1 BCE",-- how to format negative numbers for precisions 0 to 5 ["afternow"]="$1 CE",-- how to format positive numbers for precisions 0 to 5 ["bc"]="$1 BCE",-- how print negative years ["ad"]="$1",-- how print 1st century AD dates [0]="$1 billion years",-- precision: billion years [1]="$100 million years",-- precision: hundred million years [2]="$10 million years",-- precision: ten million years [3]="$1 million years",-- precision: million years [4]="$100000 years",-- precision: hundred thousand years; thousand separators added afterwards [5]="$10000 years",-- precision: ten thousand years; thousand separators added afterwards [6]="$1 millennium",-- precision: millennium [7]="$1 century",-- precision: century [8]="$1s",-- precision: decade -- the following use the format of #time parser function [9]="Y",-- precision: year, [10]="F Y",-- precision: month [11]="F j, Y",-- precision: day ["hms"]={["hours"]="h",["minutes"]="m",["seconds"]="s"},-- duration: xh xm xs }, ["years-old"]={"",""},-- year(s) old, as in magic word {PLURAL:$1|singular|plural} -- two values for most languages, up to six values for some languages, examples: -- ["years-old"] = {"singular", "paucal", "plural"} in Russian and other Slavic languages -- ["years-old"] = {"zero", "one", "two", "few 3-10", "many 11-99", "other 100-102"} in Arabic -- see documentation of PLURAL in your language at [[mw:Help:Magic words#Localization 2]] ["cite"]={-- cite parameters ["title"]="title", ["author"]="author", ["date"]="date", ["pages"]="pages", ["language"]="language", -- cite web parameters ["url"]="url", ["website"]="website", ["access-date"]="access-date", ["archive-url"]="archive-url", ["archive-date"]="archive-date", ["publisher"]="publisher", ["quote"]="quote", -- cite journal parameters ["work"]="work", ["issue"]="issue", ["issn"]="issn", ["doi"]="doi" }, -- default local wiki settings ["addpencil"]=false,-- adds a pencil icon linked to Wikidata statement, planned to overwrite by Wikidata Bridge ["categorylabels"]="",-- Category:Pages with Wikidata labels not translated (void for no local category) ["categoryprop"]="",-- Category:Pages using Wikidata property $1 (void for no local category) ["categoryref"]="",-- Category:Pages with references from Wikidata (void for no local category) ["addfallback"]={},-- additional fallback language codes ["suppressids"]={},-- list of Qid values to suppress ["qidlabels"]=true-- show labels as Qid if no fallback translation is available } localcases={}-- functions for local grammatical cases defined at subpage /i18n localrequired=...-- variadic arguments from require function localwiki= { langcode=mw.language.getContentLanguage().code, module_title=requiredormw.getCurrentFrame():getTitle() } localuntranslated-- used in infobox modules: nil or true local_-- variable for unused returned values, avoiding globals -- Module local functions -------------------------------------------- -- Credit to http://stackoverflow.com/a/1283608/2644759, cc-by-sa 3.0 localfunctiontableMerge(t1,t2) fork,vinpairs(t2)do iftype(v)=="table"then iftype(t1[k]orfalse)=="table"then tableMerge(t1[k]or{},t2[k]or{}) else t1[k]=v end else t1[k]=v end end returnt1 end localfunctionloadI18n(lang) localexist,res=pcall(require,wiki.module_title.."/i18n") ifexistandnext(res)~=nilthen tableMerge(i18n,res.i18n) cases=res.cases end iflang~=wiki.langcodethen exist,res=pcall(require,wiki.module_title.."/i18n/"..lang) ifexistandnext(res)~=nilthen tableMerge(i18n,res.i18n) tableMerge(cases,res.cases) end end i18n.suppress={} for_,idinipairs(i18n.suppressids)do i18n.suppress[id]=true end end -- Table of language codes: requested or default and its fallbacks localfunctionfindLang(langcode) ifmw.language.isKnownLanguageTag(langcodeor'')==falsethen localcframe=mw.getCurrentFrame() localpframe=cframe:getParent() langcode=pframeandpframe.args.lang ifmw.language.isKnownLanguageTag(langcodeor'')==falsethen ifnotmw.title.getCurrentTitle().isContentPagethen langcode=cframe:callParserFunction('int',{'lang'}) end ifmw.language.isKnownLanguageTag(langcodeor'')==falsethen langcode=wiki.langcode end end end loadI18n(langcode) locallanguages=mw.language.getFallbacksFor(langcode) table.insert(languages,1,langcode) table.insert(languages,2,"mul")-- see [[d:Help:Default values for labels and aliases]] iflangcode==wiki.langcodethen for_,linipairs(i18n.addfallback)do table.insert(languages,l) end end returnlanguages end -- Argument is 'set' when it exists (not nil) or when it is not an empty string. localfunctionisSet(var) returnnot(var==nilor(type(var)=='string'andmw.text.trim(var)=='')) end -- Set local case to a label localfunctioncase(localcase,label,...) ifnotisSet(label)thenreturnlabelend iftype(localcase)=="function"then returnlocalcase(label) elseiflocalcase=="smallcaps"then return'<span style="font-variant: small-caps;">'..label..'</span>' elseifcases[localcase]then returncases[localcase](label,...) end returnlabel end -- get safely a serialized snak localfunctiongetSnak(statement,snaks) localret=statement fori,vinipairs(snaks)do ifnotretthenreturnend ret=ret[v] end returnret end -- get label with an array of fallback languages -- mw.wikibase.getLabelWithLang uses lang mul as last fallback, not the first one localfunctiongetLabelByLangs(id,languages) locallabel,lang for_,linipairs(languages)do label=mw.wikibase.getLabelByLang(id,l) iflabelthen lang=(l=="mul"andlanguages[1]orl) break end end returnlabel,lang end -- getBestStatements if bestrank=true, else getAllStatements with no deprecated localfunctiongetStatements(entityId,property,bestrank) localclaims={} ifnot(entityIdandmw.ustring.match(property,"^P%d+$"))thenreturnclaimsend ifbestrankthen claims=mw.wikibase.getBestStatements(entityId,property) else localallclaims=mw.wikibase.getAllStatements(entityId,property) for_,cinipairs(allclaims)do ifc.rank~="deprecated"then table.insert(claims,c) end end end returnclaims end -- Is gender femenine? true or false localfunctionfeminineGender(id) foridninstring.gmatch(id,"Q%d+")do localclaims=mw.wikibase.getBestStatements(idnormw.wikibase.getEntityIdForCurrentPage(),'P21') localgender_id=getSnak(claims,{1,"mainsnak","datavalue","value","id"}) ifgender_id==nilornot(gender_id=="Q6581072"orgender_id=="Q1052281"orgender_id=="Q43445")then -- not female, transgender female or female organism returnfalse end end returntrue end -- Fetch female form of label localfunctionfeminineForm(id,lang) localfeminine_claims=getStatements(id,'P2521') for_,feminine_claiminipairs(feminine_claims)do ifgetSnak(feminine_claim,{'mainsnak','datavalue','value','language'})==langthen returnfeminine_claim.mainsnak.datavalue.value.text end end end -- Add an icon for no label in requested language localfunctionaddLabelIcon(label_id,lang,uselang,icon) localret_lang,ret_icon='','' ificonthen iflangandlang~=uselangthen ret_lang=" <sup>("..lang..")</sup>" end iflabel_idand(lang==nilorlang~=uselang)then localnamespace='' ifstring.sub(label_id,1,1)=='P'then namespace='Property:' end ret_icon=" [[File:OOjs_UI_icon_tag-rtl-progressive.svg|10px|baseline|class=skin-invert|" ..mw.message.new('Translate-taction-translate'):inLanguage(uselang):plain() .."|link=https://www.wikidata.org/wiki/"..namespace..label_id.."?uselang="..uselang.."]]" untranslated=true end ifisSet(i18n.categorylabels)andlang~=uselanganduselang==wiki.langcodethen ret_icon=ret_icon..'[['..i18n.categorylabels..(langand']]'or'/Q]]') end end returnret_lang..ret_icon end -- editicon values: true/false (no=false), right, void defaults to i18n.addpencil -- labelicon only by parameter localfunctionsetIcons(arg,parg) localval=arg==nilandpargorarg localedit_icon,label_icon ifnotisSet(val)then edit_icon,label_icon=i18n.addpencil,true elseifval==falseorval=="false"orval=="no"then edit_icon,label_icon=false,false else edit_icon,label_icon=val,true end returnedit_icon,label_icon end -- Add an icon for editing a statement with requirements for future Wikidata Bridge localfunctionaddEditIcon(parameters) localret='' ifparameters.editiconandparameters.idandparameters.propertythen localbridge_flow=parameters.editbridgeand' data-bridge-edit-flow="single-best-value"'or'' localicon_style=parameters.editicon=="right"and' style="float: right;"'or'' ret=' <span class="penicon"'..bridge_flow..icon_style..'>' .."[[File:OOjs UI icon edit-ltr-progressive.svg|10px|baseline|" ..string.gsub(mw.message.new('Wikibase-client-data-bridge-bailout-suggestion-go-to-repo-button'):inLanguage(parameters.lang[1]):plain(),'{{WBREPONAME}}','Wikidata') .."|link=https://www.wikidata.org/wiki/"..parameters.id.."?uselang="..parameters.lang[1].."#"..parameters.property.."]]" .."</span>" ifisSet(i18n.categoryprop)then ret=ret.."[["..string.gsub(i18n.categoryprop,'$1',parameters.property).."]]" end end returnret end -- add edit icon to the last element of a table localfunctionaddEditIconTable(thetable,parameters) if#thetable==0orparameters.editicon==falsethen returnthetable end locallast_element=thetable[#thetable] localthe_icon=addEditIcon(parameters) -- add it before last html closing tags localtags='' localrev_element=string.reverse(last_element) fortaginstring.gmatch(rev_element,'(>%l+/<)')do ifstring.match(rev_element,'^'..tags..tag)then tags=tags..tag else break end end locallast_tags=string.reverse(tags) localoffset=string.find(last_element,last_tags..'$') ifoffsetthen thetable[#thetable]=string.sub(last_element,1,offset-1)..the_icon..last_tags else thetable[#thetable]=last_element..the_icon end returnthetable end -- Escape Lua captures localfunctioncaptureEscapes(text) returnmw.ustring.gsub(text,"(%%%d)","%%%1") end -- expandTemplate or callParserFunction localfunctionexpandBraces(text,formatting) iftext==nilorformatting==nilthenreturntextend -- only expand braces if provided in argument, not included in value as in Q1164668 ifmw.ustring.find(formatting,'{{',1,true)==nilthenreturntextend iftype(text)~="string"then text=tostring(text) end forbracesinmw.ustring.gmatch(text,"{{(.-)}}")do localparts=mw.text.split(braces,"|") localtitle_part=parts[1] localparameters={} fori=2,#partsdo localsubparts=mw.ustring.find(parts[i],"=") ifsubpartsthen localparam_name=mw.ustring.sub(parts[i],1,subparts-1) localparam_value=mw.ustring.sub(parts[i],subparts+1,-1) -- reconstruct broken links by parts ifi<#partsandmw.ustring.find(param_value,"[[",1,true)andnotmw.ustring.find(param_value,"]]",1,true)then parameters[param_name]=param_value localpart_next=i+1 whileparts[part_next]andmw.ustring.find(parts[part_next],"]]",1,true)do parameters[param_name]=parameters[param_name].."|"..parts[part_next] part_next=part_next+1 end else parameters[param_name]=param_value end elseifnotmw.ustring.find(parts[i],"]]",1,true)then table.insert(parameters,parts[i]) end end localbraces_expanded ifmw.ustring.find(title_part,":") andmw.text.split(title_part,":")[1]~=mw.site.namespaces[10].name-- not a prefix Template: then braces_expanded=mw.getCurrentFrame():callParserFunction{name=title_part,args=parameters} elseiftitle_part=="!"then -- template:! may be deleted locally, now provided by MediaWiki -- although it works, it raises a Lua internal error braces_expanded="|" else braces_expanded=mw.getCurrentFrame():expandTemplate{title=title_part,args=parameters} end braces=mw.ustring.gsub(braces,"([%^%$%(%)%%%.%[%]%*%+%-%?])","%%%1")-- escape magic characters braces_expanded=captureEscapes(braces_expanded) text=mw.ustring.gsub(text,"{{"..braces.."}}",braces_expanded) end returntext end -- format data type math localfunctionprintDatatypeMath(data) returnmw.getCurrentFrame():callParserFunction('#tag:math',data) end -- format data type musical-notation localfunctionprintDatatypeMusical(data,formatting) localattr={} ifformatting=='sound'then attr.sound=1 end returnmw.getCurrentFrame():extensionTag('score',data,attr) end -- format data type string localfunctionprintDatatypeString(data,parameters) ifmw.ustring.find((parameters.formattingor''),'$1',1,true)then-- formatting = a pattern returnexpandBraces(mw.ustring.gsub(parameters.formatting,'$1',{['$1']=data}),parameters.formatting) elseifparameters.casethen returncase(parameters.case,data,parameters.lang[1],feminineGender(parameters.id)) end localdata_number=string.match(data,"^%d+") ifdata_numberthen-- sort key by initial number and remaining string localsortkey=string.format("%019d",data_number*1000) returndata,sortkey..string.sub(data,#data_number+1) end returndata end -- format data type tabular-data localfunctionprintDatatypeTabular(data,parameters) localicon ifparameters.formatting=='raw'then icon="no-icon" data=string.gsub(data,'^Data:','')-- remove prefix, i.e. see Module:Tabular data end returnprintDatatypeString(data,parameters),icon end -- format data type url localfunctionprintDatatypeUrl(data,parameters) ifparameters.formatting=='weblink'then locallabel_parts=mw.text.split(string.gsub(data,'/$',''),'/') locallabel=string.gsub(label_parts[3],'^www%.','') if#label_parts>3then label=label..'…' end return'['..data..' '..label..']' end returnprintDatatypeString(data,parameters) end -- format data type external-id localfunctionprintDatatypeExternal(data,parameters) ifparameters.formatting=='externalid'then localp_stat=mw.wikibase.getBestStatements(parameters.property,'P1630')-- formatter URL localp_link_pattern=getSnak(p_stat,{1,"mainsnak","datavalue","value"}) ifp_link_patternthen localp_link=mw.ustring.gsub(p_link_pattern,'$1',{['$1']=data}) return'['..p_link..' '..data..']' end end returnprintDatatypeString(data,parameters) end -- format data type commonsMedia and geo-shape localfunctionprintDatatypeMedia(data,parameters) localicon ifnotstring.find((parameters.formattingor''),'$1',1,true)then icon="no-icon" ifnotstring.find(data,'^Data:')then data=mw.uri.encode(data,'PATH')-- encode special characters in filename end end returnprintDatatypeString(data,parameters),icon end -- format data type globe-coordinate localfunctionprintDatatypeCoordinate(data,formatting) localfunctionglobes(globe_id) -- parameter globe in coordinates accepted by GeoHack -- see [[w:en:Special:PrefixIndex/Template:GeoTemplate]] localglobes={['Q3343']='ariel',['Q3134']='callisto',['Q596']='ceres', ['Q6604']='charon',['Q7548']='deimos',['Q15040']='dione',['Q2']='earth', ['Q3303']='enceladus',['Q3143']='europa',['Q3169']='ganymede', ['Q15037']='hyperion',['Q17958']='iapetus',['Q3123']='io', ['Q319']='jupiter',['Q111']='mars',['Q308']='mercury',['Q15034']='mimas', ['Q3352']='miranda',['Q405']='moon',['Q3332']='oberon',['Q7547']='phobos', ['Q17975']='phoebe',['Q339']='pluto',['Q15050']='rhea',['Q15047']='tethys', ['Q2565']='titan',['Q3322']='titania',['Q3359']='triton', ['Q3338']='umbriel',['Q313']='venus',['Q3030']='vesta'} returnglobes[globe_id] end localfunctionroundPrecision(num,prec) ifprec==nilorprec<=0thenreturnnumend localsig=10^math.floor(math.log10(prec)+.5)-- significant figure from sexagesimal precision: 0.00123 -> 0.001 returnmath.floor(num/sig+0.5)*sig end localprecision=data.precision locallatitude=roundPrecision(data.latitude,precision) locallongitude=roundPrecision(data.longitude,precision) ifformattingandstring.find(formatting,'$lat',1,true)andstring.find(formatting,'$lon',1,true)then localret=mw.ustring.gsub(formatting,'$l[ao][tn]',{['$lat']=latitude,['$lon']=longitude}) ifstring.find(formatting,'$globe',1,true)then localmyglobe='earth' ifisSet(data.globe)then localglobenum=mw.text.split(data.globe,'entity/')[2]-- http://www.wikidata.org/wiki/Q2 myglobe=globes(globenum)or'earth' end ret=mw.ustring.gsub(ret,'$globe',myglobe) end returnexpandBraces(ret,formatting) elseifformatting=='latitude'then returnlatitude,"no-icon" elseifformatting=='longitude'then returnlongitude,"no-icon" elseifformatting=='dimension'then returndata.dimension,"no-icon" else--default formatting='globe' ifisSet(data.globe)==falseordata.globe=='http://www.wikidata.org/entity/Q2'then return'earth',"no-icon" else localglobenum=mw.text.split(data.globe,'entity/')[2] returnglobes(globenum)orglobenum,"no-icon" end end end -- Local functions for data value quantity localfunctionunitSymbol(id,lang)-- get unit symbol or code localunit_symbol='' iflang==wiki.langcodeandpcall(require,wiki.module_title.."/Units")then unit_symbol=require(wiki.module_title.."/Units").getUnit(0,'',id,true) end ifunit_symbol==''then -- fetch it localclaims=mw.wikibase.getBestStatements(id,'P5061') if#claims>0then locallangclaims={} for_,snakinipairs(claims)do localsnak_language=getSnak(snak,{"mainsnak","datavalue","value","language"}) ifsnak_languageandnotlangclaims[snak_language]then-- just the first one by language langclaims[snak_language]=snak.mainsnak.datavalue.value.text end end for_,linipairs(lang)do iflangclaims[l]then returnlangclaims[l] end end end end returnunit_symbol end localfunctiongetUnit(amount,id,parameters)-- get unit symbol or name localsuffix='' ifstring.sub(parameters.formattingor'',1,8)=="unitcode"then -- get unit symbol localunit_symbol=unitSymbol(id,parameters.lang) ifisSet(unit_symbol)then ifstring.sub(parameters.formattingor'',-6)=="linked"then suffix="[["..(mw.wikibase.getSitelink(id)or"d:"..id).."|"..unit_symbol.."]]" else suffix=unit_symbol end end end ifsuffix==''then-- formatting=unit, or formatting=unitcode not found -- get unit label localunit_label,lang=getLabelByLangs(id,parameters.lang) iflang==wiki.langcodeandpcall(require,wiki.module_title.."/Units")then suffix=require(wiki.module_title.."/Units").getUnit(amount,unit_label,id,false) ifstring.sub(parameters.formattingor'',-6)=="linked"then suffix="[["..(mw.wikibase.getSitelink(id)or"d:"..id).."|"..suffix.."]]" end else suffix=(unit_labelorid)..addLabelIcon(id,lang,parameters.lang[1],parameters.labelicon) end end ifsuffix~=''then suffix=' '..suffix end returnsuffix end localfunctionroundDefPrecision(in_num,factor) -- rounds out_num with significant figures of in_num (default precision) localout_num=in_num*factor iffactor/60==math.floor(factor/60)orout_num==0then-- sexagesimal integer or avoiding NaN returnout_num end -- first, count digits after decimal mark, handling cases like '12.345e6' localexponent,prec localinteger,dot,decimals,expstr=in_num:match('^(%d*)(%.?)(%d*)(.*)') locale=expstr:sub(1,1) ife=='e'ore=='E'then exponent=tonumber(expstr:sub(2)) end ifdot==''then prec=-integer:match('0*$'):len() else prec=#decimals end ifexponentthen -- So '1230' and '1.23e3' both give prec = -1, and '0.00123' and '1.23e-3' give 5. prec=prec-exponent end -- significant figures localin_bracket=10^-prec-- -1 -> 10, 5 -> 0.00001 localout_bracket=in_bracket*out_num/in_num out_bracket=10^math.floor(math.log10(out_bracket)+.5)-- 1230 -> 1000, 0.00123 -> 0.001 -- round it (credit to Luc Bloom from http://lua-users.org/wiki/SimpleRound) returnmath.floor(out_num/out_bracket+(out_num>=0and1or-1)*0.5)*out_bracket end -- format data type quantity localfunctionprintDatatypeQuantity(data,parameters) localamount=data.amount amount=mw.ustring.gsub(amount,"%+","") localsuffix="" localconv_amount,conv_suffix ifstring.sub(parameters.formattingor'',1,4)=="unit"orstring.sub(parameters.formattingor'',1,8)=="duration"orparameters.convertthen localunit_id=data.unit unit_id=mw.ustring.sub(unit_id,mw.ustring.find(unit_id,"Q"),-1) ifstring.sub(unit_id,1,1)=="Q"then suffix=getUnit(amount,unit_id,parameters) localconvert_to ifparameters.convert=="default"orparameters.convert=="default2"then localexist,units=pcall(require,wiki.module_title.."/Units") ifexistandunits.convert_defaultandnext(units.convert_default)~=nilthen convert_to=units.convert_default[unit_id] end elseifstring.sub(parameters.convertor'',1,1)=="Q"then convert_to=parameters.convert elseifstring.sub(parameters.formattingor'',1,8)=="duration"then convert_to='Q11574'-- seconds end ifconvert_toandconvert_to~=unit_idthen -- convert units localconv_temp={-- formulae for temperatures ºC, ºF, ªK: [from] = {[to] = 'formula'} ['Q25267']={['Q42289']='$1*1.8+32',['Q11597']='$1+273.15'}, ['Q42289']={['Q25267']='($1-32)/1.8',['Q11597']='($1+459.67)*5/9'}, ['Q11597']={['Q25267']='$1-273.15',['Q42289']='($1-273.15)*1.8000+32.00'} } ifconv_temp[unit_id]andconv_temp[unit_id][convert_to]then localamount_f=mw.getCurrentFrame():callParserFunction('#expr',mw.ustring.gsub(conv_temp[unit_id][convert_to],"$1",amount)) conv_amount=math.floor(tonumber(amount_f)+0.5) else localconversions=getStatements(unit_id,'P2442')-- conversion to standard unit table.insert(conversions,mw.wikibase.getBestStatements(unit_id,'P2370')[1])-- conversion to SI unit for_,convinipairs(conversions)do ifconv.mainsnak.snaktype=='value'then-- no somevalue nor novalue ifconv.mainsnak.datavalue.value.unit=="http://www.wikidata.org/entity/"..convert_tothen conv_amount=roundDefPrecision(amount,tonumber(conv.mainsnak.datavalue.value.amount)) break end end end end ifconv_amountthen conv_suffix=getUnit(conv_amount,convert_to,parameters) end elseifparameters.convert=='M'then localexist,units=pcall(require,wiki.module_title.."/Units") ifwiki.langcode==parameters.lang[1] andexistandunits.convert2Mandtype(units.convert2M)=="function" then conv_amount,conv_suffix=units.convert2M(amount) conv_suffix=(conv_suffixor"")..suffix elseiftonumber(amount)>10^8then conv_amount=math.floor(amount/10^6+0.5) conv_suffix=' M'..mw.text.trim(suffix) end end ifconv_amountandparameters.formatting=='raw'then amount=conv_amount suffix="" conv_amount=nil end end end locallang_obj=mw.language.new(parameters.lang[1]) localsortkey=string.format("%019d",tonumber(amount)*1000) ifstring.sub(parameters.formattingor'',1,8)=="duration"then localsec=tonumber(conv_amountoramount) ifparameters.formatting=='duration'then returnlang_obj:formatDuration(sec) elseifparameters.formatting=='durationm:s'then localmm=math.floor(sec/60) localss=sec-(mm*60) returnstring.format("%02d:%02d",mm,ss) else-- durationhms or durationh:m:s localintervals={"hours","minutes","seconds"} localsec2table=lang_obj:getDurationIntervals(sec,intervals) sec2table["seconds"]=(sec2table["seconds"]or0)+tonumber("."..(tostring(sec):match("%.(%d+)")or"0"))-- add decimals localduration='' fori,vinipairs(intervals)do ifparameters.formatting=='durationh:m:s'then ifi==1andsec2table[v]then duration=duration..sec2table[v]..":" elseifi==2then duration=duration..string.format("%02d",sec2table[v]or0)..":" elseifi==3then localsec_str=tostring(lang_obj:formatNum(sec2table[v]or0)) duration=duration..(sec2table[v]<10and"0"or"")..sec_str end elseifsec2table[v]then duration=duration..lang_obj:formatNum(sec2table[v])..i18n.datetime.hms[v]..(i<3and" "or"") end end returnduration end end ifparameters.casethen amount=case(parameters.case,amount,parameters.lang[1],feminineGender(parameters.id)) elseifparameters.formatting~='raw'then ifparameters.numformatthen amount=lang_obj:formatNum(tonumber(string.format(parameters.numformat,amount))) else amount=lang_obj:formatNum(tonumber(amount)) end end ifconv_amountthen localconv_sortkey=string.format("%019d",conv_amount*1000) conv_amount=lang_obj:formatNum(conv_amount) ifparameters.convert=='default2'then returnconv_amount..conv_suffix..' ('..amount..suffix..')',conv_sortkey else returnconv_amount..conv_suffix,conv_sortkey end elseifmw.ustring.find((parameters.formattingor''),'$1',1,true)then-- formatting with pattern amount=mw.ustring.gsub(parameters.formatting,'$1',{['$1']=amount}) end returnamount..suffix,sortkey end -- format data type time localfunctionprintDatatypeTime(data,parameters) -- Dates and times are stored in ISO 8601 format localtimestamp=data.time ifparameters.formatting=="raw"then returntimestamp,timestamp end localpost_format localcalendar_add="" localprecision=data.precisionor11 ifstring.sub(timestamp,1,1)=='-'then post_format=i18n.datetime["bc"] elseifstring.sub(timestamp,2,3)=='00'then post_format=i18n.datetime["ad"] elseifprecision>8then -- calendar model localcalendar_model={["Q12138"]="gregorian",["Q1985727"]="gregorian",["Q11184"]="julian",["Q1985786"]="julian"} localcalendar_id=mw.text.split(data.calendarmodel,'entity/')[2] if(timestamp<"+1582-10-15T00:00:00Z"andcalendar_model[calendar_id]=="gregorian") or(timestamp>"+1582-10-04T00:00:00Z"andcalendar_model[calendar_id]=="julian") then calendar_add=" <sup>("..mw.message.new('Wikibase-time-calendar-'..calendar_model[calendar_id]):inLanguage(parameters.lang[1]):plain()..")</sup>" end end localfunctionformatTime(form,stamp) localpattern iftype(form)=="function"then pattern=form(stamp) else pattern=form end stamp=tostring(stamp) ifmw.ustring.find(pattern,"$1")then returnmw.ustring.gsub(pattern,"$1",stamp) elseifstring.sub(stamp,1,1)=='-'then-- formatDate() only supports years from 0 stamp='+'..string.sub(stamp,2) elseifstring.sub(stamp,1,1)~='+'then-- not a valid timestamp, it is a number stamp=string.format("%04d",stamp) end localret=mw.language.new(parameters.lang[1]):formatDate(pattern,stamp) ret=string.gsub(ret,"^(%[?%[?)0+","%1")-- suppress leading zeros ret=string.gsub(ret,"( %[?%[?)0+","%1") returnret end localfunctionpostFormat(t) ifpost_formatandmw.ustring.find(post_format,"$1")then returnmw.ustring.gsub(post_format,"$1",t) end returnt end localintyear=tonumber(string.match(timestamp,"[+-](%d+)")) localret="" ifprecision<=5then-- precision is 10000 years or more localfactor=10^((5-precision)+4) localy2=math.ceil(math.abs(intyear)/factor) localrelative=formatTime(i18n.datetime[precision],y2) ifpost_format==i18n.datetime["bc"]then ret=mw.ustring.gsub(i18n.datetime.beforenow,"$1",relative) else ret=mw.ustring.gsub(i18n.datetime.afternow,"$1",relative) end localret_number=string.match(ret,"%d+") ifret_number~=nilthen ret=mw.ustring.gsub(ret,ret_number,mw.language.new(parameters.lang[1]):formatNum(tonumber(ret_number))) end elseifprecision==6orprecision==7then-- millennia or centuries localcard=math.floor((intyear-1)/10^(9-precision))+1 ret=formatTime(i18n.datetime[precision],card) ret=postFormat(ret) elseifprecision==8then-- decades localcard=math.floor(math.abs(intyear)/10)*10 ret=formatTime(i18n.datetime[8],card) ret=postFormat(ret) elseifintyear>9999then-- not a valid timestamp return elseifprecision==9orparameters.formatting=='Y'then-- precision is year ret=formatTime(i18n.datetime[9],intyear) ret=postFormat(ret)..calendar_add elseifprecision==10then-- month ret=formatTime(i18n.datetime[10],timestamp.." + 1 day")-- formatDate yyyy-mm-00 returns the previous month ret=postFormat(ret)..calendar_add else-- precision 11, day ret=formatTime(parameters.formattingori18n.datetime[11],timestamp) ret=postFormat(ret)..calendar_add end returnret,timestamp end -- format data value wikibase-entityid with data types wikibase-item or wikibase-property localfunctionprintDatatypeEntity(data,parameters) localentity_id=data['id'] ifparameters.formatting=='raw'then returnentity_id,entity_id end localentity_page='Special:EntityPage/'..entity_id locallabel,lang=getLabelByLangs(entity_id,parameters.lang) localsitelink=mw.wikibase.getSitelink(entity_id) localparameter=parameters.formatting locallabelcase=labelorsitelink ifparameters.gender=='feminineform'then labelcase=feminineForm(entity_id,lang)orlabelcase end ifparameters.case~='gender'then labelcase=case(parameters.case,labelcase,lang,parameters.lang[1],entity_id,parameters.id) end iflabelcase==nilandi18n.qidlabels==falsethen return end localret1,ret2 ifparameter=='label'then ret1=labelcaseorentity_id ret2=labelcaseorentity_id elseifparameter=='sitelink'then ret1=(sitelinkor'd:'..entity_page) ret2=sitelinkorentity_id elseifmw.ustring.find((parameteror''),'$1',1,true)then-- formatting = a pattern ret1=mw.ustring.gsub(parameter,'$1',labelcaseorentity_id) ret1=expandBraces(ret1,parameter) ret2=labelcaseorentity_id else ifparameter=="ucfirst"orparameter=="ucinternallink"then iflabelcaseandlangthen labelcase=mw.language.new(lang):ucfirst(labelcase) end -- only first of a list, reset formatting for next ones ifparameter=="ucinterlanllink"then parameters.formatting='internallink' else parameters.formatting=nil-- default format end end ifsitelinkthen ret1='[['..sitelink..'|'..labelcase..']]' ret2=labelcase elseiflabelandstring.match(parameteror'','internallink$')andnotmw.wikibase.getEntityIdForTitle(label)then ret1='[['..label..'|'..labelcase..']]' ret2=labelcase else ret1='[[d:'..entity_page..'|'..(labelcaseorentity_id)..']]' ret2=labelcaseorentity_id end end returnret1..addLabelIcon(entity_id,lang,parameters.lang[1],parameters.labelicon),ret2 end -- format data type wikibase-lexeme localfunctionprintDatatypeLexeme(data,parameters) localentity_id=data['id'] ifparameters.formatting=='raw'then returnentity_id,entity_id end locallemmas=mw.wikibase.getEntity(entity_id):getLemmas() ifparameters.list=='lang'andlemmas[1][2]~=parameters.lang[1]then return end localret='[[d:Special:EntityPage/'..entity_id..'|'..lemmas[1][1]..']]' ifparameters.list~='lang'or(parameters.list=='lang'andlemmas[1][2]~=wiki.langcode)then ret=ret.." <sup>("..lemmas[1][2]..")</sup>" end returnret,entity_id end -- format data type monolingualtext localfunctionprintDatatypeMonolingual(data,parameters) -- data fields: language [string], text [string] localvalid_lang={[parameters.lang[1]]=true,["mul"]=true} ifparameters.list=="lang"andnotvalid_lang[data["language"]]then return elseifparameters.list=="notlang"andvalid_lang[data["language"]]then return elseifparameters.formatting=="language"orparameters.formatting=="text"then returndata[parameters.formatting] end localresult=data["text"] valid_lang={[wiki.langcode]=true,["mul"]=true} ifnotvalid_lang[data["language"]]then result=mw.ustring.gsub('<span lang="$1">$2</span>','$[12]',{["$1"]=data["language"],["$2"]=data["text"]}) end ifmw.ustring.find((parameters.formattingor''),'$',1,true)then -- output format defined with $text, $language result=mw.ustring.gsub(parameters.formatting,'$text',result) result=mw.ustring.gsub(result,'$language',data["language"]) end returnresult end localfunctiongetSnakValue(snak,parameters) parameters.editbridge=false ifsnak.snaktype=='value'then-- see Special:ListDatatypes -- data value string ifsnak.datatype=="string"then parameters.editbridge=true-- Wikidata Bridge currently only for string values returnprintDatatypeString(snak.datavalue.value,parameters) elseifsnak.datatype=="commonsMedia"orsnak.datatype=="geo-shape"then returnprintDatatypeMedia(snak.datavalue.value,parameters) elseifsnak.datatype=="tabular-data"then returnprintDatatypeTabular(snak.datavalue.value,parameters) elseifsnak.datatype=="url"then returnprintDatatypeUrl(snak.datavalue.value,parameters) elseifsnak.datatype=="external-id"then returnprintDatatypeExternal(snak.datavalue.value,parameters) elseifsnak.datatype=='math'then returnprintDatatypeMath(snak.datavalue.value) elseifsnak.datatype=='musical-notation'then returnprintDatatypeMusical(snak.datavalue.value,parameters.formatting) -- data types other than string value elseifsnak.datatype=='wikibase-item'orsnak.datatype=='wikibase-property'then ifi18n.suppress[snak.datavalue.value.id]then return end returnprintDatatypeEntity(snak.datavalue.value,parameters) elseifsnak.datatype=='wikibase-lexeme'then returnprintDatatypeLexeme(snak.datavalue.value,parameters) elseifsnak.datatype=='monolingualtext'then returnprintDatatypeMonolingual(snak.datavalue.value,parameters) elseifsnak.datatype=="globe-coordinate"then returnprintDatatypeCoordinate(snak.datavalue.value,parameters.formatting) elseifsnak.datatype=="quantity"then returnprintDatatypeQuantity(snak.datavalue.value,parameters) elseifsnak.datatype=="time"then returnprintDatatypeTime(snak.datavalue.value,parameters) end elseifsnak.snaktype=='novalue'then ifparameters.formatting=='raw'orparameters.shownovalue==falsethenreturnend returnmw.message.new('Wikibase-snakview-snaktypeselector-novalue'):inLanguage(parameters.lang[1]):plain() elseifsnak.snaktype=='somevalue'then ifparameters.formatting=='raw'orparameters.showsomevalue==falsethenreturnend returnmw.message.new('Wikibase-snakview-snaktypeselector-somevalue'):inLanguage(parameters.lang[1]):plain() end returnmw.wikibase.renderSnak(snak) end localfunctionprintError(key) return'<span class="error">'..i18n.errors[key]..'</span>' end localfunctiongetQualifierSnak(claim,qualifierId,parameters) -- a "snak" is Wikidata terminology for a typed key/value pair -- a claim consists of a main snak holding the main information of this claim, -- as well as a list of attribute snaks and a list of references snaks ifqualifierIdthen -- search the attribute snak with the given qualifier as key ifclaim.qualifiersthen localqualifier=claim.qualifiers[qualifierId] ifqualifierthen ifqualifier[1].datatype=="monolingualtext"then -- iterate over monolingualtext qualifiers to get languages localqual_lang,qual_mul foridxinpairs(qualifier)do qual_lang=getSnak(qualifier[idx],{"datavalue","value","language"}) ifqual_lang==parameters.lang[1]then returnqualifier[idx]-- return local language if found elseifqual_lang=="mul"then qual_mul=qualifier[idx] end end returnqual_mul-- else return multilingual elseifparameters.listthen returnqualifier else returnqualifier[1] end end end returnnil,printError("qualifier-not-found") else -- otherwise return the main snak returnclaim.mainsnak end end localfunctiongetValueOfClaim(claim,qualifierId,parameters) localsnak,error=getQualifierSnak(claim,qualifierId,parameters) ifnotsnakthen returnnil,nil,error elseifsnak[1]then-- a multi qualifier localresult,sortkey={},{} localmaxvals=tonumber(parameters.listmax) foridxinpairs(snak)do result[#result+1],sortkey[#sortkey+1]=getSnakValue(snak[idx],parameters) ifmaxvalsandmaxvals==#resultthenbreakend end returnmw.text.listToText(result,parameters.qseparator,parameters.qconjunction),sortkey[1] else-- a property or a qualifier returngetSnakValue(snak,parameters) end end localfunctiongetValueOfParentClaim(claim,qualifierId,parameters) localqids=mw.text.split(qualifierId,'/',true) localvalue,sortkey,valueraw={},{},{} localparent_raw,value_text ifqids[1]==parameters.propertythen parent_raw,_,_=getValueOfClaim(claim,nil,{["formatting"]="raw",["lang"]=parameters.lang}) else parent_raw,_,_=getValueOfClaim(claim,qids[1],{["formatting"]="raw",["lang"]=parameters.lang,["list"]=true,["qseparator"]='/',["qconjunction"]='/'}) end ifstring.sub(parent_rawor'',1,1)=="Q"then-- protection for 'no value' localparent_qids=mw.text.split(parent_raw,'/',true) foridx,p_qidinipairs(parent_qids)do localparent_claims=mw.wikibase.getBestStatements(p_qid,qids[2]) ifparent_claims[1]then value[idx],sortkey[idx],_=getValueOfClaim(parent_claims[1],nil,parameters) -- raw parent value needed for while/black lists, lang for avoiding an error on types other than entity valueraw[idx],_,_=getValueOfClaim(parent_claims[1],nil,{["formatting"]="raw",["lang"]=parameters.lang}) end end end ifvalue[1]then value_text=mw.text.listToText(value,parameters.qseparator,parameters.qconjunction) end returnvalue_text,sortkey[1],valueraw[1] end -- see d:Help:Sources localfunctiongetReferences(claim,parameters) ifnot(parameters.referencesorparameters.onlysourced)then return'',false end locallang=parameters.lang localmaxrefs=tonumber(parameters.references)or1 localnotproperref={ ["P143"]=true,-- imported from ["P3452"]=true,-- inferred from ["P887"]=true,-- based on heuristic ["P4656"]=true-- Wikimedia import URL } localresult={} -- traverse through all references forrefinpairs(claim.referencesor{})do localrefparts localrefs={} localvalidref=true localref_id -- traverse through all parts of the current reference forsnakkey,snakvalinpairs(claim.references[ref].snaksor{})do forpartkey,_inpairs(claim.references[ref].snaks[snakkey]or{})do ifnotproperref[snakkey]then-- not a proper reference validref=false break end end ifvalidrefthen forsnakidx=1,#snakvaldo ifsnakidx>1thenrefparts=refparts..", "end ifsnakval[snakidx].datatype=='external-id'then refparts=refpartsor''..(getSnakValue(snakval[snakidx],{formatting='externalid',property=snakval[snakidx].property,lang=lang})or'') else refparts=refpartsor''..(getSnakValue(snakval[snakidx],{lang=lang})or'') end end refs[snakkey]=refparts refparts=nil ifsnakkey=="P248"then-- stated in ref_id=getSnak(snakval,{1,"datavalue","value","id"}) end end end -- fill missing values with parent item ifref_idthen localfunctionrefParent(qid,pid,formatting) localsnak=getSnak(mw.wikibase.getBestStatements(qid,pid),{1,"mainsnak"}) returnsnakandgetSnakValue(snak,{formatting=formatting,lang=lang}) end refs['P50']=refs['P50']orrefParent(ref_id,'P50','label')-- author refs['P407']=refs['P407']orrefParent(ref_id,'P407','label')-- language of work refs['P123']=refs['P123']orrefParent(ref_id,'P123','label')-- publisher refs['P577']=refs['P577']orrefParent(ref_id,'P577')-- date refs['P1433']=refs['P1433']orrefParent(ref_id,'P1433','label')-- published in refs['P304']=refs['P304']orrefParent(ref_id,'P304')-- page(s) refs['P433']=refs['P433']orrefParent(ref_id,'P433')-- issue refs['P236']=refs['P236']orrefParent(ref_id,'P236')-- ISSN refs['P356']=refs['P356']orrefParent(ref_id,'P356')-- DOI end -- get title of local templates for citing references localtemplate_web=mw.wikibase.getSitelink('Q5637226')or"" template_web=mw.text.split(template_web,":")[2]-- split off namespace from front localtemplate_journal=mw.wikibase.getSitelink('Q5624899')or"" template_journal=mw.text.split(template_journal,":")[2] localciteParams={} ifrefs['P854']and(refs['P1476']orrefs['P248'])andtemplate_webthen -- if both "reference URL" and "title" (or "stated in") are present, then use cite web template citeParams[i18n['cite']['url']]=refs['P854'] ifrefs['P248']andrefs['P1476']==nilthen citeParams[i18n['cite']['title']]=refs['P248']:match("^%[%[.-|(.-)%]%]") else citeParams[i18n['cite']['title']]=refs['P1476'] citeParams[i18n['cite']['website']]=refs['P248'] end citeParams[i18n['cite']['author']]=refs['P50'] citeParams[i18n['cite']['language']]=refs['P407'] citeParams[i18n['cite']['publisher']]=refs['P123'] citeParams[i18n['cite']['date']]=refs['P577'] citeParams[i18n['cite']['pages']]=refs['P304'] citeParams[i18n['cite']['access-date']]=refs['P813'] citeParams[i18n['cite']['archive-url']]=refs['P1065'] citeParams[i18n['cite']['archive-date']]=refs['P2960'] citeParams[i18n['cite']['quote']]=refs['P1683'] refparts=mw.getCurrentFrame():expandTemplate{title=template_web,args=citeParams} elseifrefs['P1433']and(refs['P1476']orrefs['P248'])andtemplate_journalthen -- if both "published in" and "title" (or "stated in") are present, then use cite journal template citeParams[i18n['cite']['work']]=refs['P1433'] citeParams[i18n['cite']['title']]=refs['P1476']orrefs['P248'] citeParams[i18n['cite']['author']]=refs['P50'] citeParams[i18n['cite']['date']]=refs['P577'] citeParams[i18n['cite']['issue']]=refs['P433'] citeParams[i18n['cite']['pages']]=refs['P304'] citeParams[i18n['cite']['language']]=refs['P407'] citeParams[i18n['cite']['issn']]=refs['P236'] citeParams[i18n['cite']['doi']]=refs['P356'] refparts=mw.getCurrentFrame():expandTemplate{title=template_journal,args=citeParams} elseifvalidrefthen -- raw ouput localsnaksorder=claim.references[ref]["snaks-order"] localfunctionindexed(a) for_,binipairs(snaksorder)do ifb==athenreturntrueend end returnfalse end fork,_inpairs(refsor{})do ifnotindexed(k)then table.insert(snaksorder,k) end end localitalics="''" localref_label for_,kinipairs(snaksorder)do ifrefs[k]then refparts=refpartsandrefparts.." "or"" ref_label=case('infoboxlabel',getLabelByLangs(k,lang)or'') refparts=refparts..mw.ustring.gsub(ref_label,"^%l",mw.ustring.upper)..": " refparts=refparts..italics..refs[k]..italics.."." italics="" end end end ifrefpartsthen localref_name=claim.references[ref].hash result[#result+1]=mw.getCurrentFrame():extensionTag("ref",refparts,{name=ref_name}) ifmaxrefsandmaxrefs==#resultthenbreakend end end if#result>0then ifparameters.referencesthen ifisSet(i18n.categoryref)then result[#result+1]="[["..i18n.categoryref.."]]" end returntable.concat(result),true else return'',true end end return'',false end -- Set lists of filtered values localfunctionsetFilterLists(num_qual,args) locallists={['whitelist']={},['blacklist']={},['ignorevalue']={},['selectvalue']={}} fori=0,num_qualdo fork,_inpairs(lists)do ifisSet(args[k..i])then lists[k][tostring(i)]={} localpattern='Q%d+' ifstring.sub(args[k..i],1,1)~='Q'then pattern='[^%p%s]+' end forqinstring.gmatch(args[k..i],pattern)do lists[k][tostring(i)][q]=true end end end end returnlists['whitelist'],lists['blacklist'],lists['ignorevalue'],lists['selectvalue'] end localfunctiontableParameters(args,parameters,column) localcolumn_params=mw.clone(parameters) column_params.formatting=args["colformat"..column];ifcolumn_params.formatting==""thencolumn_params.formatting=nilend column_params.convert=args["convert"..column] ifargs["case"..column]then column_params.case=args["case"..column] end returncolumn_params end localfunctiongetEntityId(args,pargs,unnamed) pargs=pargsor{} localid=args.itemorargs.fromor(unnamedandmw.text.trim(args[1]or'')ornil) ifnotisSet(id)then id=pargs.itemorpargs.fromor(unnamedandmw.text.trim(pargs[1]or'')ornil) end ifisSet(id)then ifstring.find(id,":")then-- remove prefix as Property:Pid id=mw.text.split(id,":")[2] end else id=mw.wikibase.getEntityIdForCurrentPage() end returnid end localfunctiongetArg(value,default,aliases) iftype(value)=='boolean'thenreturnvalue elseifvalue=="false"orvalue=="no"thenreturnfalse elseifvalue=="true"orvalue=="yes"thenreturntrue elseifvalueandaliasesandaliases[value]thenreturnaliases[value] elseifisSet(value)thenreturnvalue elseifdefaultthenreturndefault elsereturnnil end end -- Main function claim --------------------------------------------- -- on debug console use: =p.claim{item="Q...", property="P...", ...} functionp.claim(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localis_sandbox=isSet(pargs.sandbox) ifnotrequiredandis_sandboxthen returnrequire(wiki.module_title.."/"..mw.message.new('Sandboxlink-subpage-name'):inLanguage(wiki.langcode):plain()).claim(frame) end --If a value is already set, use it ifisSet(args.value)then ifargs.value=='NONE'then return else returnargs.value end end -- arguments localparameters={} parameters.id=getEntityId(args,pargs) ifparameters.id==nilthenreturnend parameters.property=string.upper(args.propertyor"") localqualifierId={} qualifierId[1]=getArg(string.upper(args.qualifierorargs.qualifier1or"")) locali=2 whileisSet(args["qualifier"..i])do qualifierId[i]=string.upper(args["qualifier"..i]) i=i+1 end parameters.formatting=getArg(args.formatting) parameters.convert=getArg(args.convert) parameters.numformat=getArg(args.numformat) parameters.case=args.case parameters.list=getArg(args.list,true,{firstrank='bestrank'}) parameters.listmax=args.listmax parameters.listrank=getArg(args.listrank) iftype(parameters.list)=="number"then-- backwards compatibility parameters.listmax=parameters.listmaxorparameters.list parameters.list=true elseifparameters.list=="bestrank"then parameters.listrank=parameters.listrankor"bestrank" parameters.list=true end parameters.shownovalue=getArg(args.shownovalue,true) parameters.showsomevalue=getArg(args.showsomevalue,true) parameters.separator=getArg(args.separator) parameters.conjunction=getArg(args.conjunction,parameters.separator) parameters.qseparator=getArg(args.qseparator,parameters.separator) parameters.qconjunction=getArg(args.qconjunction,parameters.conjunction) localsorting_col=args.tablesort localsorting_up=(args.sortingor"")~="-1" localrowformat=args.rowformat parameters.references=getArg(args.references,false) parameters.onlysourced=getArg(args.onlysourced,false) localshowerrors=args.showerrors localdefault=args.default ifdefaultthenshowerrors=nilend parameters.lang=findLang(args.lang) ifparameters.formatting=="raw"then parameters.editicon,parameters.labelicon=false,false else parameters.editicon,parameters.labelicon=setIcons(args.editicon,pargs.editicon)-- needs loadI18n by findLand end -- fetch property localclaims={} localbestrank=parameters.listrank=='bestrank'andparameters.list~='lang' forpinstring.gmatch(parameters.property,'P[%d/P]+')do-- P123 or P45/P67 ifstring.find(p,".+/.+")then localprops=mw.text.split(p,"/") localclaims_child={} claims_child=getStatements(parameters.id,props[1],bestrank) if#claims_child>0then localparent_id,_,_=getValueOfClaim(claims_child[1],nil,{["formatting"]="raw",["lang"]=parameters.lang}) ifstring.sub(parent_idor'',1,1)=="Q"then claims=getStatements(parent_id,props[2],bestrank) if#claims>0then parameters.property=props[1] break end end end else claims=getStatements(parameters.id,p,bestrank) if#claims>0then parameters.property=p break end end end if#claims==0then localret=showerrorsandprintError("property-not-found")ordefault returnret,args.query=='num'and0or'' end -- defaults for table localpreformat,postformat="","" localwhitelisted=false localwhitelist,blacklist,ignorevalue,selectvalue={},{},{},{} ifparameters.formatting=="table"then parameters.separator=parameters.separatoror"<br />" parameters.conjunction=parameters.conjunctionor"<br />" parameters.qseparator=getArg(args.qseparator,mw.message.new('Comma-separator'):inLanguage(parameters.lang[1]):plain()) parameters.qconjunction=getArg(args.qconjunction,parameters.qseparator) ifnotrowformatthen rowformat="$0 ($1" i=2 whilequalifierId[i]do rowformat=rowformat..", $"..i i=i+1 end rowformat=rowformat..")" elseifmw.ustring.find(rowformat,"^[*#]")then parameters.separator="</li><li>" parameters.conjunction="</li><li>" ifmw.ustring.match(rowformat,"^[*#]")=="*"then preformat="<ul><li>" postformat="</li></ul>" else preformat="<ol><li>" postformat="</li></ol>" end rowformat=mw.ustring.gsub(rowformat,"^[*#] ?","") end -- set lists of filtered values whitelist,blacklist,ignorevalue,selectvalue=setFilterLists(#qualifierId,args) localnext=next ifnext(whitelist)~=nilthenwhitelisted=trueend end -- set feminine case if gender is requested localitemgender=args.itemgender localidgender ifitemgenderthen ifstring.match(itemgender,"^P%d+$")then localsnak_id=getSnak(mw.wikibase.getBestStatements(parameters.id,itemgender),{1,"mainsnak","datavalue","value","id"}) ifsnak_idthen idgender=snak_id end elseifstring.match(itemgender,"^Q%d+$")then idgender=itemgender end end localgender_requested=false ifparameters.case=="gender"oridgenderthen gender_requested=true elseifparameters.formatting=="table"then fori=0,#qualifierIddo ifargs["case"..i]andargs["case"..i]=="gender"then gender_requested=true break end end end ifgender_requestedthen iffeminineGender(idgenderorparameters.id)then parameters.gender="feminineform" end end -- get initial sort indices localsortindices={} foridxinpairs(claims)do sortindices[#sortindices+1]=idx end -- sort by claim rank localcomparator=function(a,b) localrankmap={deprecated=2,normal=1,preferred=0} localranka=rankmap[claims[a].rankor"normal"]..string.format("%08d",a) localrankb=rankmap[claims[b].rankor"normal"]..string.format("%08d",b) returnranka<rankb end table.sort(sortindices,comparator) localresult,result2,result_query localerror ifparameters.listorparameters.formatting=="table"then -- convert LF to line feed, <br /> may not work on some cases parameters.separator=parameters.separator=="LF"and"\010"orparameters.separator parameters.conjunction=parameters.conjunction=="LF"and"\010"orparameters.conjunction -- i18n separators parameters.separator=parameters.separatorormw.message.new('Comma-separator'):inLanguage(parameters.lang[1]):plain() parameters.conjunction=parameters.conjunctionor(mw.message.new('And'):inLanguage(parameters.lang[1]):plain()..mw.message.new('Word-separator'):inLanguage(parameters.lang[1]):plain()) -- iterate over all elements and return their value (if existing) localvalue,valueq localsortkey,sortkeyq localvalues={} localsortkeys={} localrefs={} localrowlist={}-- rows to list with whitelist or blacklist foridxinpairs(claims)do localclaim=claims[sortindices[idx]] localreference={} ifnotwhitelistedthenrowlist[idx]=trueend ifparameters.formatting=="table"then localparams=tableParameters(args,parameters,"0") value,sortkey,error=getValueOfClaim(claim,nil,params) ifvaluethen values[#values+1]={} sortkeys[#sortkeys+1]={} refs[#refs+1]={} ifwhitelist["0"]orblacklist["0"]then localvalueraw,_,_=getValueOfClaim(claim,nil,{["formatting"]="raw",["lang"]=params.lang}) ifwhitelist["0"]andwhitelist["0"][valuerawor""]then rowlist[#values]=true elseifblacklist["0"]andblacklist["0"][valuerawor""]then rowlist[#values]=false end end fori,qualinipairs(qualifierId)do localj=tostring(i) params=tableParameters(args,parameters,j) localvalueq,sortkeyq,valueraw ifqual==parameters.propertythen-- hack for getting the property with another formatting, i.e. colformat1=raw valueq,sortkeyq,_=getValueOfClaim(claim,nil,params) else forqinmw.text.gsplit(qual,'%s*OR%s*')do ifstring.find(q,".+/.+")then valueq,sortkeyq,valueraw=getValueOfParentClaim(claim,q,params) elseifstring.find(q,"^/.+")then localclaim2=getStatements(parameters.id,string.sub(q,2),bestrank) if#claim2>0then -- only first value of a property as alternative to a qualifier -- multiple values may not be related to a given raw of the table valueq,sortkeyq,_=getValueOfClaim(claim2[1],nil,params) end else valueq,sortkeyq,_=getValueOfClaim(claim,q,params) end ifvalueqthen qual=q break end end end values[#values]["col"..j]=valueq sortkeys[#sortkeys]["col"..j]=sortkeyqorvalueq ifwhitelist[j]orblacklist[j]orignorevalue[j]orselectvalue[j]then valueq=valueraworgetValueOfClaim(claim,qual,{["formatting"]="raw",["lang"]=params.lang,["list"]=params.list}) ifvalueqthen ifwhitelist[j]then fork,vinpairs(whitelist[j])do ifvandstring.find(valueq,k,1,true)then rowlist[#values]=true end end elseifblacklist[j]then fork,vinpairs(blacklist[j])do ifvandstring.find(valueq,k,1,true)then rowlist[#values]=false end end elseifignorevalue[j]then fork,vinpairs(ignorevalue[j])do ifvandstring.find(valueq,k,1,true)then values[#values]["col"..j]=nil end end elseifselectvalue[j]then localselected fork,vinpairs(selectvalue[j])do ifvandstring.find(valueq,k,1,true)then selected=true end end ifselected==nilthen values[#values]["col"..j]=nil end end end end end end else value,sortkey,error=getValueOfClaim(claim,qualifierId[1],parameters) values[#values+1]={} sortkeys[#sortkeys+1]={} refs[#refs+1]={} end ifnotvalueandshowerrorsthenvalue=errorend ifvaluethen if(parameters.referencesorparameters.onlysourced)andclaim.referencesthen reference=claim.references end refs[#refs]["col0"]=reference values[#values]["col0"]=value sortkeys[#sortkeys]["col0"]=sortkeyorvalue end end -- sort and format results sortindices={} foridxinpairs(values)do sortindices[#sortindices+1]=idx end ifsorting_colthen localsorting_table=mw.text.split(sorting_col,'%D+') localcomparator=function(a,b) localvaluea,valueb locali=1 whilevaluea==valuebandi<=#sorting_tabledo valuea=sortkeys[a]["col"..sorting_table[i]]or'' valueb=sortkeys[b]["col"..sorting_table[i]]or'' i=i+1 end ifsorting_upthen returnvalueb>valuea end returnvalueb<valuea end table.sort(sortindices,comparator) end localmaxvals=tonumber(parameters.listmax) result={} foridxinpairs(values)do localvaluerow=values[sortindices[idx]] localreference,valid_ref=getReferences({["references"]=refs[sortindices[idx]]["col0"]},parameters) value=valuerow["col0"] ifparameters.formatting=="table"then ifnotrowlist[sortindices[idx]]then value=nil else localrowformatting=rowformat.."$"-- fake end character added for easy gsub value=mw.ustring.gsub(rowformatting,"$0",{["$0"]=value}) value=mw.ustring.gsub(value,"$R0",reference)-- add reference fori,_inipairs(qualifierId)do localvalueq=valuerow["col"..i] ifargs["rowsubformat"..i]andisSet(valueq)then -- add fake end character $ -- gsub $i not followed by a number so $1 doesn't match $10, $11... -- remove fake end character valueq=captureEscapes(valueq) valueq=mw.ustring.gsub(args["rowsubformat"..i].."$","$"..i.."(%D)",valueq.."%1") valueq=string.sub(valueq,1,-2) rowformatting=mw.ustring.gsub(rowformatting,"$"..i.."(%D)",args["rowsubformat"..i].."%1") end valueq=valueqandcaptureEscapes(valueq)or'' value=mw.ustring.gsub(value,"$"..i.."(%D)",valueq.."%1") end value=string.sub(value,1,-2)-- remove fake end character value=expandBraces(value,rowformatting) end elseifvaluethen value=expandBraces(value,parameters.formatting) value=value..reference end ifisSet(value)and(notparameters.onlysourcedor(parameters.onlysourcedandvalid_ref))then result[#result+1]=value ifnotparameters.listor(maxvalsandmaxvals==#result)then break end end end ifargs.query=='num'then result_query=#result end if#result>0then ifparameters.formatting=='table'then result=addEditIconTable(result,parameters)-- in a table, add edit icon on last element end result=preformat..mw.text.listToText(result,parameters.separator,parameters.conjunction)..postformat else result='' end else -- return first element localclaim=claims[sortindices[1]] result,result2,error=getValueOfClaim(claim,qualifierId[1],parameters) ifresultthen localref,valid_ref=getReferences(claim,parameters) ifparameters.onlysourcedandvalid_ref==falsethen result=nil else result=result..ref end end ifargs.query=='num'thenresult_query=resultand1or0end end ifisSet(result)then ifnot(parameters.formatting=='table'or(result2andresult2=='no-icon'))then -- add edit icon, except table added previously and except explicit no-icon internal flag result=result..addEditIcon(parameters) end else ifshowerrorsthenresult=errorelseresult=defaultend end ifargs.query=='untranslated'andrequiredandnotis_sandboxthen result_query=untranslated end returnresult,result_queryor'' end -- Local functions for getParentValues ----------------------- localfunctionuc_first(word) ifword==nilthenreturnend returnmw.ustring.upper(mw.ustring.sub(word,1,1))..mw.ustring.sub(word,2) end localfunctiongetPropertyValue(id,property,parameter,langs,labelicon,case) localsnaks=mw.wikibase.getBestStatements(id,property) localmysnak=getSnak(snaks,{1,"mainsnak"}) ifmysnak==nilthen return end localentity_id localresult='-'-- default for 'no value' ifmysnak.datavaluethen entity_id="Q"..tostring(mysnak.datavalue.value['numeric-id']) result,_=getSnakValue(mysnak,{formatting=parameter,lang=langs,labelicon=labelicon,case=case}) end returnentity_id,result end localfunctiongetParentObjects(id, prop_format, label_format, languages, propertySupString, propertyLabel, propertyLink, label_show, labelicon0, labelicon1, upto_number, upto_label, upto_value, last_only, grammatical_case, include_self) localpropertySups=mw.text.split(propertySupString,'[^P%d]') localmaxloop=10 ifupto_numberthen maxloop=upto_number elseifnext(upto_label)ornext(upto_value)then maxloop=50 end locallabels_filter=next(label_show) localresult={} localid_value=id foriter=1,maxloopdo locallink,label,labelwicon,linktext,id_label for_,propertySupinpairs(propertySups)do local_id_value,_link=getPropertyValue(id_value,propertySup,prop_format,languages,labelicon1,grammatical_case) if_id_valueand_linkthenid_value=_id_value;link=_linkbreakend end ifnotid_valueornotlinkthenbreakend ifpropertyLinkthen _,linktext=getPropertyValue(id_value,propertyLink,"label",languages) iflinktextthen link=mw.ustring.gsub(link,"%[%[(.*)%|.+%]%]","[[%1|"..linktext.."]]") end end id_label,label=getPropertyValue(id_value,propertyLabel,label_format,languages,false,"infoboxlabel") iflabelicon0then _,labelwicon=getPropertyValue(id_value,propertyLabel,label_format,languages,labelicon0,"infoboxlabel") else labelwicon=label end iflabels_filter==nilor(label_show[id_label]orlabel_show[label])then result[#result+1]={labelwicon,link} label_show[id_labelor'none'],label_show[labelor'none']=nil,nil-- only first label found end ifupto_label[id_label]orupto_label[label]orupto_value[id_value]then break end end iflast_onlythen result={result[#result]} end ifinclude_selfthen locallabel_self,link_self _,label_self=getPropertyValue(id,propertyLabel,label_format,languages,labelicon0,"infoboxlabel") link_self,_=getLabelByLangs(id,languages) table.insert(result,1,{label_self,link_self}) end returnresult end localfunctionparentObjectsToString(result, rowformat, cascade, sorting) localret={} localfirst=1 locallast=#result localiter=1 ifsorting=="-1"thenfirst=#result;last=1;iter=-1end fori=first,last,iterdo localrowtext=mw.ustring.gsub(rowformat,"$[01]",{["$0"]=result[i][1],["$1"]=result[i][2]}) ret[#ret+1]=expandBraces(rowtext,rowformat) end ifcascadethen localdirection=mw.language.new(wiki.langcode):isRTL()and"right"or"left" localsuffix="" fori=1,#retdo ret[i]='<ul style="line-height:100%; margin-'..direction..':0.45em; padding-'..direction..':0;"><li>'..ret[i] suffix=suffix..'</li></ul>' end ret[#ret]=ret[#ret]..suffix end returnret end -- Returns pairs of parent label and property value fetching a recursive tree functionp.getParentValues(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} ifnotrequiredandisSet(pargs.sandbox)then returnrequire(wiki.module_title.."/"..mw.message.new('Sandboxlink-subpage-name'):inLanguage(wiki.langcode):plain()).getParentValues(frame) end localid=getEntityId(args,pargs) ifid==nilthenreturnend locallanguages=findLang(args.lang) localpropertySup=getArg(args.property,"P131")--administrative entity localpropertyLabel=getArg(args.label,"P31")--instance localpropertyLink=getArg(args.valuetext) localproperty_format=getArg(args.formatting) locallabel_format=getArg(args.labelformat,"label") localupto_number=getArg(args.upto) locallast_only=getArg(args.last_only,false) localediticon,labelicon=setIcons(args.editicon,pargs.editicon) localinclude_self=getArg(args.include_self,false) localcase=getArg(args.case) localupto_label={} forqinstring.gmatch(args.uptolabelidor'','Q%d+')do upto_label[q]=true end iftype(tonumber(upto_number))=="number"then upto_number=tonumber(upto_number) elseiftype(upto_number)=='string'then upto_number=nil require(wiki.module_title..'/debug').track('upto')-- replace upto by uptolabelid end localupto_value={} forqinstring.gmatch(args.uptovalueidorargs.uptolinkidor'','Q%d+')do upto_value[q]=true end locallabel_show={} forqinstring.gmatch(args.showlabelidor'','Q%d+')do label_show[q]=true end for_,vinipairs(mw.text.split(args.labelshowor'',"/"))do ifv~=''then label_show[uc_first(v)]=true require(wiki.module_title..'/debug').track('labelshow')-- replace labelshow by showlabelid end end localrowformat=args.rowformat;ifnotisSet(rowformat)thenrowformat="$0 = $1"end locallabelicon0,labelicon1=labelicon,labelicon ifstring.find(label_format,'{{.*$0.*}}')or(string.find(rowformat,'{{.*$0.*}}')andlabel_format~='raw')then labelicon0=false end localresult=getParentObjects(id, property_format, label_format, languages, propertySup, propertyLabel, propertyLink, label_show, labelicon0, labelicon1, upto_number, upto_label, upto_value, last_only, case, include_self) if#result==0thenreturnend localseparator=args.separator;ifnotisSet(separator)thenseparator="<br />"end localsorting=args.sorting;ifsorting==""thensorting=nilend localcascade=(args.cascade=="true"orargs.cascade=="yes") localret=parentObjectsToString(result, rowformat, cascade, sorting) ret=addEditIconTable(ret,{property=propertySup,editicon=editicon,id=id,lang=languages}) returnmw.text.listToText(ret,separator,separator) end -- Link with a parent label -------------------- functionp.linkWithParentLabel(frame) localpargs=frame.argsandframe:getParent().argsor{} ifnotrequiredandisSet(pargs.sandbox)then returnrequire(wiki.module_title.."/"..mw.message.new('Sandboxlink-subpage-name'):inLanguage(wiki.langcode):plain()).linkWithParentLabel(frame) end localargs={} ifframe.argsthen fork,vinpairs(frame.args)do-- metatable args[k]=v end else args=frame-- via require end ifisSet(args.value)then returnargs.value end -- get id value of property/qualifier locallargs=mw.clone(args) largs.list=tonumber(args.list)andargs.listortrue largs.formatting="raw" largs.separator="/·/" largs.editicon=false localitems_list,_=p.claim(largs) ifnotisSet(items_list)thenreturnend localitems_table=mw.text.split(items_list,"/·/",true) -- get internal link of property/qualifier ifisSet(args.formatting)then largs.formatting=nil-- default link if defined with any value else largs.formatting="internallink" end locallink_list,_=p.claim(largs) locallink_table=mw.text.split(link_list,"/·/",true) -- get label of parent property localparent_claim=getSnak(getStatements(items_table[1],args.parent,true),{1,"mainsnak","datatype"}) ifparent_claim=='monolingualtext'then largs.formatting=nil largs.list='lang' else largs.formatting="label" largs.list=false end largs.property=args.parent largs.qualifier=nil fori,vinipairs(items_table)do largs.item=v locallink_label,_=p.claim(largs) ifisSet(link_label)then link_table[i]=mw.ustring.gsub(link_table[i]or'',"%[%[(.*)%|.+%]%]","[[%1|"..link_label.."]]") end end args.editicon,_=setIcons(args.editicon,pargs.editicon) args.id=getEntityId(args,pargs) args.lang=findLang(args.lang) returnmw.text.listToText(link_table)..addEditIcon(args) end -- Calculate number of years old ---------------------------- functionp.yearsOld(frame) ifnotrequiredandframe.argsandisSet(frame:getParent().args.sandbox)then returnrequire(wiki.module_title.."/"..mw.message.new('Sandboxlink-subpage-name'):inLanguage(wiki.langcode):plain()).yearsOld(frame) end localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localid=getEntityId(args,pargs) ifid==nilthenreturnend locallang=mw.language.new('en') localfunctiongetBestDate(id,prop) localmainsnak=getSnak(mw.wikibase.getBestStatements(id,prop),{1,"mainsnak"}) ifmainsnakandmainsnak.snaktypethen ifmainsnak.snaktype=="somevalue"then return{time=nil,precision=0} elseifmainsnak.snaktype=="value"then returngetSnak(mainsnak,{"datavalue","value"}) end end return{time=nil,precision=nil} end localbirth=getBestDate(id,'P569') ifbirth.time==nilorbirth.precision<8then return end localdeath=getBestDate(id,'P570') ifdeath.precisionanddeath.precision<8then-- includes somevalue return elseifdeath.time==nilthen death={time=lang:formatDate('c'),precision=11}-- current date end localdates={} dates[1]={['min']={},['max']={},['precision']=birth.precision} dates[1].min.year=tonumber(mw.ustring.match(birth.time,"^[+-]?%d+")) dates[1].min.month=tonumber(mw.ustring.match(birth.time,"-(%d%d)-")) dates[1].min.day=tonumber(mw.ustring.match(birth.time,"-(%d%d)T")) dates[1].max=mw.clone(dates[1].min) dates[2]={['min']={},['max']={},['precision']=death.precision} dates[2].min.year=tonumber(mw.ustring.match(death.time,"^[+-]?%d+")) dates[2].min.month=tonumber(mw.ustring.match(death.time,"-(%d%d)-")) dates[2].min.day=tonumber(mw.ustring.match(death.time,"-(%d%d)T")) dates[2].max=mw.clone(dates[2].min) fori,dinipairs(dates)do ifd.precision==10then-- month d.min.day=1 localtimestamp=string.format("%04d",tostring(math.abs(d.max.year))) ..string.format("%02d",tostring(d.max.month)) .."01" d.max.day=tonumber(lang:formatDate("j",timestamp.." + 1 month - 1 day")) elseifd.precision<10then-- year or decade d.min.day=1 d.min.month=1 d.max.day=31 d.max.month=12 ifd.precision==8then-- decade d.max.year=d.max.year+9 end end end localfunctionage(d1,d2) localyears=d2.year-d1.year ifd2.month<d1.monthor(d2.month==d1.monthandd2.day<d1.day)then years=years-1 end ifd2.year>0andd1.year<0then years=years-1-- no year 0 end returnyears end localold_min=age(dates[1].max,dates[2].min) localold_max=age(dates[1].min,dates[2].max) ifold_max>200then require(wiki.module_title..'/debug').track('200yo') end localold,old_expr ifold_min==0andold_max==0then old="< 1" old_max=1-- expression in singular elseifold_min==old_maxthen old=old_min else old=old_min.."/"..old_max end ifargs.formatting=='unit'then locallangs=findLang(args.lang) localyo localyo_pl={} iflangs[1]==wiki.langcodethen yo_pl=i18n["years-old"] end ifnotisSet(yo_pl[2])then localyo_label,_=getLabelByLangs('Q24564698',langs) yo_pl={yo_label,yo_label} end yo=mw.language.new(langs[1]):plural(old_max,yo_pl) ifmw.ustring.find(yo,'$1',1,true)then old_expr=mw.ustring.gsub(yo,"$1",old) else old_expr=old..' '..yo end elseifargs.formattingthen old_expr=expandBraces(mw.ustring.gsub(args.formatting,'$1',old),args.formatting) else old_expr=old end returnold_expr end -- Gets a label in a given language (content language by default) or its fallbacks, optionnally linked. functionp.getLabel(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} ifnotrequiredandisSet(pargs.sandbox)then returnrequire(wiki.module_title.."/"..mw.message.new('Sandboxlink-subpage-name'):inLanguage(wiki.langcode):plain()).getLabel(frame) end localid=getEntityId(args,pargs,1) ifid==nilthenreturnend locallanguages=findLang(args.lang) locallabelicon=false ifmw.wikibase.isValidEntityId(id)then _,labelicon=setIcons(args.editicon,pargs.editicon) end locallabel_icon='' locallabel,lang ifargs.labelthen label=args.label else -- exceptions or labels fixed localexist,labels=pcall(require,wiki.module_title.."/labels"..(languages[1]==wiki.langcodeand''or'/'..languages[1])) ifexistandlabels.infoboxLabelsFromIdandnext(labels.infoboxLabelsFromId)~=nilthen label=labels.infoboxLabelsFromId[id] end iflabel==nilthen label,lang=getLabelByLangs(id,languages) iflabelthen ifisSet(args.itemgender)then iffeminineGender(args.itemgender)then label=feminineForm(id,lang)orlabel end local_,items_g=string.gsub(args.itemgender,"Q%d+","") ifnotisSet(args.case)anditems_g>1then args.case="plural" end end label=mw.language.new(lang):ucfirst(mw.text.nowiki(label))-- sanitize ifargs.casethen label=case(args.case,label,lang) end end label_icon=addLabelIcon(id,lang,languages[1],labelicon) end end locallinked=args.linked localret2=requiredanduntranslatedor'' ifisSet(linked)andlinked~="no"then localarticle=mw.wikibase.getSitelink(id)or("d:Special:EntityPage/"..id) return"[["..article.."|"..(labelorid).."]]"..label_icon,ret2 else return(labelorid)..label_icon,ret2 end end functionp.sitelinks(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} -- arguments localparam={} param.id=getEntityId(args,pargs) ifparam.id==nilthenreturnend param.project=getArg(args.project) param.site=getArg(args.site) param.sitelang=getArg(args.sitelang) param.show=getArg(args.formatting,'[[$w:$l:$t|$s:$t]] $i') param.sep=getArg(args.separator,', ') -- fetch sitelinks localsitelinks_obj=mw.wikibase.getEntity(param.id).sitelinks localslinks={}-- do some clean up (commonswiki > commons) and add some data localiw={['wikipedia']='w',['wikibooks']='b',['wikinews']='n',['wikiquote']='q', ['wikisource']='s',['wikiversity']='v',['wikivoyage']='voy',['wiktionary']='wikt',['commons']='c', ['meta']='m',['mediawiki']='mw',['species']='species',['wikidata']='d',['wikifunctions']='f'} forslink,sdatainpairs(sitelinks_obj)do -- langcode + wiki, wikibooks, wikinews, wikiquote, wikisource, wikiversity, wikivoyage, wiktionary locals_lang=string.match(slink,'(%l+)wik[it]') locals_project=string.match(slink,'wik[it]%l*') ifslink=='commonswiki'orslink=='metawiki'orslink=='mediawikiwiki' orslink=='specieswiki'orslink=='wikidatawiki'orslink=='wikifunctionswiki' then s_project=string.sub(slink,1,-5)-- remove -wiki slinks[s_project]={['lang']='und',['project']=s_project,['iw']=iw[s_project],['title']=sdata.title,['badges']=sdata.badges} elseifs_project=='wiki'then-- restore project full name slinks[slink]={['lang']=s_lang,['project']='wikipedia',['iw']='w',['title']=sdata.title,['badges']=sdata.badges} elseifs_project=='wiktionary'then-- use short site name s_project=string.sub(slink,1,-7) slinks[s_project]={['lang']=s_lang,['project']='wiktionary',['iw']='wikt',['title']=sdata.title,['badges']=sdata.badges} else slinks[slink]={['lang']=s_lang,['project']=s_project,['iw']=iw[s_project],['title']=sdata.title,['badges']=sdata.badges} end end -- select requested project, site, sitelang localslinks_req={} ifnot(param.projectorparam.siteorparam.sitelang)then slinks_req=slinks else forprinstring.gmatch(param.projector'','%l+')do-- lowercase letters, skip separators forsl,sdinpairs(slinks)do ifsd.project==prthen slinks_req[sl]=sd end end end forsinstring.gmatch(param.siteor'','%l+')do forsl,sdinpairs(slinks)do ifsl==sthen slinks_req[sl]=sd end end end forlinstring.gmatch(param.sitelangor'','%l+')do forsl,sdinpairs(slinks)do ifsd.lang==lthen slinks_req[sl]=sd end end end end -- sort table localsites_sorted={} forsitexinpairs(slinks_req)do sites_sorted[#sites_sorted+1]=sitex end localsort_project_lang=function(a,b) localkey_a=slinks_req[a].project..slinks_req[a].lang localkey_b=slinks_req[b].project..slinks_req[b].lang returnkey_a<key_b end table.sort(sites_sorted,sort_project_lang) -- format output localshowtext={} localshownum,showbnum=0,0 for_,slinipairs(sites_sorted)do localsd=slinks_req[sl] localshow=param.show-- default '[[$w:$l:$t|$s:$t]] $i' iw:lang:title, site:title icon, also $p project show=string.gsub(show,'$w',sd.iw) show=string.gsub(show,'$p',sd.project) ifsd.lang=='und'then show=string.gsub(show,'$l:?','') else show=string.gsub(show,'$l',sd.lang) end show=string.gsub(show,'$t',sd.title) show=string.gsub(show,'$s',sl) ifnext(sd.badges)then show=string.gsub(show,'$i','[[File:Article de qualité.svg|15x15px]]') showbnum=showbnum+1 else show=string.gsub(show,' ?$i','') end ifshow~=param.showthen table.insert(showtext,show) end shownum=shownum+1 end localoutput ifstring.find(param.show,'$[nb]')then output=string.gsub(param.show,'$n',shownum)-- number of sites output=string.gsub(output,'$b',showbnum)-- number of badges else output=table.concat(showtext,param.sep) end returnoutput end -- Utilities ----------------------------- -- See also module ../debug. -- Copied from Module:Wikibase functionp.getSiteLink(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localid=getEntityId(args,pargs,1) ifid==nilthenreturnend returnmw.wikibase.getSitelink(id,mw.text.trim(args[2]or'')) end -- Helper function for the default language code used functionp.lang(frame) locallang=frameandframe.args[1]-- nil via require returnfindLang(lang)[1] end -- Number of statements functionp.numStatements(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localid=getEntityId(args,pargs) ifid==nilthenreturn0end localprop=mw.text.trim(args[1]or'') localnum={} ifnotisSet(prop)then locallargs={} fork,vinpairs(pargs)do largs[k]=v end fork,vinpairs(args)do largs[k]=v end largs.query='num' _,num=p.claim(largs) returnnum elseifargs[2]then-- qualifier localqual=mw.text.trim(args[2]) localvalues=p.claim{item=id,property=prop,qualifier=qual,formatting='raw',separator='/·/'} ifvaluesthen num=mw.text.split(values,'/·/') end else num=mw.wikibase.getBestStatements(id,prop) end return#num end -- Returns true if property datavalue is found excluding novalue/somevalue functionp.validProperty(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localitem=getEntityId(args,pargs) ifitem==nilthenreturnend localproperty=mw.text.trim(args[1]) localprop_data=getSnak(mw.wikibase.getBestStatements(item,property),{1,"mainsnak","datavalue"}) returnprop_dataandtrueornil end functionp.editAtWikidata(frame) localargs=frame.argsorframe-- via invoke or require localpargs=frame.argsandframe:getParent().argsor{} localvalue=isSet(args[1]) ifvaluethenreturnend localparam={} param.id=getEntityId(args,pargs) param.property=args.property param.lang=findLang(args.lang) param.editicon,_=setIcons(args.editicon) returnaddEditIcon(param) end functionp.formatNum(frame) localnum=tonumber(mw.text.trim(frame.args[1])) locallang=findLang(mw.text.trim(frame.args[2])) returnmw.language.new(lang[1]):formatNum(num) end -- [[Modul:Wikidata/Legacy]] compatibility -- look into entity object functionp.ViewSomething(frame) localf=(frame.args[1]orframe.args.id)andframeorframe:getParent() localid=f.args.id ifidand(#id==0)then id=nil end localdata=mw.wikibase.getEntity(id) ifnotdatathen returnnil end locali=1 whiletruedo localindex=f.args[i] ifnotindexthen iftype(data)=="table"then returnmw.text.jsonEncode(data,mw.text.JSON_PRESERVE_KEYS+mw.text.JSON_PRETTY) else returntostring(data) end end data=data[index]ordata[tonumber(index)] ifnotdatathen return end i=i+1 end end functionp.getImageLegend(frame) -- look for named parameter id; if it's blank make it nil localid=frame.args.id ifidand(#id==0)then id=nil end -- look for named parameter lang -- it should contain a two-character ISO-639 language code -- if it's blank fetch the language of the local wiki locallang=frame.args.lang if(notlang)or(#lang<2)then lang=mw.language.getContentLanguage().code end -- first unnamed parameter is the local parameter, if supplied localinput_parm=mw.text.trim(frame.args[1]or"") ifinput_parm=="FETCH_WIKIDATA"then localent=mw.wikibase.getEntity(id) localimgs ifentandent.claimsthen imgs=ent.claims.P18 end localimglbl ifimgsthen -- look for an image with 'preferred' rank fork1,v1inpairs(imgs)do ifv1.rank=="preferred"andv1.qualifiersandv1.qualifiers.P2096then localimglbls=v1.qualifiers.P2096 fork2,v2inpairs(imglbls)do ifv2.datavalue.value.language==langthen imglbl=v2.datavalue.value.text break end end end end -- if we don't find one, look for an image with 'normal' rank if(notimglbl)then fork1,v1inpairs(imgs)do ifv1.rank=="normal"andv1.qualifiersandv1.qualifiers.P2096then localimglbls=v1.qualifiers.P2096 fork2,v2inpairs(imglbls)do ifv2.datavalue.value.language==langthen imglbl=v2.datavalue.value.text break end end end end end end returnimglbl else returninput_parm end end -- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata functionp.pageId(frame) returnmw.wikibase.getEntityIdForCurrentPage() end returnp