Modul:Wikidata: Skillnad mellan sidversioner

Från Järnvägsdata
jarnvagsdata>Uzume
(missed one)
jarnvagsdata>Nirmos
m (Skyddade "Modul:Wikidata": används på 136 993 sidor ([Redigera=Enbart registrerade användare] (på obestämd tid) [Flytta=Enbart registrerade användare] (på obestämd tid)))
Rad 1: Rad 1:
-- vim: set noexpandtab ft=lua ts=4 sw=4:
-- Den ordning fallback language hämtas, om svensk label saknas. Engelska först, därefter bokmål, danska, etc...
require('Module:No globals')
local fallback = {'en', 'nb', 'da', 'nn', 'de', 'fr', 'es', 'it', 'pt'}
 
local i18n = {
local p = {}
    ["errors"] = {
local debug = false
        ["property-param-not-provided"] = "Property parameter not provided.",
 
        ["entity-not-found"] = "Entity not found.",
 
        ["unknown-claim-type"] = "Unknown claim type.",
------------------------------------------------------------------------------
        ["unknown-snak-type"] = "Unknown snak type.",
-- module local variables and functions
        ["unknown-datatype"] = "Unknown datatype.",
 
        ["unknown-entity-type"] = "Unknown entity type.",
local wiki =
        ["unknown-value-module"] = "You must set both value-module and value-function parameters.",
{
        ["value-module-not-found"] = "The module pointed by value-module not found.",
langcode = mw.language.getContentLanguage().code
        ["value-function-not-found"] = "The function pointed by value-function not found."
    },
    ["somevalue"] = "''unknown value''",
    ["novalue"] = "''no value''"
}
}
local sortingproperties = {'P585','P571','P580','P569','P582','P570'}


-- internationalisation
function getqualifierbysortingproperty(claim, sortingproperty)
local i18n =
for k, v in pairs(sortingproperty) do
{
if claim.qualifiers and claim.qualifiers[v] and claim.qualifiers[v][1].snaktype == 'value' then
["errors"] =
return claim.qualifiers[v][1].datavalue.value.time
{
end
["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."
},
["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
-- the following are for function getDateValue() and getQualifierDateValue()
["default-format"] = "dmy", -- default value of the #3 (getDateValue) or
-- #4 (getQualifierDateValue) argument
["default-addon"] = "BC", -- default value of the #4 (getDateValue) or
-- #5 (getQualifierDateValue) argument
["prefix-addon"] = false, -- set to true for languages put "BC" in front of the
-- datetime string; or the addon will be suffixed
["addon-sep"] = " ", -- separator between datetime string and addon (or inverse)
["format"] = -- options of the 3rd argument
{
["mdy"] = "F j, Y",
["my"] = "F Y",
["y"] = "Y",
["dmy"] = "j F Y",
["ymd"] = "Y-m-d",
["ym"] = "Y-m"
}
},
["monolingualtext"] = '<span lang="%language">%text</span>',
["warnDump"] = "[[Category:Called function 'Dump' from module Wikidata]]",
["ordinal"] =
{
[1] = "st",
[2] = "nd",
[3] = "rd",
["default"] = "th"
}
}
 
if wiki.langcode ~= "en" then
--require("Module:i18n").loadI18n("Module:Wikidata/i18n", i18n)
-- got idea from [[:w:Module:Wd]]
local module_title; if ... == nil then
module_title = mw.getCurrentFrame():getTitle()
else
module_title = ...
end
end
require('Module:i18n').loadI18n(module_title..'/i18n', i18n)
return nil
end
end


-- this function needs to be internationalised along with the above:
function getDate(claim, options)
-- takes cardinal numer as a numeric and returns the ordinal as a string
local sortingproperty = sortingproperties
-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.
if type(options.sortingproperty) == 'table' then
local function makeOrdinal (cardinal)
sortingproperty = options.sortingproperty
local ordsuffix = i18n.ordinal.default
elseif type(options.sortingproperty) == 'string' then
if cardinal % 10 == 1 then
sortingproperty = {options.sortingproperty}
ordsuffix = i18n.ordinal[1]
elseif cardinal % 10 == 2 then
ordsuffix = i18n.ordinal[2]
elseif cardinal % 10 == 3 then
ordsuffix = i18n.ordinal[3]
end
end
-- In English, 1, 21, 31, etc. use 'st', but 11, 111, etc. use 'th'
return getqualifierbysortingproperty(claim, sortingproperty)  
-- similarly for 12 and 13, etc.
if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then
ordsuffix = i18n.ordinal.default
end
return tostring(cardinal) .. ordsuffix
end
end


local function printError(code)
function comparedates(a, b)  
return '<span class="error">' .. (i18n.errors[code] or code) .. '</span>'
if a and b then
end
return a > b
local function parseDateFormat(f, timestamp, addon, prefix_addon, addon_sep)  
elseif a then
local year_suffix
return true
local tstr = ""
local lang_obj = mw.language.new(wiki.langcode)
local f_parts = mw.text.split(f, 'Y', true)
for idx, f_part in pairs(f_parts) do
year_suffix = ''
if string.match(f_part, "x[mijkot]$") then
-- for non-Gregorian year
f_part = f_part .. 'Y'
elseif idx < #f_parts then
-- supress leading zeros in year
year_suffix = lang_obj:formatDate('Y', timestamp)
year_suffix = string.gsub(year_suffix, '^0+', '', 1)
end
tstr = tstr .. lang_obj:formatDate(f_part, timestamp) .. year_suffix
end
if addon ~= "" and prefix_addon then
return addon .. addon_sep .. tstr
elseif addon ~= "" then
return tstr .. addon_sep .. addon
else
return tstr
end
end
end
end
local function parseDateValue(timestamp, date_format, date_addon)
local prefix_addon = i18n["datetime"]["prefix-addon"]
local addon_sep = i18n["datetime"]["addon-sep"]
local addon = ""


-- check for negative date
function sortbyqualifier(claims, options)
if string.sub(timestamp, 1, 1) == '-' then
timestamp = '+' .. string.sub(timestamp, 2)
table.sort(claims, function(a,b)
addon = date_addon
local timeA = getDate(a, options)
end
local timeB = getDate(b, options)
local _date_format = i18n["datetime"]["format"][date_format]
if options.sortbytime == 'inverted' then
if _date_format ~= nil then
return comparedates(timeB, timeA)
return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)
else
return printError("unknown-datetime-format")
end
end
 
-- This local function combines the year/month/day/BC/BCE handling of parseDateValue{}
-- with the millennium/century/decade handling of formatDate()
local function parseDateFull(timestamp, precision, date_format, date_addon)
local prefix_addon = i18n["datetime"]["prefix-addon"]
local addon_sep = i18n["datetime"]["addon-sep"]
local addon = ""
 
-- check for negative date
if string.sub(timestamp, 1, 1) == '-' then
timestamp = '+' .. string.sub(timestamp, 2)
addon = date_addon
end
 
-- get the next four characters after the + (should be the year now in all cases)
-- ok, so this is dirty, but let's get it working first
local intyear = tonumber(string.sub(timestamp, 2, 5))
if intyear == 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(intyear) / factor)
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
if addon ~= "" then
-- negative date
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 (8), centuries (7) and millennia (6)
local era, card
if precision == 6 then
card = math.floor((intyear - 1) / 1000) + 1
era = mw.ustring.gsub(i18n.datetime[6], "$1", makeOrdinal(card))
end
if precision == 7 then
card = math.floor((intyear - 1) / 100) + 1
era = mw.ustring.gsub(i18n.datetime[7], "$1", makeOrdinal(card))
end
if precision == 8 then
era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(intyear) / 10) * 10))
end
if era then
if addon ~= "" then
era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
else
else
era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era)
return comparedates(timeA, timeB)
end
return era
end
 
