Module:Wikidata
Uit Wiki Raamsdonks Erfgoed
Documentatie Module:Wikidata/doc
Testwaarden Module:Wikidata
PS: id= wordt normaal niet gebruikt. Het dient hier om met behulp van Arbitrary access waarden van andere artikelen te kunnen testen.
Command | Expected result | Pass/Fail | Result | Wikidata |
---|---|---|---|---|
Claim, Images | ||||
{{#invoke:Wikidata|claim|p41|id=Q727}} | Flag of Amsterdam.svg | |||
Claim, Strings | ||||
{{#invoke:Wikidata|claim|p1477|id=Q5598}} | Rembrandt Harmenszoon van Rijn | |||
Claim, Monolingualtext | ||||
TBD | ||||
Claim, Items | ||||
{{#invoke:Wikidata|claim|p106|id=Q5598}} | kunstschilder | |||
{{#invoke:Wikidata|claim|p106|parameter=link|id=Q5598}} | kunstschilder | |||
{{#invoke:Wikidata|claim|p106|parameter=count|id=Q5598}} | 3 | |||
{{#invoke:Wikidata|claim|p106|parameter=link|list=, |id=Q5598}} | kunstschilder, tekenaar, prentkunstenaar, kunstverzamelaar | |||
Claim, Date / Time | ||||
{{#invoke:Wikidata|claim|p569|id=Q5598}} | 15 juli 1606 | |||
{{#invoke:Wikidata|claim|p837|id=Q34812}} | 1 januari | |||
{{#invoke:Wikidata|claim|p582|id=Q12554}} | 1520 | |||
{{#invoke:Wikidata|claim|p580|id=Q1}} | 13798 mln. jaar geleden | |||
{{#invoke:Wikidata|claim|P569|parameter=link|id=Q786521}} | 4 maart 1949 | |||
Claim, Coordinates | ||||
{{#invoke:Wikidata|claim|p625|id=Q727}} | 52.383333333333/4.9 | |||
{{#invoke:Wikidata|claim|p625|parameter=latitude|id=Q727}} | 52.383333333333 | |||
{{#invoke:Wikidata|claim|p625|parameter=longitude|id=Q727}} | 4.9 | |||
Claim, Quantities | ||||
{{#invoke:Wikidata|claim|p1082|id=Q727}} | 860124 (2018) | |||
{{#invoke:Wikidata|claim|p1108|id=Q560}} | 4,5 | |||
Claim, URL's | ||||
{{#invoke:Wikidata|claim|p856|id=Q727}} | https://www.amsterdam.nl | |||
Claim, Qualifiers, References etc. | ||||
{{#invoke:Wikidata|claim|P898|qualifier=P407|id=Q727}} | Nederlands | |||
{{#invoke:Wikidata|claim|P1566|references=ja|id=Q727}} | 2759794[1] | |||
getValue | ||||
TBD | ||||
descriptionIn | ||||
{{#invoke:Wikidata|descriptionIn|ru|Q5598}} | нидерландский художник, рисовальщик и гравёр | Luafout op regel 90: attempt to index a nil value | ||
labelIn | ||||
{{#invoke:Wikidata|labelIn|ru|Q5598}} | Рембрандт | Luafout op regel 97: attempt to index a nil value | ||
labelOf | ||||
{{#invoke:Wikidata|labelOf|Q5598}} | Rembrandt | |||
pageId | ||||
{{#invoke:Wikidata|pageId}} | Q12069631 or blank | |||
sitelinkOf | ||||
{{#invoke:Wikidata|sitelinkOf|Q5598}} | Rembrandt van Rijn | |||
badges | ||||
{{#invoke:Wikidata|badges|enwiki|Q5598}} | Q17437798 (=goed artikel) |
Wikidata-entiteit niet gevonden. | ||
getSiteLink | ||||
Gebruik: [[en:{{#invoke:Wikidata|getSiteLink|enwiki}}|Module:Wikidata op de Engelstalige Wikipedia]] | ||||
{{#invoke:Wikidata|getSiteLink|commonswiki|id=Q60045}} | Albert Speer | |||
{{#invoke:Wikidata|getSiteLink|enwikivoyage|id=Q60045}} | (geen uitvoer) | |||
{{#invoke:Wikidata|getSiteLink|nietbestaandewiki|id=Q60045}} | (geen uitvoer) |
-- module local variables
local wiki =
{
langcode = mw.language.getContentLanguage().code
}
-- internationalisation
local i18n = {
["errors"] = {
["property-not-found"] = "Eigenschap niet gevonden.",
["entity-not-found"] = "Wikidata-entiteit niet gevonden.",
["unknown-claim-type"] = "Onbekend statementtype.",
["unknown-snak-type"] = "Onbekend snaktype.",
["unknown-datavalue-type"] = "Onbekend gegevenstype.",
["unknown-entity-type"] = "Onbekend entiteitstype.",
["qualifier-not-found"] = "Kwalificatie niet gevonden.",
["site-not-found"] = "Wikimedia-project niet gevonden."
},
["somevalue"] = "Onbekende waarde",
["novalue"] = "Geen waarde",
["datetime"] =
{
-- $1 is a placeholder for the actual number
[0] = "$1 mld. jaar", -- precision: billion years
[1] = "$100 mln. jaar", -- precision: hundred million years
[2] = "$10 mln. jaar", -- precision: ten million years
[3] = "$1 mln. jaar", -- precision: million years
[4] = "$100.000 jaar", -- precision: hundred thousand years
[5] = "$10.000 jaar", -- precision: ten thousand years
[6] = "$1e millennium", -- precision: millennium
[7] = "$1e eeuw", -- precision: century
[8] = "jaren $1", -- precision: decade
-- the following use the format of #time parser function
[9] = "Y", -- precision: year
[10] = "F Y", -- precision: month
[11] = "j F Y", -- precision: day
[12] = 'j F Y, G "uur"', -- precision: hour
[13] = "j F Y G:i", -- precision: minute
[14] = "j F Y G:i:s", -- precision: second
["beforenow"] = "$1 geleden", -- how to format negative numbers for precisions 0 to 5
["afternow"] = "over $1", -- how to format positive numbers for precisions 0 to 5
["bc"] = '$1 "v.Chr."', -- how print negative years
["ad"] = "$1" -- how print positive years
},
["monolingualtext"] = '<span lang="%language">%text</span>'
}
local p = { }
local function printError(code)
return '<span class="error">' .. i18n.errors[code] .. '</span>'
end
-- the "qualifiers" and "snaks" field have a respective "qualifiers-order" and "snaks-order" field
-- use these as the second parameter and this function instead of the built-in "pairs" function
-- to iterate over all qualifiers and snaks in the intended order.
local function orderedpairs(array, order)
if not order then return pairs(array) end
-- return iterator function
local i = 0
return function()
i = i + 1
if order[i] then
return order[i], array[order[i]]
end
end
end
-- getting sitelink of a given wiki
-- source: https://en.wikipedia.org/w/index.php?title=Module:Wikidata&oldid=757775054 line 1102
function p.getSiteLink(frame)
local siteId = frame.args[1]
local wikidataId = frame.args["id"]
local entity = mw.wikibase.getEntity( wikidataId )
if not entity then
return
end
local link = entity:getSitelink( siteId )
if not link then
return
end
return link
end
function p.descriptionIn(frame)
local langcode = frame.args[1]
local id = frame.args[2]
-- return description of a Wikidata entity in the given language or the default language of this Wikipedia site
return mw.wikibase.getEntityObject(id).descriptions[langcode or wiki.langcode].value
end
function p.labelIn(frame)
local langcode = frame.args[1]
local id = frame.args[2]
-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site
return mw.wikibase.getEntityObject(id).labels[langcode or wiki.langcode].value
end
local function printDatavalueCoordinate(data, parameter)
-- data fields: latitude [double], longitude [double], altitude [double], precision [double], globe [wikidata URI, usually http://www.wikidata.org/entity/Q2 [earth]]
if parameter then
if parameter == "globe" then data.globe = mw.ustring.match(data.globe, "Q%d+") end -- extract entity id from the globe URI
return data[parameter]
else
return data.latitude .. "/" .. data.longitude -- combine latitude and longitude, which can be decomposed using the #titleparts wiki function
end
end
local function printDatavalueQuantity(data, parameter)
-- data fields: amount [number], unit [string], upperBound [number], lowerBound [number]
if parameter then
return data[parameter]
else
return string.gsub(tonumber(data.amount),"%.",",") -- nl: replace dot decimal separator by comma decimal separator
end
end
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millenia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
local function normalizeDate(date)
date = mw.text.trim(date, "+")
-- extract year
local yearstr = mw.ustring.match(date, "^\-?%d+")
local year = tonumber(yearstr)
-- remove leading zeros of year
return year .. mw.ustring.sub(date, #yearstr + 1), year
end
function formatDate(date, precision, timezone, calendarmodel)
precision = precision or 11
date, year = normalizeDate(date)
if year == 0 and precision <= 9 then return "" end
-- precision is 10000 years or more
if precision <= 5 then
local factor = 10 ^ ((5 - precision) + 4)
local y2 = math.ceil(math.abs(year) / factor)
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
if year < 0 then
relative = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
else
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
end
return relative
end
-- precision is decades, centuries and millenia
local era
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end
if precision == 7 then era = mw.ustring.gsub(i18n.datetime[7], "$1", tostring(math.floor((math.abs(year) - 1) / 100) + 1)) end
if precision == 8 then era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(year) / 10) * 10)) end
if era then
if year < 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
elseif year > 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era) end
return era
end
-- precision is year
if precision == 9 then
return year
end
-- precision is less than years
if precision > 9 then
--[[ the following code replaces the UTC suffix with the given negated timezone to convert the global time to the given local time
timezone = tonumber(timezone)
if timezone and timezone ~= 0 then
timezone = -timezone
timezone = string.format("%.2d%.2d", timezone / 60, timezone % 60)
if timezone[1] ~= '-' then timezone = "+" .. timezone end
date = mw.text.trim(date, "Z") .. " " .. timezone
end
]]--
local formatstr = i18n.datetime[precision]
if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], "")
elseif year < 0 then
-- Mediawiki formatDate doesn't support negative years
date = mw.ustring.sub(date, 2)
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.bc, "$1", i18n.datetime[9]))
elseif year > 0 and i18n.datetime.ad ~= "$1" then
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.ad, "$1", i18n.datetime[9]))
end
if (mw.ustring.find(calendarmodel, 'Q1985786', 1, true)) and year > 1582 then
return mw.language.new(wiki.langcode):formatDate(formatstr, date) .. '<sup> [[Juliaanse kalender|jul.]]</sup>'
else
return mw.language.new(wiki.langcode):formatDate(formatstr, date)
end
end
end
local function formatDateLink(time, precision, calendarmodel)
precision = precision or 11
local year, m, d = mw.ustring.match( time, "(%-?%d+)%-(%d+)%-(%d+)T" )
local maanden = {'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'}
m = tonumber(m)
d = tonumber(d)
year = tonumber(year)
-- precision is decades, centuries and millenia
local era
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end
if precision == 7 then era = mw.ustring.gsub(i18n.datetime[7], "$1", tostring(math.floor((math.abs(year) - 1) / 100) + 1)) end
if precision == 8 then era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(year) / 10) * 10)) end
if era then
if year < 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
elseif year > 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era) end
return era
end
if precision == 9 then
return '[[' .. year .. ']]'
end
if precision == 10 then
if m == 8 then
return '[[Augustus (maand)|augustus]] [[' .. year .. ']]'
else
return '[[' .. maanden[m] .. ']] [[' .. year .. ']]'
end
end
if precision > 10 then
if (mw.ustring.find(calendarmodel, 'Q1985786', 1, true)) and year > 1582 then
return d .. ' ' .. maanden[m] .. ' ' .. year .. '<sup> [[Juliaanse kalender|jul.]]</sup>'
else
return '[[' .. d .. ' ' .. maanden[m] .. ']] [[' .. year .. ']]'
end
end
end
local function printDatavalueTime(data, parameter)
-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millenia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
-- calendarmodel: e.g. http://www.wikidata.org/entity/Q1985727 for the proleptic Gregorian calendar or http://www.wikidata.org/wiki/Q11184 for the Julian calendar]
if parameter then
if parameter == "calendarmodel" then data.calendarmodel = mw.ustring.match(data.calendarmodel, "Q%d+") -- extract entity id from the calendar model URI
elseif parameter == "time" then data.time = normalizeDate(data.time) end
if parameter == "link" then
return formatDateLink(data.time, data.precision, data.calendarmodel)
end
return data[parameter]
else
return formatDate(data.time, data.precision, data.timezone, data.calendarmodel)
end
end
local function printDatavalueEntity(data, parameter)
-- data fields: entity-type [string], numeric-id [int, Wikidata id]
local id = "Q" .. data["numeric-id"]
if parameter then
if parameter == "link" then
local target = mw.wikibase.sitelink(id)
if target and string.byte(target, #target) ~= ")" then
local hbTarget = target .. " (hoofdbetekenis)"
local hbTitle = mw.title.new(hbTarget)
if hbTitle.isRedirect and hbTitle.redirectTarget.fullText == target then
target = hbTarget
end
end
return "[[" .. (target or (":d:" .. id)) .. "|" .. (mw.wikibase.label(id) or id) .. "]]"
else
return data[parameter]
end
else
if data["entity-type"] == "item" then return mw.wikibase.label("Q" .. data["numeric-id"]) or id else printError("unknown-entity-type") end
end
end
local function printDatavalueMonolingualText(data, parameter)
-- data fields: language [string], text [string]
if parameter then
return data[parameter]
else
return mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, "%%language", data["language"]), "%%text", data["text"])
end
end
function findClaims(entity, property)
if not property or not entity or not entity.claims then return end
if mw.ustring.match(property, "^P%d+$") then
-- if the property is given by an id (P..) access the claim list by this id
return entity.claims[property]
else
property = mw.wikibase.resolvePropertyId(property)
if not property then return end
return entity.claims[property]
end
end
function getSnakValue(snak, parameter)
-- snaks have three types: "novalue" for null/nil, "somevalue" for not null/not nil, or "value" for actual data
if snak.snaktype == "novalue" then return i18n["novalue"]
elseif snak.snaktype == "somevalue" then return i18n["somevalue"]
elseif snak.snaktype ~= "value" then return nil, printError("unknown-snak-type")
end
-- call the respective snak parser
if snak.datavalue.type == "string" then return snak.datavalue.value
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, parameter)
elseif snak.datavalue.type == "monolingualtext" then return printDatavalueMonolingualText(snak.datavalue.value, parameter)
else return nil, printError("unknown-datavalue-type")
end
end
local function getQualifierSnak(claim, qualifierId)
-- 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 return qualifier[1] end
end
return nil, printError("qualifier-not-found")
else
-- otherwise return the main snak
return claim.mainsnak
end
end
local function getValueOfClaim(claim, qualifierId, parameter)
local error
local snak
snak, error = getQualifierSnak(claim, qualifierId)
if snak then
return getSnakValue(snak, parameter)
else
return nil, error
end
end
local function getReferences(frame, claim)
local result = ""
-- traverse through all references
for ref in pairs(claim.references or {}) do
local refparts
-- traverse through all parts of the current reference
for snakkey, snakval in orderedpairs(claim.references[ref].snaks or {}, claim.references[ref]["snaks-order"]) do
if refparts then refparts = refparts .. ", " else refparts = "" end
-- output the label of the property of the reference part, e.g. "imported from" for P143
refparts = refparts .. tostring(mw.wikibase.label(snakkey)) .. ": "
-- output all values of this reference part, e.g. "German Wikipedia" and "English Wikipedia" if the referenced claim was imported from both sites
for snakidx = 1, #snakval do
if snakidx > 1 then refparts = refparts .. ", " end
refparts = refparts .. getSnakValue(snakval[snakidx])
end
end
if refparts then result = result .. frame:extensionTag("ref", refparts) end
end
return result
end
function p.claim(frame)
local property = frame.args[1] or ""
local id = frame.args["id"]
local qualifierId = frame.args["qualifier"]
local parameter = frame.args["parameter"]
local list = frame.args["list"]
local references = frame.args["references"]
local showerrors = frame.args["showerrors"]
local default = frame.args["default"]
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
-- 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 list then
local value
-- iterate over all elements and return their value (if existing)
result = {}
for idx in pairs(claims) do
local claim = claims[sortindices[idx]]
value, error = getValueOfClaim(claim, qualifierId, parameter)
if not value and showerrors then value = error end
if value and references then value = value .. getReferences(frame, claim) end
result[#result + 1] = value
end
result = table.concat(result, list)
elseif parameter == "count" then
result = #claims
else
-- return first element
local claim = claims[sortindices[1]]
result, error = getValueOfClaim(claim, qualifierId, parameter)
if result and references then result = result .. getReferences(frame, claim) end
end
if result then return result else
if showerrors then return error else return default end
end
end
function p.getValue(frame)
local param = frame.args[2]
if param == "FETCH_WIKIDATA" then return p.claim(frame) else return param end
end
function p.pageId(frame)
local entity = mw.wikibase.getEntityObject()
if not entity then return nil else return entity.id end
end
function p.labelOf(frame)
local id = frame.args[1]
-- returns the label of the given entity/property id
-- if no id is given, the one from the entity associated with the calling Wikipedia article is used
if not id then
local entity = mw.wikibase.getEntityObject()
if not entity then return printError("entity-not-found") end
id = entity.id
end
return mw.wikibase.label(id)
end
function p.sitelinkOf(frame)
local id = frame.args[1]
-- returns the Wikipedia article name of the given entity
-- if no id is given, the one from the entity associated with the calling Wikipedia article is used
if not id then
local entity = mw.wikibase.getEntityObject()
if not entity then return printError("entity-not-found") end
id = entity.id
end
return mw.wikibase.sitelink(id)
end
function p.badges(frame)
local site = frame.args[1]
local id = frame.args[2]
if not site then return printError("site-not-found") end
local entity = mw.wikibase.getEntityObject(id)
if not entity then return printError("entity-not-found") end
local badges = entity.sitelinks[site].badges
if badges then
local result
for idx = 1, #badges do
if result then result = result .. "/" .. badges[idx] else result = badges[idx] end
end
return result
end
end
-- call this in cases of script errors within a function instead of {{#invoke:Wikidata|<method>|...}} call {{#invoke:Wikidata|debug|<method>|...}}
function p.debug(frame)
local func = frame.args[1]
if func then
-- create new parameter set, where the first parameter with the function name is removed
local newargs = {}
for key, val in pairs(frame.args) do
if type(key) == "number" then
if key > 1 then newargs[key - 1] = val end
else
newargs[key] = val
end
end
frame.args = newargs
local status, result = pcall(p[func], frame)
if status then return result else return '<span class="error">' .. result .. '</span>' end
else
return '<span class="error">invalid parameters</span>'
end
end
return p