Modulu:Wikidata

Wikipedia, Entziklopedia askea
Hona jauzi: nabigazioa, Bilatu
Moduluaren dokumentazio ikonoa Moduluaren dokumentazioa[ikusi] [Modulu:Wikidata/dok] [Modulu:Wikidata/dok] [Birkargatu]

Hemen erakusten dena /dok azpiorrialdeko dokumentazioa da. [kodearen kutxara saltatu]


Modulu honek Wikidatatik datuak ateratzen ditu eta formatua ematen die.

Oinarrizko funtzioak

  • claim: Adierazpen baten balioa (edo balioak) edo adierazpen baten kualifikadorea ematen du, aurrez esandako formatuan. Defektuz txertatuta dagoen artikuluaren itema bilatzen du (Qnnnn).

Beste funtzio batzuk:

  • getParentValues: propietate baten emaitzak eta etiketak ematen ditu, gorantz, era errekurtsiboan.
  • getTAValue: TA98 (Terminologia Anatomicaren lehen edizioa, 1998) emaitza ematen du P1323 propietatean. Ez ditu parametroak eskaintzen baina zerrenda bat ematen du kanpo-loturen formatu egokiarekin.
  • ViewSomething: datu egituratuetako edozein gauza itzultzen du, etiketak, deskribapenak, erreferentziak edo interwiki loturak barne.
  • years_old: pertsona baten adina itzultzen du: jaiotza data (p569) eta heriotza data (p570) arteko diferentzia eginez, edo ez badago P570 propietaterik, gaurko egunaren eta jaiotza data (p569) arteko aldea kalkulatzen du. Datuen prezisioaren arabera zifra bat edo bi ematen ditu. Bi datuetako bat mendeen arabera zehaztuta dagoenean ez du emaitzarik ematen.
    • Honako sintaxia erabiltzen du: {{#invoke:Wikidata |formatting=''tipus pattern'' |item= }}. item eta formatting hautazkoak dira. Formatu adibide bat izango litzateke ($1 urte)
Sintaxi osoa
{{#invoke:Wikidata|claim|property= |qualifier= |value= |list= |tablesort= |formatting= |separator= |conjunction= |item= |showerrors= |default= }}
Taula formatua emateko sintaxi osagarria
{{#invoke:Wikidata|claim|property= |qualifier= |qualifier2= |...|qualifier9= |tablesort= |rowformat= |rowsubformat1= |...|rowsubformat9= |formatting=table |separator= |conjunction= |item= |showerrors= |default= }}
Claim funtzioaren parametroak
  • property= (beharrezkoa) Adierazpenaren propietatea, "P" eta zenbaki bat emanez. Wikidatako propietate guztien zerrenda ikusteko Propietateen zerrenda ikusi. Letra txikiz ere idatzi daiteke p, baina ez da gomendatzen. Propietatearen etiketa ere sar daiteke, adibidez property=herrialdea jartzen badugu property=P17 batean herrialdea (P17) jartzea bezalakoa da.
  • qualifier= (aukeran) Kualifikatzailearen propietatea, "P" bat eta, jarraian, zenbaki bat. Wikidatako elementuan lotura agertzen da. p txikia ere sar daiteke, baina ez da formatu lehenetsia.
  • value= (aukeran) Wikidatako balore preferentea. Izan daiteke txantiloian erabiltzen den parametro bat, {{{parametro|}}} formatoarekin. Horrela parametro horren balioa hartzen du eta, ez balego, Wikidatako balioa.
  • list= (aukeran). Defektuz list=true hartzen du eta itemak dituen adierazpen eta kualifikatzaile guztiak ematen dizkigu (ikus separator eta conjuction).
    • list=false Balio bakarra ematen digu, mailarik altuena duena preferente/arrunta/obsolotoa mailaketaren arabera, edo mailarik altuena duenetik zaharrena.
    • list=firstrank Mailarik altuena duten baloreen zerrenda egiten du. list=true bezalakoa da adierazpen guztien maila berdina baldin bada.
    • tablesort=0 (aukeran) zerrendaren antolaketa gorantz egitea. Defektuz antolaketa mailaren arabera eta Wikidatako adierazpenaren antzinakotasunaren arabera ematen da.
  • formatting= (aukeran) Nahi dugun formatua. Honako baloreak eman dakioke:
    • Elementuaren formatua (entity):
      • formatting=raw Elementuaren zenbakia emango digu.
      • formatting=label Elementuaren etiketa emango digu.
      • formatting=sitelink Elementuaren Wikipediako orrialdearen izenburua emango digu.
      • formatting=internallink Barne lotura posible baldin bda, izan Wikipediako loturarekin (sitelink) edo etiketarekin. Ez badago Wikipediako loturarik baina etiketaren bat baldin badago, defektuz Wikidatako lotura bat emango digu, gorriz. Etiketarik ez balego, ingelerazko etiketa hartzen du defektuz.
      • formatting=pattern Patroi baten araberako formatua, $1 erabiltzen aldatu behar den elementu gisa.
      Txantiloiak edo parser funtzioak sar daitezke honako formatua erabilita: {{((}}txantiloia{{!}}parametroa{{!}}izena{{=}}parametroa{{))}}
      Defektuz ematen den formatua lotura batena izango da.
    • Testu formatua (string):
      • formatting=weblink Kanpo lotura formatua [http://example.com example.com]
      • formatting=pattern $1 patroia erabiltzen du aldatu behar den parametro gisa. Adibidez: formatting=[http://whc.unesco.org/en/list/$1 $1]. Wikidatak lotura sortzen duen propietate motatan erabiltzen da, eta patro egokia propietatearen eztabaida orrialdean aurki daiteke.
    • Zenbaki formatua (quantity):
      • formatting=unit Zenbaki formatua, unitatea barne.
      • formatting=unitcode Zenbaki formatua, unitatearen laburdura jarriz, Modulu:Wikidata/Units moduluan zehazten duenaren arabra.
    • Formatu eleanitza (monolingualtext):
      • formatting=language Parametroaren balioa lortu nahi dugun hizkuntza kodea, monolingual text formatua duten parametroetarako, hala nola izen ofiziala (P1448).
      • formatting=text monolingual text formatua duten propietateetarako bertsio berezi bat da, bakar-bakarrik testua eskuratuz, formatting gabe eksatzen badugu hizkuntzaren kodea jasotzen baitu <span lang="en">United...</span>.
      • formatting=eu edo beste hizkuntza bateko balioa. Balio bakarra ematen du, kasu honetan monolingual text balio ezberdinen katalanezko bertsioa. Adibidez: etiketaren forma femeninoa (P2521).
    • Koordenatuen formatua (globecoordinate):
      • formatting=latitude Koordenatu adierazpen baten latitudea, formatu dezimalean
      • formatting=longitude Koordenatu adierazpen baten luzera, formatu dezimalean
      • formatting=dimension Koordenatu adierazpen baten dimentsioaren balioa, metrotan, koordenatuen mapentzako dim parametroa emateko.
      • formatting=globe (defektuz) {{koord}} txantiloiko globe parametroa ematen du, Lurretik kanpoko koordenaturen bat beharko balitz, erabiltzeko. Datuak [[Modulu:

Valor del paràmetre globe de la plantilla:coord, necessari per coordenades fora de la Terra. Les dades estan definides al Modulu:Gorputz zeleste/datuak moduluan zehaztu beharko lirateke (EGITEKE).

    • Daten formatua (time):
      • formatting= format #time [mw:Help:Extension:ParserFunctions/ca#.23time|#time analizadorarearen]] edozein formatu onartzen du. Adibidez formatting=d-m-Y (18-10-2017), formatting=[[j xg]] (18 Urri), formatting=Y (2017). Defektuz "j F Y" (18 urria 2017) erabiltzen du.
    • Propietate eta kualifikatzaileen taula formatua:
      • formatting=table Propietate zerrenda bat ematen du, taula formatuan, bere kualifikatzaileekin. 9 kualifikatzaile arte eman daitezke, eta formatuan bakoitza lerro batean sar dezake. Berez erabiltzen dituen bereizleak separator eta conjunction parametroetakoak dira. Formatu honek ematen dituen aukerak anitzak dira:
        • qualifier2 ... qualifier9= Lehen qualifier baino gehiago behar baditugu
        • rowformat= Propietate eta kualifikadoreen lerro bakoitzaren formatua. Propietatea $0 erabilita markatzen da, eta kualifikatzaileak $1etik $9ra. Defektuz rowformat=$0 ($1, ... $9) da formatua. Erabili daitezke zerrenda markak, * edo # baita txantiloiak ere {{((}}, {{!}} eta }} erabilita bereizketak egiteko.
        • rowsubformat1 ... rowsubformat9= $1-$9 arteko balioei emateko formatua definitzeko. Izan daiteke oso erabilgarria kualifikatzaile bat hutsik egonez gero. Adibidez, "rowformat=$0 $1" eta "rowsubformat1=zein $1" jarrita "$0 zein $1" jasoko dugu edo "$0" kualifikatzailerik ez balego.
        • colformat0 ... colformat9= Formatua ematen dio zutabe bakoitzari, 0 propietateari eta 1-9 artean kualifikadoreei. formatting balioak erabli daitezke zutabe bakoitzerako. Honela zutabe bati formatu zehatz bat eman ahal zaio.
        • tablesort= 0 eta 9 arteko balioekin, propietate eta kualifikatzaileen arabera antolatzen du taula. Defektuz propietatearen mailaren arabera antolatuko du, edo Wikidatako definizioaren antzinakotasunaren arabera.
        • sorting=-1 ordena aldatzen du, atzekoz aurrera egiten. Defektuz goranzkoa da.
  • separator= (aukeran) zerrendan edo taulan erabiltzeko bereizlea. Defektuz komaz bereizten da, euskaraz , erabilita. Tauletan defektuz lerro haustura bat egiten du: <br />.
  • conjunction= (aukeran) Zerrenda bateko azken bi elementuen artean erabiltzeko konjuntzioa. Defektuz eta erabiltzen du. Tauletan <br /> erabiltzen du.
  • case= (aukeran) Sortu behar den kasu gramatikala. Definitutako kasuak:
    • case=singularra, hitz baten forma singularra ekartzen du, adibidez irakasle -> irakaslea
    • case=ergatiboa, hitz baten edo zerrenda baten forma ergatiboa ekartzen du, adibidez Stanley Kubrick -> Stanley Kubrickek
    • case=genitiboa, hitz baten edo zerrenda baten forma genitiboa ekartzen du, adibidez Mikel Laboa -> Mikel Laboaren
  • item= (aukerakoa) Erabiltzen ari garen artikulua ez den beste item bat zehazteko balio du, eta (Qnnnn) formatuan eman behar da. Moderazioz erabili, arren, errekurtso ugari erabiltzen baititu.
  • itemgender= (aukerakoa) Elementuaren forma femenikoa aurkitzen da, sexua edo generoa (P21) erabilita, defektuz item erabilita. case=gender eta case=infoboxlabel batera erabiltzen da.
  • showerrors= (aukeran) Errore mezuak ematen ditu.
  • default= (aukeran) Akatsik balego eman beharreko mezua. Ez du efekturik showerrors jartzen badugu.
getParentValues funtzioaren parametroak
  • item= (aukeran) Item bat (Qnnnnn) zehaztea baimentzen du. Wikidatarako sarbide arbitrario hau ez da gomendagarria, baliabide asko behar baititu.
  • property= (aukeran) Adierazpenaren propietatea, "P" eta zenbaki baten formatuan. Defektuz honako erakunde administratiboan dago (P131) izango da.
  • label= (aukeran) Etiketaren propietatea. Defektuz honako hau da (P31) izango da.
  • valuetext= (aukeran) Balioaren loturaren testuaren propietatea. Defektuz formatting=internallink emango du.
  • upto= (aukerak) Noraino iritsi nahi dugun kontsultzen zuhaitzan, propietaterik aurkitzen duen bitartean. Balio motak
    • upto=etiketa: gelditu behar den etiketa, adibidez "upto=herrialdea".
    • upto=zenbakia: lortu nahi diren balio kopurua. Defektuz 10 datoz, babes gisa, baina normalki ez dira hainbeste behar izango.
  • labelshow= (aukeran) Erakutsi nahi diren etiketen iragazkia, barar batekin bereiztua bat baino gehiago baidra. Adibidez "labelshow=udalerria/eskualdea"
  • sorting= (aukeran) Zerrendan ordena. Balio posible bakarra du, "sorting=-1", berezkoaren alderantziko ordena erakusteko.
  • rowformat= (aukeran) balio bikote bakoitza antolatzeko modua, $0 etiketarako eta $1 baliorako. Defektuz "rowformat=$0 = $1" erabili da, adibidez "eskualdea = [[Iruñerria]]" erakutsiz.
  • separator= (aukeran) Balio bikote bakoitzarentzat nahi dugun bereizlea. Defektuz <br /> da. Ez da konjuntziorik behar bereizleentzat, kasu honetan.

Oharra: Etiketak aldatu daitezke formatu hobe batekin infotaulatan erabiltzeko. Adibidez, "Brasilgo udalerria"ren ordez "Udalerria" ikusiko dugu. Hau guztia Modulu:Wikidata/labels moduluan zehazten da, bertan jarriz behar ditugun aldaketak.

Adibideak
  • Erabiler sinplea:
{{#invoke:Wikidata | claim |property=P20}} Jean-François Champollion artikuluan honako emaitza emango du: Paris
heriotza lekua (P20) propietatea da, elementua erakutsiz.
  • Loturarik gabe:
{{#invoke:Wikidata | claim | property=P20 | formatting=label}}: Paris
  • Balio lehenetsia
{{#invoke:Wikidata | claim | property=P20 | value={{{heriotza lekua|}}} }} infotaulan {{{heriotza lekua|}}} definitu badugu agertuko da, bestela Paris jarriko du.
  • Data modukoa:
{{#invoke:Wikidata | claim | property=P569}} jaitza data ematen du berezko formatuan:
1790eko abenduak 23
  • Patroi batekin emandako datuak:
{{#invoke:Wikidata | claim | property=P214 | formatting=[http://viaf.org/viaf/$1 $1]}}:
34454460
  • Balio bakarra:
Adibide irudia
{{#invoke:Wikidata | claim | property=P18 | list=false | formatting=[[File:$1|thumb|upright=.5|Adibide irudia]]}}
Definitu den lehen irudia baino ez du emango.
  • Kanpo loturaren formatua:
{{#invoke:Wikidata | claim | property=P856 | formatting=weblink}} Berlin artikuluan:
https://www.berlin.de/
  • Balio zerrenda:
mugakidea(k) (P47) {{#invoke:Wikidata | claim | property=P47}} Bilbo artikuluan
Alonsotegi, Arrigorriaga, Barakaldo, Basauri, Erandio, Galdakao, Sondika, Zamudio, Derio eta Etxebarri
  • Formatudun zerrenda
osatuta (P527) {{#invoke:Wikidata | claim | property=P527 | separator=<br /> | conjunction=<br />}} Euskal Herrian:
Araba
Bizkaia
Gipuzkoa
Nafarroako Foru Erkidegoa
Lapurdi
Nafarroa Beherea
Zuberoa
Trebiñu
  • Koordenatuak:
{{#invoke:Wikidata | claim | property=P625 | formatting=latitude}}: 43.262222222222
{{#invoke:Wikidata | claim | property=P625 | formatting=longitude}}: -2.9533333333333

Ikus, gainera


Dokumentazio hau Modulu:Wikidata/dok orrialdetik txertatua dago.
Mesedez, sar itzazu kategoriak dokumentazio azpiorrialdean eta interwiki loturak Wikidatan. Modulu honen azpiorrialdeak.
-- Master version: [[:ca:Module:Wikidata]]
-- compatible version: 20171012

local p = {}

local wiki = 
{
	langcode = mw.language.getContentLanguage().code
}

-----------------------------------------------------------------------------
-- internationalisation at [[Module:Wikidata/i18n]]
local i18n = {
	["errors"] = {
		["property-not-found"] = "Property not found.",
		["entity-not-found"] = "Wikidata entity not found.",
		["unknown-claim-type"] = "Unknown claim type.",
		["unknown-entity-type"] = "Unknown entity type.",
		["qualifier-not-found"] = "Qualifier not found.",
		["site-not-found"] = "Wikimedia project not found.",
		["unknown-datetime-format"] = "Unknown datetime format.",
		["local-article-not-found"] = "Article is not yet available in this wiki.",
		['not-from-content-page'] = "Do not invoke from content page. Use a template or use a module subpage like /sandbox for testing."
	},
	["datetime"] =
	{
		-- $1 is a placeholder for the actual number
		[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] = "$100,000 years",		-- precision: hundred thousand years
		[5] = "$10,000 years",		-- precision: ten thousand years
		[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
		[12] = "F j, Y ga",			-- precision: hour
		[13] = "F j, Y g:ia",		-- precision: minute
		[14] = "F j, Y g:i:sa",		-- precision: second
		
		["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 positive years
		["bc-addon"] = " BC",		-- suffix for negative dates
		["ad-addon"] = ""			-- suffix for 1st century AD dates
	},
	["monolingualtext"] = '<span lang="%language">%text</span>',
	["warnDump"] = "[[Category:Called function 'Dump' from module Wikidata]]"
}

local function track(key)
	local frame = mw.getCurrentFrame()
	pcall(frame.expandTemplate, frame, { title = 'track/' .. key })
end

local cases = {} -- functions for local grammatical cases defined at [[Module:Wikidata/i18n]]

----------------------------------------------------------------------------
-- module local functions

-- Credit to http://stackoverflow.com/a/1283608/2644759
-- cc-by-sa 3.0
local function tableMerge(t1, t2)
	for k,v in pairs(t2) do
		if type(v) == "table" then
			if type(t1[k] or false) == "table" then
				tableMerge(t1[k] or {}, t2[k] or {})
			else
				t1[k] = v
			end
		else
			t1[k] = v
		end
	end
	return t1
end

local function loadI18n()
	local exist, res = pcall(require, "Module:Wikidata/i18n")
	if exist and next(res) ~= nil then
		tableMerge(i18n, res.i18n)
		cases = res.cases
	end
end

loadI18n()

local function case(word, localcase)
	if word == nil or word == '' or cases[localcase] == nil then
		return word
	end
	
	return cases[localcase](word)
end

local function expandBraces(text)
	if text == nil then return text end
	if type(text) ~= "string" then
		text = tostring(text)
	end
	
	for braces in mw.ustring.gmatch(text, "{{(.-)}}") do
		local parts = mw.text.split(braces, "|")
		local title = parts[1]
		local parameters = {}
		for i = 2, #parts do
			if mw.ustring.find(parts[i], "=") then
				local subparts = mw.text.split(parts[i], "=")
				parameters[subparts[1]] = subparts[2]
			else
				table.insert(parameters, parts[i])
			end
		end
		
		local braces_expanded
		if mw.ustring.find(title, ":") then
			braces_expanded = mw.getCurrentFrame():callParserFunction{name=title, args=parameters}
		else
			braces_expanded = mw.getCurrentFrame():expandTemplate{title=title, args=parameters}
		end
		title = mw.ustring.gsub(title, "([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") -- escape magic characters
		text = mw.ustring.gsub(text, "{{" .. title .. ".-}}", braces_expanded)
	end
	
	return text
end

local function printDatavalueString(data, parameters)
	if parameter == 'weblink' then 
		return '[' .. data ..  ' ' ..  mw.text.split(data, '//' )[2] .. ']'
	elseif mw.ustring.find((parameters.formatting or ''), '$1', 1, true) then -- formatting = a pattern
		return expandBraces(mw.ustring.gsub(parameters.formatting, '$1', data))
	elseif parameters.case then
		return case(data, parameters.case)
	else
		return data
	end
end

local function printDatavalueCoordinate(data, parameter)
	if parameter == 'latitude' then
		return data.latitude
	elseif parameter == 'longitude' then
		return data.longitude
	elseif parameter == 'dimension' then
		return data.dimension
	else --default formatting='globe'
		if data.globe == '' or data.globe == nil or data.globe == 'http://www.wikidata.org/entity/Q2' then
			return 'earth'
		else
			local globenum = mw.text.split(data.globe, 'entity/')[2] -- http://www.wikidata.org/wiki/Q2
			local globetable = {Q3134 = 'callisto', Q596 = 'ceres', Q15040 = 'dione', Q3303 = 'enceladus',
				Q3143 = 'europa', Q17975 = 'phoebe', Q3169 = 'ganymede', Q3123 = 'io', Q17958 = 'iapetus',
				Q405 = 'moon', Q111 = 'mars', Q308 = 'mercury', Q15034 = 'mimas', Q15050 = 'rhea',
				Q15047 = 'tethys', Q2565 = 'titan', Q3359 = 'triton', Q313 = 'venus', Q3030 = 'vesta'}
			if globetable[globenum] then 
				return globetable[globenum]
			else
				return globenum
			end
		end
	end
end

local function printDatavalueQuantity(data, parameter)
	-- exemples: 277±1 Centímetre, 1,94 metre
	local amount = data.amount
	amount = mw.ustring.gsub(amount, "%+", "")
	local sortkey = string.format("%09d", amount)
	local lang = mw.language.new(wiki.langcode)
	amount = lang:formatNum(tonumber(amount))
	-- This is used to get the unit name for a numeric value
	local suffix = ""
	if parameter == "unit" or parameter == "unitcode" then
		-- get the url for the unit entry on Wikidata:
		local unitID = data.unit
		-- and just return the last bit from "Q" to the end (which is the QID):
		unitID = mw.ustring.sub(unitID, mw.ustring.find(unitID, "Q"), -1)
		if mw.ustring.sub(unitID, 1, 1) == "Q" then
			local unit_label = mw.wikibase.label(unitID)
			suffix = " " .. require("Module:Wikidata/Units").getUnit(amount, unit_label, unitID, parameter == "unitcode")
		end
	end
	return amount .. suffix, sortkey
end

local function printDatavalueTime(data, parameter)
	-- Dates and times are stored in ISO 8601 format
	local timestamp = data.time
	local sortkey = timestamp
	local addon = ""
	
	-- check for negative date, ex. "-0027-01-16T00:00:00Z"
	if string.sub(timestamp, 1, 1) == '-' then
		timestamp = '+' .. string.sub(timestamp, 2)
		addon = i18n.datetime["bc-addon"]
	elseif string.sub(timestamp, 2, 3) == '00' then
		addon = i18n.datetime["ad-addon"]
	end
	local function d(f, t)
		return mw.language.new(wiki.langcode):formatDate(f, t or timestamp) .. addon
	end
	local precision = data.precision or 11
	local intyear = tonumber(mw.ustring.match(timestamp, "^\+?%d+"))
	local ret = ""
	
	-- precision is 10000 years or more
	if precision <= 5 then
		local factor = 10 ^ ((5 - precision) + 4)
		local y2 = math.ceil(math.abs(intyear) / factor)
		local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
		if addon == i18n.datetime["bc-addon"] then
			-- negative date
			ret = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
		else
			ret = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
		end
	-- precision is millennia, centuries or decades
	elseif precision == 6 then
		local card = math.floor((intyear - 1) / 1000) + 1
		if mw.ustring.find(i18n.datetime[6], "$1") then
			ret = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(card)) .. addon
		else
			ret = d(i18n.datetime[6], string.format("%04d", tostring(card)))
		end
	elseif precision == 7 then
		local card = math.floor((math.abs(intyear) - 1) / 100) + 1
		if mw.ustring.find(i18n.datetime[7], "$1") then
			ret = mw.ustring.gsub(i18n.datetime[7], "$1", tostring(card)) .. addon
		else
			ret = d(i18n.datetime[7], string.format("%04d", tostring(card)))
		end
	elseif precision == 8 then
		local card = math.floor(math.abs(intyear) / 10) * 10
		ret = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(card)) .. addon
	-- precision is year
	elseif parameter == 'Y' or precision == 9 then
		ret = tostring(intyear) .. addon
	-- precision is month
	elseif precision == 10 then
		timestamp = timestamp .. " + 1 day" -- formatDate yyyy-mm-00 returns the previous month
		ret, _ = string.gsub(d(i18n.datetime[10]), " 0+", " ") -- supress leading zeros in year
	elseif parameter then
		ret, _ = string.gsub(d(parameter), "([ %[])0+", "%1") -- supress leading zeros in year optionally linked
	else
		-- ret, _ = string.gsub(d(i18n.datetime[11]), " 0+", " ")
		-- TODO: move localized function to /i18n
		ret = require("Module:Date").genitive_year(intyear) .. d(' F"k" j')
	end
	return ret, sortkey
end

local function printDatavalueEntity(data, parameters)
	local entityId = "Q" .. tostring(data['numeric-id'])
	local label = mw.wikibase.label(entityId)
	local sitelink = mw.wikibase.sitelink(entityId)
	local parameter = parameters.formatting
	local labelcase = label or sitelink
	if parameters.case then
		labelcase = case(labelcase, parameters.case)
	end
	local ret1, ret2
	if parameter == 'raw' then 
		ret1 = entityId
		ret2 = entityId
	elseif parameter == 'label' then
		ret1 = labelcase or entityId
		ret2 = labelcase or entityId
	elseif parameter == 'sitelink' then
		ret1 = (sitelink or 'wikidata:' .. entityId)
		ret2 = sitelink or entityId
	elseif mw.ustring.find((parameter or ''), '$1', 1, true) then -- formatting = a pattern
		ret1 = mw.ustring.gsub(parameter, '$1', labelcase or entityId)
		ret1 = expandBraces(ret1)
		ret2 = labelcase or entityId
	else
		if parameter == "ucfirst" then
			labelcase = labelcase and mw.language.getContentLanguage():ucfirst(labelcase)
			parameters.formatting = 'internallink' -- only once in a list
		end
		
		if sitelink then
			ret1 = '[[' .. sitelink .. '|' .. labelcase .. ']]'
			ret2 = labelcase
		elseif label and parameter == 'internallink' or parameter == 'ucfirst' then
			ret1 = '[[' .. label .. '|' .. labelcase .. ']]'
			ret2 = labelcase
		else
			ret1 = '[[wikidata:' .. entityId .. '|' .. (labelcase or entityId) .. ']]'
			ret2 = labelcase or entityId
		end
	end
	
	return ret1, ret2
end

local function printDatavalueMonolingualText(data, parameter)
	-- data fields: language [string], text [string]
	local result = nil
	if parameter == "language" or parameter == "text" then
		result = data[parameter]
	elseif parameter then
		if data["language"] == wiki.langcode then
			result = data["text"]
		end
	else
		result = mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, "%%language", data["language"]), "%%text", data["text"])
	end
	return result
end

local function printDatatypeMath(data)
	return mw.getCurrentFrame():callParserFunction('#tag:math', data)
end

local function printError(key)
    return '<span class="error">' .. i18n.errors[key] .. '</span>'
end

local function findClaims(entity, property)
	if not property or not entity or not entity.claims then return end
	
	if not mw.ustring.match(property, "^P%d+$") then
		-- get property id for the given label
		property = mw.wikibase.resolvePropertyId(property)
	end
	
	return entity.claims[property]
end

local function getSnakValue(snak, parameters)
	local parameter = parameters.formatting
	if snak.snaktype == 'value' then
		-- call the respective snak parser
		if snak.datatype == 'math' then
			return printDatatypeMath(snak.datavalue.value)
		elseif snak.datavalue.type == "string" then
			return printDatavalueString(snak.datavalue.value, parameters)
		elseif snak.datavalue.type == "globecoordinate" then
			return printDatavalueCoordinate(snak.datavalue.value, parameter)
		elseif snak.datavalue.type == "quantity" then
			return printDatavalueQuantity(snak.datavalue.value, parameter)
		elseif snak.datavalue.type == "time" then
			return printDatavalueTime(snak.datavalue.value, parameter)
		elseif snak.datavalue.type == 'wikibase-entityid' then
			return printDatavalueEntity(snak.datavalue.value, parameters)
		elseif snak.datavalue.type == 'monolingualtext' then
			return printDatavalueMonolingualText(snak.datavalue.value, parameter)
		end
	end
	return mw.wikibase.renderSnak(snak)
end

local function getQualifierSnak(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
	if qualifierId then
		-- search the attribute snak with the given qualifier as key
		if claim.qualifiers then
			local qualifier = claim.qualifiers[qualifierId]
			if qualifier then
				-- iterate over monolingualtext qualifiers to get local language
				for idx in pairs(qualifier) do
					if qualifier[idx].datavalue and qualifier[idx].datavalue.value and qualifier[idx].datavalue.value.language then
						if qualifier[idx].datavalue.value.language == wiki.langcode then
							return qualifier[idx]
						end
					end
				end
				if parameters.list then
					return qualifier
				else
					return qualifier[1]
				end
			end
		end
		return nil, printError("qualifier-not-found")
	else
		-- otherwise return the main snak
		return claim.mainsnak
	end
end

local function getValueOfClaim(claim, qualifierId, parameters)
	local error
	local snak
	snak, error = getQualifierSnak(claim, qualifierId, parameters)
	if not snak then
		return nil, nil, error
	elseif snak[1] then -- a multi qualifier
		local result = {}
		local sortkey = {}
		for idx in pairs(snak) do
			result[#result + 1], sortkey[#sortkey + 1] = getSnakValue(snak[idx], parameters)
		end
		return mw.text.listToText(result, parameters.qseparator, parameters.qconjunction), sortkey[1]
	else -- a property or a qualifier
		return getSnakValue(snak, parameters)
	end
end

-- Return the site link (for the current site) for a given data item.
function p.getSiteLink(frame)
    if frame.args[1] == nil then
        entity = mw.wikibase.getEntityObject()
        if not entity then
        	return nil
        end
        id = entity.id
    else
        id = frame.args[1]
    end
 
    return mw.wikibase.sitelink(id)
end

-- On debug console use: =p._debug({item="Q...", property="P...", ...})
function p._debug(args)
	return p._main(args)
end

function p.claim(frame)
	--if mw.title.new(frame:getParent():getTitle()).isContentPage and not mw.title.new(frame:getTitle()).isSubpage then
	--	-- invoked from a content page and not invoking a module subpage
	--	return printError("not-from-content-page")
	--end
	return p._main(frame.args)
end

function p._main(args)
	--If a value is already set, use it
	if args.value and args.value ~= '' then
		return args.value
	end
	
	-- arguments
	local property = args["property"] or ""
	local id = args["item"]; if id == "" then id = nil end
	local idgender = args["itemgender"]
	if idgender and not string.match(idgender, "^Q%d+$") then -- id malformed, maybe "unknown value"
		idgender = nil
	end
	local qualifierId = {}
	qualifierId[1] = args["qualifier"]
	for i = 2, 9 do
		qualifierId[i] = args["qualifier" .. i]
	end
	local parameter = args["formatting"] or ''; if parameter == "" then parameter = nil end
	local case = args.case
	local list = args["list"] or true; if list == "false" then list = false end
	local sorting_col = args.tablesort
	local sorting_up = (args.sorting or "") ~= "-1"
	local separator = args.separator
	local conjunction = args.conjunction or args.separator
	local rowformat = args.rowformat
	local showerrors = args["showerrors"]
	local default = args["default"]
	
	property = property:gsub("^p(%d)", "P%1")
	if qualifierId[1] then qualifierId[1] = qualifierId[1]:gsub("^p(%d)", "P%1") end
	if args["rank"] and args["rank"] ~= '' then list = false end -- compatibilitat de transició
	if args["rank"] then track("wikidata/rank") end
	local parameters = {["formatting"] = parameter, ["list"] = list, ["case"] = case,
		["separator"] = separator, ["conjunction"] = conjunction, ["qseparator"] = separator, ["qconjunction"] = conjunction}
	local preformat = ""
	local postformat = ""
	if parameters.formatting == "table" then
		parameters.separator = parameters.separator or "<br />"
		parameters.conjunction = parameters.conjunction or "<br />"
		parameters.qseparator = ", "
		parameters.qconjunction = ", "
		if not rowformat then
			rowformat = "$0 ($1"
			for i = 2, 9 do
				if qualifierId[i] then
					rowformat = rowformat .. ", $" .. i
				end
			end
			rowformat = rowformat .. ")"
		elseif mw.ustring.find(rowformat, "^[*#]") then
			parameters.separator = "</li><li>"
			parameters.conjunction = "</li><li>"
			if mw.ustring.match(rowformat, "^[*#]") == "*" then
				preformat = "<ul><li>"
				postformat = "</li></ul>"
			else
				preformat = "<ol><li>"
				postformat = "</li></ol>"
			end
			rowformat = mw.ustring.gsub(rowformat, "^[*#] ?", "")
		end
	end
	if default then showerrors = nil end
	
	-- get wikidata entity
	local entity = mw.wikibase.getEntityObject(id)
	if not entity then
		if showerrors then return printError("entity-not-found") else return default end
	end
	-- fetch the first claim of satisfying the given property
	local claims = findClaims(entity, property)
	if not claims or not claims[1] then
		if showerrors then return printError("property-not-found") else return default end
	end
	
	-- find feminine case if gender is requested
	local genderCase
	if parameters.case == "gender" or idgender or parameters.formatting == "table" then
		local genderEntity = idgender and mw.wikibase.getEntityObject(idgender) or entity
		local genderClaims = genderEntity.claims["P21"]
		if genderClaims then
			local genderId = getValueOfClaim(genderClaims[1], nil, {["formatting"]="raw"})
			if genderId == "Q6581072" or genderId == "Q1052281" or genderId == "Q43445" then -- female, transgender female, female organism
				genderCase = (parameters.case == "infoboxlabel") and "labelfeminine" or "feminine"
				if parameters.case == "gender" or idgender then
					parameters.case = genderCase
				end
			end
		end
	end
	
	-- get initial sort indices
	local sortindices = {}
	for idx in pairs(claims) do
		sortindices[#sortindices + 1] = idx
	end
	-- sort by claim rank
	local comparator = function(a, b)
		local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
		local ranka = rankmap[claims[a].rank or "normal"] ..  string.format("%08d", a)
		local rankb = rankmap[claims[b].rank or "normal"] ..  string.format("%08d", b)
		return ranka < rankb
	end
	table.sort(sortindices, comparator)
	
	local result
	local error
	if parameters.list or parameters.formatting == "table" then
		-- convert LF to line feed, <br /> may not work on some cases
		parameters.separator = parameters.separator == "LF" and "\010" or parameters.separator
		parameters.conjunction = parameters.conjunction == "LF" and "\010" or parameters.conjunction
		-- iterate over all elements and return their value (if existing)
		local value, valueq
		local sortkey, sortkeyq
		local values = {}
		local sortkeys = {}
		local firstrank = parameters.list == "firstrank" and claims[sortindices[1]].rank or ''
		for idx in pairs(claims) do
			local claim = claims[sortindices[idx]]
			if firstrank ~= '' and firstrank ~= claim.rank then
				break
			end
			values[#values + 1] = {}
			sortkeys[#sortkeys + 1] = {}
			if parameters.formatting == "table" then
				local params = mw.clone(parameters)
				params.formatting = args["colformat0"]
				if args["case0"] then
					params.case = args["case0"] == "gender" and genderCase or args["case0"]
				end
				value, sortkey, error =  getValueOfClaim(claim, nil, params)
				for i, qual in ipairs(qualifierId) do
					params.formatting = args["colformat" .. i]
					if args["case" .. i] then
						params.case = args["case" .. i] == "gender" and genderCase or args["case" .. i]
					else
						params.case = parameters.case
					end
					valueq, sortkeyq, _ =  getValueOfClaim(claim, qual, params)
					values[#values]["col" .. i] = valueq
					sortkeys[#sortkeys]["col" .. i] = sortkeyq or valueq
				end
			else
				value, sortkey, error =  getValueOfClaim(claim, qualifierId[1], parameters)
			end
			if not value and showerrors then value = error end
			
			values[#values]["col0"] = value
			sortkeys[#sortkeys]["col0"] = sortkey or value
		end
		-- sort and format results
		sortindices = {}
		for idx in pairs(values) do
			sortindices[#sortindices + 1] = idx
		end
		if sorting_col then
			local comparator = function(a, b)
				local valuea = sortkeys[a]["col" .. sorting_col] or ''
				local valueb = sortkeys[b]["col" .. sorting_col] or ''
				if sorting_up then
					return valuea < valueb
				end
				return valuea > valueb
			end
			table.sort(sortindices, comparator)
		end
		result = {}
		for idx in pairs(values) do
			local valuerow = values[sortindices[idx]]
			value = valuerow["col0"]
			if parameters.formatting == "table" then
				value = mw.ustring.gsub(rowformat, "$0", value)
				for i, _ in ipairs(qualifierId) do
					valueq = valuerow["col" .. i]
					if args["rowsubformat" .. i] and valueq then
						valueq = mw.ustring.gsub(args["rowsubformat" .. i], "$" .. i, valueq)
					end
					value = mw.ustring.gsub(value, "$" .. i, valueq or '')
				end
			end
			value = expandBraces(value)
			result[#result + 1] = value
		end
		result = preformat .. mw.text.listToText(result, parameters.separator, parameters.conjunction) .. postformat
	else
		-- return first element	
		local claim = claims[sortindices[1]]
		result, _, error = getValueOfClaim(claim, qualifierId[1], parameters)
	end
	
	if result then return result else
		if showerrors then return error else return default end
	end
end

-- Return the statements with a format
function p.formatStatements(frame)
	track("wikidata/formatStatements")
	return p.claim(frame) -- compatibilitat de transició
end

-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
-- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm
-- uses the newer mw.wikibase calls instead of directly using the snaks
-- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string
p.getTAValue = function(frame)
    local ent = mw.wikibase.getEntityObject()
    local props = ent:formatPropertyValues('P1323')
    local out = {}
    local t = {}
    for k, v in pairs(props) do
        if k == 'value' then
            t = mw.text.split( v, ", ")
            for k2, v2 in pairs(t) do
                out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]"
            end
        end
    end
    local ret = table.concat(out, "<br> ")
    if #ret == 0 then
        ret = "Invalid TA"
    end
    return ret
end

-- look into entity object
function p.ViewSomething(frame)
	local f = (frame.args[1] or frame.args.item) and frame or frame:getParent()
	local id = f.args.item
	if id and (#id == 0) then
		id = nil
	end
	local data = mw.wikibase.getEntityObject(id)
	if not data then
		return nil
	end

	local i = 1
	while true do
		local index = f.args[i]
		if not index then
			if type(data) == "table" then
				return frame:extensionTag('syntaxhighlight', mw.text.jsonEncode(data, mw.text.JSON_PRETTY), {lang = 'json'})
			else
				return tostring(data)
			end
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return
		end
		
		i = i + 1
	end
end

-- Dump data tree structure
-- From pl:Module:Wikidane, by User:Paweł Ziemian
-- Funció pensada com a eina d'ajuda en previsualització.
function p.Dump(frame)
	local data = mw.wikibase.getEntityObject()
	if not data then
		return i18n.warnDump
	end
	
	local f = frame.args[1] and frame or frame:getParent()

	local i = 1
	while true do
		local index = f.args[i]
		if not index then
			return frame:extensionTag('syntaxhighlight', mw.dumpObject(data), {lang = 'json'}) .. i18n.warnDump
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return i18n.warnDump
		end
		
		i = i + 1
	end
end

-- Look into entity object
-- From pl:Module:Wikidane, function V, by User:Paweł Ziemian
function p.getEntityFromTree(frame)
	local data = mw.wikibase.getEntityObject()
	if not data then
		return nil
	end
	
	local f = frame.args[1] and frame or frame:getParent()
	
	local i = 1
	while true do
		local index = f.args[i]
		if not index then
			return tostring(data)
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return
		end
		
		i = i + 1
	end
end

-- getParentValues: returns a property value with its instance label fetching a recursive tree

local function uc_first(word)
	return mw.ustring.upper(mw.ustring.sub(word, 1, 1)) .. mw.ustring.sub(word, 2)
end

local function getPropertyValue(id, property, parameter)
	local entity = mw.wikibase.getEntityObject(id)
	if not (entity and entity.claims) then return end
	
	local claims = entity.claims[property]
	if not claims then return end
	-- get initial sort indices
	local sortindices = {}
	for idx in pairs(claims) do
		sortindices[#sortindices + 1] = idx
	end
	-- sort by claim rank
	local comparator = function(a, b)
		local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
		local ranka = rankmap[claims[a].rank or "normal"] ..  string.format("%08d", a)
		local rankb = rankmap[claims[b].rank or "normal"] ..  string.format("%08d", b)
		return ranka < rankb
	end
	table.sort(sortindices, comparator)
	
	local snak = claims[sortindices[1]].mainsnak
	
	local entityId
	local result = '-' -- default for 'no value'
	if snak.datavalue then
		entityId = "Q" .. tostring(snak.datavalue.value['numeric-id'])
		result, _ = getSnakValue(snak, {formatting=parameter})
	end
	
	return entityId, result
end

function p.getParentValues(frame)
	local args = frame.args
	local id = args["item"]; if id == "" then id = nil end
	local propertySup = args["property"]; if (propertySup == nil or propertySup == "") then propertySup = "P131" end --administrative entity
	local propertyLabel = args["label"]; if (propertyLabel == nil or propertyLabel == "") then propertyLabel = "P31" end --instance
	local propertyLink = args["valuetext"]; if propertyLink == "" then propertyLink = nil end --internallink
	local upto = args["upto"]; if upto == "" then upto = nil end
	local labelShow = args["labelshow"]; if labelShow == "" then labelShow = nil end
	local rowformat = args["rowformat"]; if (rowformat == nil or rowformat == "") then rowformat = "$0 = $1" end
	local separator = args["separator"]; if (separator == nil or separator == "") then separator = "<br />" end
	local sorting = args["sorting"]; if sorting == "" then sorting = nil end
	
	local lastlabel = uc_first(upto or '')
	local maxloop = tonumber(upto) or (lastlabel == '' and 10 or 50)
	
	local labelFilter = {}
	if labelShow then
		for i, v in ipairs(mw.text.split(labelShow, "/")) do
			labelFilter[uc_first(v)] = true
		end
	end
	
	local result = {}
	local label, link, linktext
	
	for iter = 1, maxloop do
		local label, link
		id, link = getPropertyValue(id, propertySup, "internallink")
		if id then
			_, label = getPropertyValue(id, propertyLabel, "label")
			if label and link then
				if propertyLink then
					_, linktext = getPropertyValue(id, propertyLink, "label")
					if linktext then
						link = mw.ustring.gsub(link, "%[%[(.*)%|.+%]%]", "[[%1|" .. linktext .. "]]")
					end
				end
				label = case(label, "infoboxlabel")
				if labelShow == nil or labelFilter[label] then
					result[#result + 1] = {label, link}
					labelFilter[label] = nil -- only first label found
				end
				if label == lastlabel then
					break
				end
			else
				break
			end
		else
			break
		end
	end
	
	local ret = {}
	local first = 1
	local last = #result
	local iter = 1
	if sorting == "-1" then first = #result; last = 1; iter = -1 end

	for i = first, last, iter do
		local rowtext = mw.ustring.gsub(rowformat, "$[01]", {["$0"] = result[i][1], ["$1"] = result[i][2]})
		ret[#ret +1] = expandBraces(rowtext)
	end
	return mw.text.listToText(ret, separator, separator)
end

function p.linkWithParentLabel(frame)
	local args = {}
	for k, v in pairs(frame.args) do -- metatable
		args[k] = v
	end
	args.list = "true"
	args.formatting = "internallink"
	args.separator = "/·/"
	local link = p._main(args) -- get internal link of property/qualifier
	if items_list == nil then
		return
	end
	local link_table = mw.text.split(link_list, "/·/", true)
	args.formatting = "raw"
	local items_list = p._main(args) -- get item of property/qualifier
	local items_table = mw.text.split(items_list, "/·/", true)
	args.property = args.parent
	args.qualifier = nil
	args.formatting = "label"
	args.list = "false"
	for i, v in ipairs(items_table) do
		args.item = v
		local link_label = p._main(args) -- get label of parent property
		if link_label then
			link_table[i] = mw.ustring.gsub(link_table[1] or '', "%[%[(.*)%|.+%]%]", "[[%1|" .. link_label .. "]]")
		end
	end
	
	return mw.text.listToText(link_table)
end

function p.years_old(frame)
	local args = frame.args
	local id = args.item; if id == '' then id = nil end
	local lang = mw.language.new('en')
	
	local function fetchsnak(id, snak)
		local ret = mw.wikibase.getEntityObject(id)
		for i, v in ipairs(snak) do
			if ret == nil then break end
			ret = ret[v]
		end
		return ret
	end
	
	local birth = fetchsnak(id, {'claims', 'P569', 1, 'mainsnak', 'datavalue', 'value'})
	if type(birth) ~= 'table' or birth.time == nil or birth.precision == nil or birth.precision < 8 then
		return
	end
	local death = fetchsnak(args.item, {'claims', 'P570', 1, 'mainsnak', 'datavalue', 'value'})
	if type(death) ~= 'table' or death.time == nil or death.precision == nil then
		death = {['time'] = lang:formatDate('c'), ['precision'] = 11} -- current date
	elseif death.precision < 8 then
		return
	end
	
	local dates = {}
	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)
	
	for i, d in ipairs(dates) do
		if d.precision == 10 then -- month
			d.min.day = 1
			local timestamp = 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"))
		elseif d.precision < 10 then -- year or decade
			d.min.day = 1
			d.min.month = 1
			d.max.day = 31
			d.max.month = 12
			if d.precision == 8 then -- decade
				d.max.year = d.max.year + 9
			end
		end
	end
	
	local function age(d1, d2)
		local years = d2.year - d1.year
		if d2.month < d1.month or (d2.month == d1.month and d2.day < d1.day) then
			years = years - 1
		end
		if d2.year > 0 and d1.year < 0 then
			years = years - 1 -- no year 0
		end
		return years
	end
	
	local old_min = age(dates[1].max, dates[2].min)
	local old_max = age(dates[1].min, dates[2].max)
	local old = old_min == old_max and old_min or old_min .. "/" .. old_max
	if args.formatting then
		old = mw.ustring.gsub(args.formatting, '$1', old)
	end
	
	return old
end

return p