local _date_format = i18n["datetime"]["format"][date_format]
if _date_format ~= nil then
-- check for precision is year and override supplied date_format
if precision == 9 then
_date_format = i18n["datetime"][9]
end
end
return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)
else
return printError("unknown-datetime-format")
end
end
)
return claims
end
end


-- the "qualifiers" and "snaks" field have a respective "qualifiers-order" and "snaks-order" field
function getLabelFromFallBack( id )  
-- use these as the second parameter and this function instead of the built-in "pairs" function
local entity = getEntityFromId( id )
-- to iterate over all qualifiers and snaks in the intended order.
for k, v in pairs(fallback) do
local function orderedpairs(array, order)
if entity.labels[v] then
if not order then return pairs(array) end
return {value = entity.labels[v].value, language = entity.labels[v].language}
 
-- return iterator function
local i = 0
return function()
i = i + 1
if order[i] then
return order[i], array[order[i]]
end
end
end
end
end
-- Om inget fallback-språk finns av de i variabeln ovan, så används det först definierade i objektet
 
if entity.labels then  
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
for v, k in pairs(entity.labels) do
local function normalizeDate(date)
return {value = k.value, language = k.language}
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
 
local function formatDate(date, precision, timezone)
precision = precision or 11
local 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
end
return relative
end
-- precision is decades, centuries and millennia
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
return mw.language.new(wiki.langcode):formatDate(formatstr, date)
end
end
return {value = '-', language = ''}
end
end


local function printDatavalueEntity(data, parameter)
function getEntityFromId( id )
-- data fields: entity-type [string], numeric-id [int, Wikidata id]
if id then  
local id
return mw.wikibase.getEntityObject( id )
 
if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"]
elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"]
else return printError("unknown-entity-type")
end
 
if parameter then
if parameter == "link" then
local linkTarget = mw.wikibase.getSitelink(id)
local linkName = mw.wikibase.getLabel(id)
if linkTarget then
-- if there is a local Wikipedia article link to it using the label or the article title
return "[[" .. linkTarget .. "|" .. (linkName or linkTarget) .. "]]"
else
-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label
if linkName then return linkName else return "[[:d:" .. id .. "|" .. id .. "]]" end
end
else
return data[parameter]
end
else
else
return mw.wikibase.getLabel(id) or id
return mw.wikibase.getEntityObject()  
end
end
end
end
 
local function printDatavalueTime(data, parameter)
function getEntityIdFromValue( value )
-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]
    if value['entity-type'] == 'item' then
--  precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
        return 'Q' .. value['numeric-id']
--  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]
    elseif value['entity-type'] == 'property' then
if parameter then
        return 'P' .. value['numeric-id']
if parameter == "calendarmodel" then data.calendarmodel = mw.ustring.match(data.calendarmodel, "Q%d+") -- extract entity id from the calendar model URI
    else
elseif parameter == "time" then data.time = normalizeDate(data.time) end
        return formatError( 'unknown-entity-type' )
return data[parameter]
    end
else
return formatDate(data.time, data.precision, data.timezone)
end
end
end
 
local function printDatavalueMonolingualText(data, parameter)
function formatError( key )
-- data fields: language [string], text [string]
    return '<span class="error">' .. i18n.errors[key] .. '</span>'
if parameter then
return data[parameter]
else
local result = mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, "%%language", data["language"]), "%%text", data["text"])
return result
end
end
end
function formatStatements( options, ref )
  local formattedStatements = {}
  local claims = {}
  if not options.property then
      return formatError( 'property-param-not-provided' )
  end


local function findClaims(entity, property)
    if type(ref) == 'table' then -- för de fall där funktionen anropas och alla claims redan finns i en tabell
if not property or not entity or not entity.claims then return end
claims = ref[options.property]
 
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
else
property = mw.wikibase.resolvePropertyId(property)
if not property then return end
    --Get entity
 
    local entity = nil
return entity.claims[property]
    if options.entity and type( options.entity ) == "table" then
end
        entity = options.entity
end
    else
 
        entity = getEntityFromId( options.entityId )
local function getSnakValue(snak, parameter)
    end
if snak.snaktype == "value" then
-- call the respective snak parser
    if not entity then
if snak.datavalue.type == "string" then return snak.datavalue.value
        return '' --TODO error?
elseif snak.datavalue.type == "globecoordinate" then return printDatavalueCoordinate(snak.datavalue.value, parameter)
    end
elseif snak.datavalue.type == "quantity" then return printDatavalueQuantity(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "time" then return printDatavalueTime(snak.datavalue.value, parameter)
    if not entity.claims or not entity.claims[options.property:upper()] then
elseif snak.datavalue.type == "wikibase-entityid" then return printDatavalueEntity(snak.datavalue.value, parameter)
        return '' --TODO error?
elseif snak.datavalue.type == "monolingualtext" then return printDatavalueMonolingualText(snak.datavalue.value, parameter)
    end
    --Format statement and concat them cleanly
if options.rank == 'best' or not options.rank then  
claims = entity:getBestStatements( options.property:upper() )
elseif options.rank == 'valid' then
for i, statement in pairs( entity.claims[options.property:upper()] ) do
    if statement.rank == 'preferred' or statement.rank == 'normal' then
    table.insert( claims, statement )
    end
end
elseif options.rank == 'all' then
for i, statement in pairs( entity.claims[options.property:upper()] ) do
table.insert( claims, statement )
end
else
for i, statement in pairs( entity.claims[options.property:upper()] ) do
if statement.rank == options.rank then
table.insert( claims, statement )
end
end
end
end
end
if options.avoidqualifier then
return mw.wikibase.renderSnak(snak)
local claims2 = {}
end
for i, statement in pairs( claims ) do
 
if not statement.qualifiers or not statement.qualifiers[options.avoidqualifier:upper()] then
local function getQualifierSnak(claim, qualifierId)
table.insert( claims2, statement)
-- a "snak" is Wikidata terminology for a typed key/value pair
end
-- a claim consists of a main snak holding the main information of this claim,
end
-- as well as a list of attribute snaks and a list of references snaks
claims = claims2
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
end
return nil, printError("qualifier-not-found")
--om det finns vissa statements som har en qualifier som säger "språk = svenska", ta bara med dessa
else
if not options.langpref or options.langpref == '' then
-- otherwise return the main snak
local claims2 = {}
return claim.mainsnak
for i, statement in pairs( claims ) do
end
if statement.qualifiers and statement.qualifiers.P407 then
end
for k, v in pairs( statement.qualifiers.P407 ) do
 
if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 9027 then -- Q9027 = 'svenska'
local function getValueOfClaim(claim, qualifierId, parameter)
table.insert( claims2, statement )
local error
end
local snak
end
snak, error = getQualifierSnak(claim, qualifierId)
end
if snak then
end
return getSnakValue(snak, parameter)
if #claims2 > 0 then
else
claims = claims2
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.getLabel(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
end
end
if refparts then result = result .. frame:extensionTag("ref", refparts) end
if options.sortbytime == 'chronological' or options.sortbytime == 'inverted' then
end
claims = sortbyqualifier(claims, options)
return result
end
 
local function parseInput(frame)
local qid = frame.args.qid
if qid and (#qid == 0) then qid = nil end
local propertyID = mw.text.trim(frame.args[1] or "")
local input_parm = mw.text.trim(frame.args[2] or "")
if input_parm ~= "FETCH_WIKIDATA" then
return false, input_parm, nil, nil
end
local entity = mw.wikibase.getEntity(qid)
local claims
if entity and entity.claims then
claims = entity.claims[propertyID]
if not claims then
return false, "", nil, nil
end
end
else
return false, "", nil, nil
end
end
return true, entity, claims, propertyID
if options.enbarten and options.enbarten ~= '' and #claims > 1 then
end
claims = {claims[1]}
local function isType(claims, type)
return claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == type
end
local function getValue(entity, claims, propertyID, delim, labelHook)
if labelHook == nil then
labelHook = function (qnumber)
return nil;
end
end
end
if isType(claims, "wikibase-entityid") then
if claims then
local out = {}
for i, statement in pairs( claims ) do
for k, v in pairs(claims) do
local s = formatStatement( statement, options )
local qnumber = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
if s == '' then s = nil end
local sitelink = mw.wikibase.getSitelink(qnumber)
if type(ref) == 'table' or (options.noref and options.noref ~='') then --Inte leta efter referenser om själva anropet görs från en referens
local label = labelHook(qnumber) or mw.wikibase.getLabel(qnumber) or qnumber
table.insert( formattedStatements, s )
if sitelink then
out[#out + 1] = "[[" .. sitelink .. "|" .. label .. "]]"
else
else
out[#out + 1] = "[[:d:" .. qnumber .. "|" .. label .. "]]<abbr title='" .. i18n["errors"]["local-article-not-found"] .. "'>[*]</abbr>"
local t = ''--formatReferences( statement, options )
table.insert( formattedStatements, s .. t )
end
end
end
end
return table.concat(out, delim)
else
-- just return best values
return entity:formatPropertyValues(propertyID).value
end
end
return mw.text.listToText( formattedStatements, options.separator, options.conjunction )
end
end
 
function formatReferences( statement, options )
------------------------------------------------------------------------------
local reference = {}
-- module global functions
if statement.references then
 
local cite = require('Modul:Cite')
if debug then
for i, ref in pairs(statement.references) do
function p.inspectI18n(frame)
local items, s = {}, nil
local val = i18n
if ref.snaks then
for _, key in pairs(frame.args) do
if ref.snaks.P248 then
key = mw.text.trim(key)
for j, prop in pairs(ref.snaks.P248) do
val = val[key]
table.insert(items, 'Q' .. prop.datavalue.value['numeric-id'])
end
return val
end
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.getEntity(id):getDescription(langcode or wiki.langcode)
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.getEntity(id):getLabel(langcode or wiki.langcode)
end
 
-- This is used to get a value, or a comma separated list of them if multiple values exist
p.getValue = function(frame)
local delimdefault = ", " -- **internationalise later**
local delim = frame.args.delimiter or ""
delim = string.gsub(delim, '"', '')
if #delim == 0 then
delim = delimdefault
end
local go, errorOrentity, claims, propertyID = parseInput(frame)
if not go then
return errorOrentity
end
return getValue(errorOrentity, claims, propertyID, delim)
end
 
-- Same as above, but uses the short name property for label if available.
p.getValueShortName = function(frame)
local go, errorOrentity, claims, propertyID = parseInput(frame)
if not go then
return errorOrentity
end
local entity = errorOrentity
-- if wiki-linked value output as link if possible
local function labelHook (qnumber)
local label
local claimEntity = mw.wikibase.getEntity(qnumber)
if claimEntity ~= nil then
if claimEntity.claims.P1813 then
for k2, v2 in pairs(claimEntity.claims.P1813) do
if v2.mainsnak.datavalue.value.language == "en" then
label = v2.mainsnak.datavalue.value.text
end
end
end
s = cite.citeitem( items, ref.snaks, options )
if s == '' or not s then
s = 'Källangivelsen på Wikidata använder propertys som inte känns igen av Modul:Cite'
end
end
end
end
table.insert(reference, mw.getCurrentFrame():extensionTag( 'ref', s, {name = ref.hash} ) )
end
end
if label == nil or label == "" then return nil end
return label
end
end
return getValue(errorOrentity, claims, propertyID, ", ", labelHook);
return table.concat(reference)
end
end
 
function formatStatement( statement, options )
-- This is used to get a value, or a comma separated list of them if multiple values exist
    if statement.type == 'statement' then
-- from an arbitrary entry by using its QID.
return formatSnak( statement.mainsnak, options ).value
-- Use : {{#invoke:Wikidata|getValueFromID|<ID>|<Property>|FETCH_WIKIDATA}}
elseif not statement.type then
-- E.g.: {{#invoke:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}} - to fetch value of 'spouse' (P26) from 'Richard Burton' (Q151973)
return formatSnak( statement, options ).value --reference and qualifier
-- Please use sparingly - this is an *expensive call*.
    end
p.getValueFromID = function(frame)
return formatError( 'unknown-claim-type' )
local itemID = mw.text.trim(frame.args[1] or "")
local propertyID = mw.text.trim(frame.args[2] or "")
local input_parm = mw.text.trim(frame.args[3] or "")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntity(itemID)
local claims
if entity and entity.claims then
claims = entity.claims[propertyID]
end
if claims then
return getValue(entity, claims, propertyID, ", ")
else
return ""
end
else
return input_parm
end
end
end
local function getQualifier(frame, outputHook)  
local propertyID = mw.text.trim(frame.args[1] or "")
function formatSnak( snak, options )
local qualifierID = mw.text.trim(frame.args[2] or "")
    if snak.snaktype == 'somevalue' then
local input_parm = mw.text.trim(frame.args[3] or "")
        return {value = i18n['somevalue']}
if input_parm == "FETCH_WIKIDATA" then
    elseif snak.snaktype == 'novalue' then
local entity = mw.wikibase.getEntity()
        return {value = i18n['novalue']}
if entity.claims[propertyID] ~= nil then
    elseif snak.snaktype == 'value' then
local out = {}
        return {value = formatDatavalue( snak.datavalue, options, snak.datatype ).value}
for k, v in pairs(entity.claims[propertyID]) do
    else
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
        return {value = formatError( 'unknown-snak-type' )}
if v2.snaktype == 'value' then
    end
out[#out + 1] = outputHook(v2);
end
end
end
return table.concat(out, ", "), true
else
return "", false
end
else
return input_parm, false
end
end
end
p.getQualifierValue = function(frame)
local function outputValue(value)
function formatDatavalue( datavalue, options, datatype )
local qnumber = "Q" .. value.datavalue.value["numeric-id"]
    --Use the customize handler if provided
if (mw.wikibase.getSitelink(qnumber)) then
    if options['value-module'] or options['value-function'] then
return "[[" .. mw.wikibase.getSitelink(qnumber) .. "]]"
        if not options['value-module'] or not options['value-function'] then
else
            return {value = formatError( 'unknown-value-module' )}
return "[[:d:" .. qnumber .. "|" ..qnumber .. "]]<abbr title='" .. i18n["errors"]["local-article-not-found"] .. "'>[*]</abbr>"
        end
        local formatter = require ('Module:' .. options['value-module'])
        if not formatter then
            return {value = formatError( 'value-module-not-found' )}
        end
        local fun = formatter[options['value-function']]
        if not fun then
            return {value = formatError( 'value-function-not-found' )}
        end
        return {value = fun( datavalue.value, options )}
    end
    --Default formatters
    if datatype == 'wikibase-item' then
        return {value = formatEntityId( getEntityIdFromValue( datavalue.value ), options ).value}
       
    elseif datatype == 'string' or datatype == 'commonsMedia' then
        if options.pattern and options.pattern ~= '' then
        if options.pattern == "auktoritetsdata" then
        local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        return {value = formatFromPattern( datavalue.value, {pattern = patter} )}
        elseif options.pattern == "auktoritetsdata2" or options.pattern == 'auktoritetsdata3' then
        local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        return {value = '[' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ' ' .. datavalue.value .. ']' }
        else
            return {value = formatFromPattern( datavalue.value, options )}
            end
        else
            return {value = datavalue.value}
        end
       
    elseif datatype == 'time' then
        local Time = require 'Module:Time'
        return {value = Time.newFromWikidataValue( datavalue.value ):toHtml()}
       
    elseif datatype == 'globe-coordinate' then
        local GlobeCoordinate = require 'Module:GlobeCoordinate'
        return {value = GlobeCoordinate.newFromWikidataValue( datavalue.value ):toHtml()}
   
elseif datatype == 'quantity' then
local amount, unit, cat = datavalue.value.amount, datavalue.value.unit, nil
if unit then
unit = unit:match('Q%d+')
end
end
end
local formatera = require('Modul:Math')
return (getQualifier(frame, outputValue))
local number = formatera.newFromWikidataValue(datavalue.value)
end


-- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators
local unitraw = unit
p.getRawValue = function(frame)
if unit then
local go, errorOrentity, claims, propertyID = parseInput(frame)
-- Kontrollerar om det finns någon förkortning för denna 'unit'
if not go then
local lab = options.label or formatStatements({property = 'P558', entityId = unit, enbarten = 'true', langpref = options.langpref, noref = 'true'})
return errorOrentity
if lab and ( not options.nounitshort or options.nounitshort == '' ) then
end
local s = formatEntityId( unit, {label = lab, nolink = (options.nounitlink or options.nolink) })
local entity = errorOrentity
unit = s.value
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
cat = s.cat
-- if number type: remove thousand separators, bounds and units
else -- om det inte finns en förkortning
if isType(claims, "quantity") then
local s = formatEntityId( unit, {nolink = options.nounitlink})
result = mw.ustring.gsub(result, "(%d),(%d)", "%1%2")
unit = s.value
result = mw.ustring.gsub(result, "(%d)±.*", "%1")
cat = s.cat
end
end
return result
end
end
return {value = number .. ' ' .. (unit or ''), amount = amount, unit = unit, unitraw = unitraw, cat = cat}
 
-- This is used to get the unit name for the numeric value returned by getRawValue
elseif datatype == 'url' then
p.getUnits = function(frame)
if options.label and options.label ~= '' then
local go, errorOrentity, claims, propertyID = parseInput(frame)
return {value = '[' .. datavalue.value .. ' ' .. options.label .. ']'}
if not go then
return errorOrentity
end
local entity = errorOrentity
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
if isType(claims, "quantity") then
result = mw.ustring.sub(result, mw.ustring.find(result, " ")+1, -1)
end
return result
end
 
-- This is used to get the unit's QID to use with the numeric value returned by getRawValue
p.getUnitID = function(frame)
local go, errorOrentity, claims = parseInput(frame)
if not go then
return errorOrentity
end
local entity = errorOrentity
local result
if isType(claims, "quantity") then
-- get the url for the unit entry on Wikidata:
result = claims[1].mainsnak.datavalue.value.unit
-- and just reurn the last bit from "Q" to the end (which is the QID):
result = mw.ustring.sub(result, mw.ustring.find(result, "Q"), -1)
end
return result
end
 
p.getRawQualifierValue = function(frame)
local function outputHook(value)
if value.datavalue.value["numeric-id"] then
return mw.wikibase.getLabel("Q" .. value.datavalue.value["numeric-id"])
else
else
return value.datavalue.value
return {value = datavalue.value}
end
end
end
local ret, gotData = getQualifier(frame, outputHook)
elseif datavalue.type == 'monolingualtext' then
if gotData then
return {value = mw.text.tag('span', {title = mw.language.fetchLanguageName(datavalue.value.language, 'sv')}, datavalue.value.text)}
ret = string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2)
end
    else
return ret
        return {value = formatError( 'unknown-datatype' )}
end
    end
 
-- This is used to get a date value for date_of_birth (P569), etc. which won't be linked
-- Dates and times are stored in ISO 8601 format (sort of).
-- At present the local formatDate(date, precision, timezone) function doesn't handle timezone
-- So I'll just supply "Z" in the call to formatDate below:
p.getDateValue = function(frame)
local date_format = mw.text.trim(frame.args[3] or i18n["datetime"]["default-format"])
local date_addon = mw.text.trim(frame.args[4] or i18n["datetime"]["default-addon"])
local go, errorOrentity, claims = parseInput(frame)
if not go then
return errorOrentity
end
local entity = errorOrentity
local out = {}
for k, v in pairs(claims) do
if v.mainsnak.datavalue.type == 'time' then
local timestamp = v.mainsnak.datavalue.value.time
local dateprecision = v.mainsnak.datavalue.value.precision
-- A year can be stored like this: "+1872-00-00T00:00:00Z",
-- which is processed here as if it were the day before "+1872-01-01T00:00:00Z",
-- and that's the last day of 1871, so the year is wrong.
-- So fix the month 0, day 0 timestamp to become 1 January instead:
timestamp = timestamp:gsub("%-00%-00T", "-01-01T")
out[#out + 1] = parseDateFull(timestamp, dateprecision, date_format, date_addon)
end
end
return table.concat(out, ", ")
end
end
p.getQualifierDateValue = function(frame)
local date_format = mw.text.trim(frame.args[4] or i18n["datetime"]["default-format"])
function formatEntityId( entityId, options )
local date_addon = mw.text.trim(frame.args[5] or i18n["datetime"]["default-addon"])
local label = options.label or mw.wikibase.label( entityId )
local function outputHook(value)
if label == '' then
local timestamp = value.datavalue.value.time
label = mw.wikibase.label( entityId ) or nil
return parseDateValue(timestamp, date_format, date_addon)
end
end
return (getQualifier(frame, outputHook))
end


-- This is used to fetch all of the images with a particular property, e.g. image (P18), Gene Atlas Image (P692), etc.
    local link = mw.wikibase.sitelink( entityId )
-- Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=frameless)
    if link and (not options.nolink or options.nolink == '') then
-- It will return a standard wiki-markup [[File:Filename | size]] for each image with a selectable size and separator (which may be html)
        if label and label ~= '' then
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA}}
            return {value = '[[:' .. link .. '|' .. label .. ']]' }
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA|<br>|250px}}
        else
-- If a property is chosen that is not of type "commonsMedia", it will return empty text.
            return {value = '[[:' .. link .. ']]' }
p.getImages = function(frame)
        end
local sep = mw.text.trim(frame.args[3] or " ")
    else
local imgsize = mw.text.trim(frame.args[4] or "frameless")
    if label then
local go, errorOrentity, claims = parseInput(frame)
    return {value = label}
if not go then
    else
return errorOrentity
    local s = getLabelFromFallBack( entityId )
end
    local l = mw.language.fetchLanguageName(s.language, 'sv')
local entity = errorOrentity
    if not l or l == '' then
if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then
    l = 'okänt språk'
local out = {}
    end
for k, v in pairs(claims) do
    if s then
local filename = v.mainsnak.datavalue.value
    return {value = mw.text.tag('span', {title = l}, s.value), cat = 'med labels på ' .. l }
out[#out + 1] = "[[File:" .. filename .. "|" .. imgsize .. "]]"
    end
end
    end
return table.concat(out, sep)
    return {value = entityId, cat = 'som har labels med Qid'}
else
    end
return ""
end
end
end
 
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
function formatFromPattern( str, options )
-- 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
    return mw.ustring.gsub( options.pattern, '$1', str ) .. '' --Hack to get only the first result of the function
-- 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.getEntity()
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
end
 
--[[
local p = {}
This is used to return an image legend from Wikidata
image is property P18
function p.formatStatements( frame, key )
image legend is property P2096
    local args = frame.args
 
Call as {{#invoke:Wikidata |getImageLegend | <PARAMETER> | lang=<ISO-639code> |id=<QID>}}
    --If a value if already set, use it
Returns PARAMETER, unless it is equal to "FETCH_WIKIDATA", from Item QID (expensive call)
    if args.value and args.value ~= '' then
If QID is omitted or blank, the current article is used (not an expensive call)
        return args.value
If lang is omitted, it uses the local wiki language, otherwise it uses the provided ISO-639 language code
    end
ISO-639: https://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqisocodes.html#wp1252447
    return formatStatements( frame.args, key )
 
Ranks are: 'preferred' > 'normal'
This returns the label from the first image with 'preferred' rank
Or the label from the first image with 'normal' rank if preferred returns nothing
Ranks: https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua
]]
 
p.getImageLegend = function(frame)
-- look for named parameter id; if it's blank make it nil
local id = frame.args.id
if id and (#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
local lang = frame.args.lang
if (not lang) or (#lang < 2) then
lang = mw.language.getContentLanguage().code
end
 
-- first unnamed parameter is the local parameter, if supplied
local input_parm = mw.text.trim(frame.args[1] or "")
if input_parm == "FETCH_WIKIDATA" then
local ent = mw.wikibase.getEntity(id)
local imgs
if ent and ent.claims then
imgs = ent.claims.P18
end
local imglbl
if imgs then
-- look for an image with 'preferred' rank
for k1, v1 in pairs(imgs) do
if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P2096 then
local imglbls = v1.qualifiers.P2096
for k2, v2 in pairs(imglbls) do
if v2.datavalue.value.language == lang then
imglbl = v2.datavalue.value.text
break
end
end
end
end
-- if we don't find one, look for an image with 'normal' rank
if (not imglbl) then
for k1, v1 in pairs(imgs) do
if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P2096 then
local imglbls = v1.qualifiers.P2096
for k2, v2 in pairs(imglbls) do
if v2.datavalue.value.language == lang then
imglbl = v2.datavalue.value.text
break
end
end
end
end
end
end
return imglbl
else
return input_parm
end
end
end
 
-- This is used to get the QIDs of all of the values of a property, as a comma separated list if multiple values exist
function p.formatStatementsFromLua( options, key )
-- Usage: {{#invoke:Wikidata |getPropertyIDs |<PropertyID> |FETCH_WIKIDATA}}
    --If a value if already set, use it
-- Usage: {{#invoke:Wikidata |getPropertyIDs |<PropertyID> |<InputParameter> |qid=<QID>}}
    if options.value and options.value ~= '' then
 
        return options.value
p.getPropertyIDs = function(frame)
    end
local go, errorOrentity, propclaims = parseInput(frame)
    local s = formatStatements( options, key )
if not go then
    if s == '' then
return errorOrentity
    s = nil
end
    end
local entity = errorOrentity
    return s
-- if wiki-linked value collect the QID in a table
if (propclaims[1] and propclaims[1].mainsnak.snaktype == "value" and propclaims[1].mainsnak.datavalue.type == "wikibase-entityid") then
local out = {}
for k, v in pairs(propclaims) do
out[#out + 1] = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
end
return table.concat(out, ", ")
else
-- not a wikibase-entityid, so return empty
return ""
end
end
end
 
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
-- Return the site link (for the current site) for a given data item.
function p.pageId(frame)
function p.getSiteLink( frame )
return mw.wikibase.getEntityIdForCurrentPage()
    if frame.args[1] == nil then
end
        entity = mw.wikibase.getEntityObject()
 
        if not entity then
function p.claim(frame)
        entity = mw.wikibase.getEntityObject(frame.args[1])
local property = frame.args[1] or ""
        end
local id = frame.args["id"]
        id = entity.id
local qualifierId = frame.args["qualifier"]
    else
local parameter = frame.args["parameter"]
        id = frame.args[1]
local list = frame.args["list"]
    end
local references = frame.args["references"]
local showerrors = frame.args["showerrors"]
    return mw.wikibase.sitelink( id )
local default = frame.args["default"]
if default then showerrors = nil end
 
-- get wikidata entity
local entity = mw.wikibase.getEntity(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)
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
end


Rad 935: Rad 398:
id = nil
id = nil
end
end
local data = mw.wikibase.getEntity(id)
local data = mw.wikibase.getEntityObject(id)
if not data then
if not data then
return nil
return nil
Rad 950: Rad 413:
end
end
end
end
 
data = data[index] or data[tonumber(index)]
data = data[index] or data[tonumber(index)]
if not data then
if not data then
return
return
end
end
 
i = i + 1
i = i + 1
end
end
end
end


-- getting sitelink of a given wiki
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
-- get sitelink of current item if qid not supplied
-- 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
function p.getSiteLink(frame)
-- uses the newer mw.wikibase calls instead of directly using the snaks
local qid = frame.args.qid
-- 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
if qid == "" then qid = nil end
p.getTAValue = function(frame)
local f = mw.text.trim( frame.args[1] or "")
local ent = mw.wikibase.getEntityObject()
local entity = mw.wikibase.getEntity(qid)
local props = ent:formatPropertyValues('P1323')
if not entity then
local out = {}
return
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
end
local link = entity:getSitelink( f )
ret = table.concat(out, "<br> ")
if not link then
if #ret == 0 then
return
ret = "Invalid TA"
end
return link
end
 
function p.Dump(frame)
local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
local data = mw.wikibase.getEntity(f.args.id)
if not data then
return i18n.warnDump
end
 
local i = 1
while true do
local index = f.args[i]
if not index then
return "<pre>"..mw.dumpObject(data).."</pre>".. i18n.warnDump
end
 
data = data[index] or data[tonumber(index)]
if not data then
return i18n.warnDump
end
 
i = i + 1
end
end
return ret
end
end


return p
return p

Versionen från 9 maj 2020 kl. 05.09

Se även Modul:Wikidataen för viss skild funktionalitet

Modulen används för att hämta formatterad data från Wikidata.

anrop:

{{#invoke:Wikidata|formatStatements|property=p17}}

Parametrar

  • property = Nödvändig parameter som beskriver vilken property som ska hämtas.
  • entityId = Det id-nummer den artikel har som du vill hämta property från.
  • enbarten = När bara ett värde ska hämtas. Tex för att hämta bild på heraldiskt vapen, och då inte få tillbaka alla objekt.
  • separator = När något annat än "," ska separera en lista på objekt. Tex separator=<br/> Se även conjunction
  • conjunction = Som ovan, men påverkar bara den sista separatorn i en lista av objekt. Default är och.
  • label = När man själv vill välja hur länken ska formateras. Tex [[Blekinge läns vapen|vapen]] fås av att ange label=vapen Den här parametern påverkar även enheter
  • pattern = När man vill hämta en sträng och passa in den i ett mönster, exempelvis för att lägga in en kod av något slag istället för $1 i https://viaf.org/viaf/$1/.
    • pattern = auktoritetsdata är ett specialfall av ovanstående. Det "pattern" som används, är då det som är angivet i P1630 (format för URL) för den berörda propertyn.
    • pattern = auktoritetsdata2 kompletterar ovanstående och skapar en länk av typen [https://viaf.org/viaf/$1/ $1]
  • rank = Bestämmer vilken typ av Claims som ska släppas igenom.
    • rank = all släpper igenom alla claims
    • rank = valid släpper igenom preferred och normal, men inte deprecated
    • rank = best (default) släpper igenom preferred, men om det inte finns släpps normal igenom
    • rank = preferred/normal/deprecated släpper igenom angiven rank, men ingen annan
  • avoidqualifier = Sorterar bort värden som är associerade med en viss property i sin qualifier. Exempelvis avoidqualifier=P518 (berörd del) om man vill ha folkmängden för hela orten, inte bara de som är kvinnor eller den andel som bor i Haninge kommun.
  • nolink = Något värde tar bort länkar, även länkar till enheter görs olänkade.
    • nounitlink = samma som ovan, men påverkar bara enheter.
  • noshortunit = enheter förkortas inte med ett värde i denna parameter, d.v.s kilometer förkortas inte till km, vilket annars är standard.
  • sortbytime = sorterar claims efter datum i qualifiers, detta system används med fördel tillsammans med parameter enbarten ovan
    • sortbytime = chronological sorterar claims i kronologisk ordning i qualifiers
    • sortbytime = inverted sorterar claims i omvänd kronologisk ordning i qualifiers
  • sortingproperty = Ange vilken property som ska stödas. Det går att lägga in en tabell i denna parameter, men då bara från en annan modul. Default är: 'P585','P571','P580','P569','P582','P570' i given ordning. Hittills stöds bara properties med datatype = time
  • sortbyarbitrary = sorterar claims efter datum de objekt som länkas i de olika statementen, exempelvis födelsedag för en rad av "barn". Tillåtna värden är 'chronological' eller 'inverted'. Vilken property som ska sökas anges med parameter 'sortingproperty ovan'.


  • langpref = I denna modul finns det ett filter som prioriterar claims som har qualifiern "språk = svenska". Ett värde på parameter langpref inaktiverar detta filter
  • noref = Ange ett värde i denna parameter om du inte är intresserad av att ta med själva källhänvisningen, utan bara datan.
  • versalisering = För att ange vilken versalisering utdatan ska ha. Tillåtna värden är: lc/uc/lcfirst/ucfirst
    • firstversalisering = Samma som ovan, men påverkar bara det första i raden av värden
  • modifytime = fixar med datumformat
    • modifytime = longdate skriver datum på formatet "30 juni 2026", dvs ner till datumnivå när så tillåts
    • modifytime = Y skriver datum på formatet "2026", dvs endast årtal.
  • modifyqualifiertime = Som ovan, men påverkar bara qualifiers
  • getsimpleproperty = För att hämta information från det länkade objektet. Denna funktion tillåter ingen iteration, utan går bara en nivå.
    • getproperty = Här anger du vilken property du ska hämta med getsimpleproperty
    • getenbarten = Här anger du om en eller alla statements ska hämtas med getsimpleproperty
    • getmodifytime = Här anger du vilket tidsformat getsimpleproperty ska hämta
    • getraw = Som "raw" nedan
  • raw = är en parameter som kan användas från andra moduler. Den resulterar i att utdatan kommer i en tabell.
  • novalue = En parameter som styr hur "novalue" på Wikidata ska presenteras här. Tomt värde ger 'nil' som resultat
  • somevalue = Som "novalue" ovan
  • relevans = Objekt som saknar en sitelink till svwiki inte kommer att inkluderas.
  • prefix = Text läggs in före svaret
  • suffix = Text läggs in efter svaret

-- Den ordning fallback language hämtas, om svensk label saknas. Engelska först, därefter bokmål, danska, etc...
local fallback = {'en', 'nb', 'da', 'nn', 'de', 'fr', 'es', 'it', 'pt'}
local i18n = {
    ["errors"] = {
        ["property-param-not-provided"] = "Property parameter not provided.",
        ["entity-not-found"] = "Entity not found.",
        ["unknown-claim-type"] = "Unknown claim type.",
        ["unknown-snak-type"] = "Unknown snak type.",
        ["unknown-datatype"] = "Unknown datatype.",
        ["unknown-entity-type"] = "Unknown entity type.",
        ["unknown-value-module"] = "You must set both value-module and value-function parameters.",
        ["value-module-not-found"] = "The module pointed by value-module not found.",
        ["value-function-not-found"] = "The function pointed by value-function not found."
    },
    ["somevalue"] = "''unknown value''",
    ["novalue"] = "''no value''"
}
local sortingproperties = {'P585','P571','P580','P569','P582','P570'}

function getqualifierbysortingproperty(claim, sortingproperty)
	for k, v in pairs(sortingproperty) do
		if claim.qualifiers and claim.qualifiers[v] and claim.qualifiers[v][1].snaktype == 'value' then
			return claim.qualifiers[v][1].datavalue.value.time 
		end
	end
	return nil
end

function getDate(claim, options)
	local sortingproperty = sortingproperties
	if type(options.sortingproperty) == 'table' then
		sortingproperty = options.sortingproperty
	elseif type(options.sortingproperty) == 'string' then
		sortingproperty = {options.sortingproperty}
	end
	return getqualifierbysortingproperty(claim, sortingproperty) 
end

function comparedates(a, b) 
	if a and b then
		return a > b
	elseif a then
		return true
	end
end

function sortbyqualifier(claims, options)
	
	table.sort(claims, function(a,b)
		local timeA = getDate(a, options)
		local timeB = getDate(b, options)
		if options.sortbytime == 'inverted' then
			return comparedates(timeB, timeA)
		else
			return comparedates(timeA, timeB)
		end
	end
	)
	return claims
end

function getLabelFromFallBack( id ) 
	local entity = getEntityFromId( id )
 	for k, v in pairs(fallback) do
		if entity.labels[v] then
			return {value = entity.labels[v].value, language = entity.labels[v].language}
		end
	end
	-- Om inget fallback-språk finns av de i variabeln ovan, så används det först definierade i objektet
	if entity.labels then 
		for v, k in pairs(entity.labels) do
			return {value = k.value, language = k.language}
		end
	end
	return {value = '-', language = ''}
end

function getEntityFromId( id )
	if id then 
		return mw.wikibase.getEntityObject( id )
	else
		return mw.wikibase.getEntityObject() 
	end
end
 
function getEntityIdFromValue( value )
    if value['entity-type'] == 'item' then
        return 'Q' .. value['numeric-id']
    elseif value['entity-type'] == 'property' then
        return 'P' .. value['numeric-id']
    else
        return formatError( 'unknown-entity-type' )
    end
end
 
function formatError( key )
    return '<span class="error">' .. i18n.errors[key] .. '</span>'
end
 
 
function formatStatements( options, ref )
   	local formattedStatements = {}
   	local claims = {}
   	if not options.property then
       	return formatError( 'property-param-not-provided' )
   	end

    if type(ref) == 'table' then -- för de fall där funktionen anropas och alla claims redan finns i en tabell
		claims = ref[options.property]
	else
 
    	--Get entity
    	local entity = nil
    	if options.entity and type( options.entity ) == "table" then
        	entity = options.entity
    	else
        	entity = getEntityFromId( options.entityId )
    	end
 
    	if not entity then
        	return '' --TODO error?
    	end
 
    	if not entity.claims or not entity.claims[options.property:upper()] then
        	return '' --TODO error?
    	end
 
    	--Format statement and concat them cleanly
		if options.rank == 'best' or not options.rank then 
			claims = entity:getBestStatements( options.property:upper() )
		elseif options.rank == 'valid' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
	    		if statement.rank == 'preferred' or statement.rank == 'normal' then
    				table.insert( claims, statement )
    			end
			end
		elseif options.rank == 'all' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				table.insert( claims, statement )
			end
		else
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				if statement.rank == options.rank then
					table.insert( claims, statement )
				end
			end
		end
		if options.avoidqualifier then
			local claims2 = {}
			for i, statement in pairs( claims ) do	
				if not statement.qualifiers or not statement.qualifiers[options.avoidqualifier:upper()] then
					table.insert( claims2, statement)
				end
			end
			claims = claims2
		end
		--om det finns vissa statements som har en qualifier som säger "språk = svenska", ta bara med dessa
		if not options.langpref or options.langpref == '' then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if statement.qualifiers and statement.qualifiers.P407 then
					for k, v in pairs( statement.qualifiers.P407 ) do
						if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 9027 then -- Q9027 = 'svenska'
							table.insert( claims2, statement )
						end
					end
				end
			end
			if #claims2 > 0 then
				claims = claims2
			end
		end
		if options.sortbytime == 'chronological' or options.sortbytime == 'inverted' then
			claims = sortbyqualifier(claims, options)
		end
	end
	if options.enbarten and options.enbarten ~= '' and #claims > 1 then
		claims = {claims[1]}
	end
	if claims then
		for i, statement in pairs( claims ) do	
			local s = formatStatement( statement, options ) 
			if s == '' then s = nil end
			if type(ref) == 'table' or (options.noref and options.noref ~='') then --Inte leta efter referenser om själva anropet görs från en referens
				table.insert( formattedStatements, s )
			else
				local t = ''--formatReferences( statement, options )
				table.insert( formattedStatements, s .. t )	
			end
		end
	end
	return mw.text.listToText( formattedStatements, options.separator, options.conjunction )
end
function formatReferences( statement, options )
	local reference = {}
	if statement.references then
		local cite = require('Modul:Cite')
		for i, ref in pairs(statement.references) do
			local items, s = {}, nil
			if ref.snaks then
				if ref.snaks.P248 then
					for j, prop in pairs(ref.snaks.P248) do
						table.insert(items, 'Q' .. prop.datavalue.value['numeric-id'])
					end
				end
				s = cite.citeitem( items, ref.snaks, options ) 
				if s == '' or not s then
					s = 'Källangivelsen på Wikidata använder propertys som inte känns igen av Modul:Cite'
				end
			end
			table.insert(reference, mw.getCurrentFrame():extensionTag( 'ref', s, {name = ref.hash} ) )
		end
	end
	return table.concat(reference)
end
function formatStatement( statement, options )
    if statement.type == 'statement' then
		return formatSnak( statement.mainsnak, options ).value 
	elseif not statement.type then
		return formatSnak( statement, options ).value --reference and qualifier
    end
	return formatError( 'unknown-claim-type' )
end
 
function formatSnak( snak, options )
    if snak.snaktype == 'somevalue' then
        return {value =  i18n['somevalue']}
    elseif snak.snaktype == 'novalue' then
        return {value = i18n['novalue']}
    elseif snak.snaktype == 'value' then
        return {value = formatDatavalue( snak.datavalue, options, snak.datatype ).value}
    else
        return {value = formatError( 'unknown-snak-type' )}
    end
end
 
function formatDatavalue( datavalue, options, datatype )
    --Use the customize handler if provided
    if options['value-module'] or options['value-function'] then
        if not options['value-module'] or not options['value-function'] then
            return {value = formatError( 'unknown-value-module' )}
        end
        local formatter = require ('Module:' .. options['value-module'])
        if not formatter then
            return {value = formatError( 'value-module-not-found' )}
        end
        local fun = formatter[options['value-function']]
        if not fun then
            return {value = formatError( 'value-function-not-found' )}
        end
        return {value = fun( datavalue.value, options )}
    end
 
    --Default formatters
    if datatype == 'wikibase-item' then
        return {value = formatEntityId( getEntityIdFromValue( datavalue.value ), options ).value}
        
    elseif datatype == 'string' or datatype == 'commonsMedia' then
        if options.pattern and options.pattern ~= '' then
        	if options.pattern == "auktoritetsdata" then
        		local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        		return {value = formatFromPattern( datavalue.value, {pattern = patter} )}
        	elseif options.pattern == "auktoritetsdata2" or options.pattern == 'auktoritetsdata3' then
        		local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        		return {value = '[' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ' ' .. datavalue.value .. ']' } 
        	else
            	return {value = formatFromPattern( datavalue.value, options )}
            end
        else
            return {value = datavalue.value}
        end
        
    elseif datatype == 'time' then
        local Time = require 'Module:Time'
        return {value = Time.newFromWikidataValue( datavalue.value ):toHtml()}
        
    elseif datatype == 'globe-coordinate' then
        local GlobeCoordinate = require 'Module:GlobeCoordinate'
        return {value = GlobeCoordinate.newFromWikidataValue( datavalue.value ):toHtml()}
    
	elseif datatype == 'quantity' then 
		local amount, unit, cat = datavalue.value.amount, datavalue.value.unit, nil
		if unit then
			unit = unit:match('Q%d+')
		end
		local formatera = require('Modul:Math')
		local number = formatera.newFromWikidataValue(datavalue.value)

		local unitraw = unit
		if unit then
			-- Kontrollerar om det finns någon förkortning för denna 'unit'
			local lab = options.label or formatStatements({property = 'P558', entityId = unit, enbarten = 'true', langpref = options.langpref, noref = 'true'})
			if lab and ( not options.nounitshort or options.nounitshort == '' )  then
				local s = formatEntityId( unit, {label = lab, nolink = (options.nounitlink or options.nolink) })
				unit = s.value
				cat = s.cat
			else -- om det inte finns en förkortning
				local s = formatEntityId( unit, {nolink = options.nounitlink})
				unit = s.value
				cat = s.cat
			end
		end
		return {value = number .. ' ' .. (unit or ''), amount = amount, unit = unit, unitraw = unitraw, cat = cat}
		
	elseif datatype == 'url' then
		if options.label and options.label ~= '' then
			return {value = '[' .. datavalue.value .. ' ' .. options.label .. ']'}
		else
			return {value = datavalue.value}
		end
		
	elseif datavalue.type == 'monolingualtext' then
		return {value = mw.text.tag('span', {title = mw.language.fetchLanguageName(datavalue.value.language, 'sv')}, datavalue.value.text)}
		
    else
        return {value = formatError( 'unknown-datatype' )}
    end
end
 
function formatEntityId( entityId, options )
	local label = options.label or mw.wikibase.label( entityId )
	if label == '' then
		label = mw.wikibase.label( entityId ) or nil
	end

    local link = mw.wikibase.sitelink( entityId )
    if link and (not options.nolink or options.nolink == '') then
        if label and label ~= '' then
            return {value = '[[:' .. link .. '|' .. label .. ']]' }
        else
            return {value = '[[:' .. link .. ']]' }
        end
    else
    	if label then
    		return {value = label}
    	else
    		local s = getLabelFromFallBack( entityId )
    		local l = mw.language.fetchLanguageName(s.language, 'sv')
    		if not l or l == '' then
    			l = 'okänt språk'
    		end
    		if s then
    			return {value = mw.text.tag('span', {title = l}, s.value), cat = 'med labels på ' .. l }
    		end
    	end
    	return {value = entityId, cat = 'som har labels med Qid'}
    end
end
 
function formatFromPattern( str, options )
    return mw.ustring.gsub( options.pattern, '$1', str ) .. '' --Hack to get only the first result of the function
end
 
local p = {}
 
function p.formatStatements( frame, key )
    local args = frame.args
 
    --If a value if already set, use it
    if args.value and args.value ~= '' then
        return args.value
    end
    return formatStatements( frame.args, key )
end
 
function p.formatStatementsFromLua( options, key )
    --If a value if already set, use it
    if options.value and options.value ~= '' then
        return options.value
    end
    local s = formatStatements( options, key )
    if s == '' then
    	s = nil
    end
    return s
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
        	entity = mw.wikibase.getEntityObject(frame.args[1])
        end
        id = entity.id
    else
        id = frame.args[1]
    end
 
    return mw.wikibase.sitelink( id )
end

-- look into entity object
function p.ViewSomething(frame)
	local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
	local id = f.args.id
	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 mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)
			else
				return tostring(data)
			end
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return
		end
		
		i = i + 1
	end
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
	ret = table.concat(out, "<br> ")
	if #ret == 0 then
		ret = "Invalid TA"
	end
	return ret
end

return p