Module:Kinship
Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
This module shall replace Template:Kinship somewhen and allow automatic data retrieval from Wikidata. Some data useful for mapping might be found at Template:Kinship/Wikidata mapping. Some testcases can be found at Module talk:Kinship/testcases, the syntax there is still work in progress.
Currently {{#invoke:Kinship|kinship|item=Q6530}}
gives:
kinship of Henryk Hescheles, Marian Hemar and Janina Altman, parent of Tomasz Lem, single person of Barbara Lem, mother of Samuel Lem
Code
--[[
Code by Marsupium is also under CC-0, copy-paste it wherever you like!
Currently no support for:
* proper handling of all kinds of linking
* proper handling of properties with >1 value of "inverse of (P1696)"
* possibility to chose what data to retrieve/show from Wikidata:
how shall this be done????? always all for one kind of relation? not good
* qualifier "type of kinship (P1039)"
* genders in relation labels
* date qualifiers
* "partner" instead of "unmarried partner (P451)", should be supported?
* …
TODO:
* propose to rename the template to "Template:Relationship" etc.
]]
local wd = require("Module:Wikidata")
local wdLabel = require("Module:Wikidata label")
local wdGetClaims = require("Module:Wikidata/GetClaims")
local LangSwitch = require("Module:LangSwitch")
local linguistic = require("Module:Linguistic")
local city = require("Module:City")._city
local p = {}
local subject = {}
-- as of [[Template:Kinship/labels]]:
-- [[Special:PermanentLink/256815792]], 2017-08-30:
local relationDictionary = {
aunt = "Q76507",
uncle = "Q76557",
cousin = "Q23009870",
brother = "Q10861465",
brotherinlaw = "Q2914212",
daughter = "Q308194",
father = "Q7565",
grandfather = "Q9238344",
grandmother = "Q9235758",
granddaughter = "Q19756330",
grandson = "Q11921506",
grandnephew = "Q4113832",
greatgranddaughter = "Q20747487",
greatgrandson = "Q19682170",
halfbrother = "Q15312935",
halfsister = "Q2920422",
stepson = "Q4346792",
stepdaughter = "Q19822354",
husband = "Q212878",
mother = "Q7560",
nephew = "Q15224724",
niece = "Q3403377",
partner = "P451", -- no item yet (2017-09-06), same meaning? -> ask at talk!
sister = "Q595094",
sisterinlaw = "Q3238556",
son = "Q177232",
student = "Q48282",
teacher = "Q37226",
wife = "Q188830" --[[, -- more:
spouse = "Q1196129"
]]
}
function p.oneEntity(query)
-- get one entity value for a property of an entity
local result = {id = nil, label = nil}
if query.entity and query.property then
local prop = wd.getClaims({entity=query.entity, property=query.property})
if prop then
result.id = prop[1]["mainsnak"]["datavalue"]["value"]["id"]
if query.label == true and query.lang then
result.label = wdLabel._getLabel(result.id, query.lang)
end
end
end
return result.id, result.label
end
local function XofY(lang, object, args)
local xID = object["data"]["outID"]
local xName = object["data"]["outName"] or ''
local y = object["value"]
local link = nil
if args.link then
y = '[[:' .. args.link .. '|' .. y .. ']]'
elseif not args['link type'] then
-- for backwards compatability, to be considered/discussed
local page = mw.title.new( y, 'category' )
if page and page.exists then
link = 'Category:' .. y
y = "[[:Category:" .. y .. "|" .. y .. "]]"
end
else
y = city(y, lang) -- TODO: WARNING: misuse of [[Module:City]]
end
-- mimics [[Template:Kinship/link]]
-- TODO: needs change of data model of subject[prop]["template"]["value"]
-- to work with Wikidata
-- for future features see also
-- [[Module talk:City#Wikidata for places not in Module:City/data]]
-- TODO: 'link type' should overwrite link
local x = xID and wdLabel._getLabel(xID, lang, "-") or xName ..
"[[Category:Pages using Kinship template with incorrect parameter]]"
-- "-" means no link
local switch = {
de = x .. " von " .. y,
en = x .. " of " .. y,
fa = x .. y,
fr = x .. " " .. linguistic.of(y, "fr"),
-- works without raw through [[Module:Delink]], better performance without though
-- raw could be provided if wd.formatStatements is not used
-- and if [[Module:Match link]] provides raw link
hu = y .. x, -- there are no prepositions in Hungarian, only various appendages, so can't added here
it = x .. " di " .. y,
mk = x .. " на " .. y,
nl = x .. " van " .. y,
pl = args.pl and link and x .. " " .. "[[:" .. link .. "|" .. args.pl .. "]]" or
args.pl and x .. " " .. args.pl or
x .. " osoby: " .. y,
pt = x .. " de " .. y,
ru = args.ru and x .. " " .. args.ru or x .. " следующего лица: " .. y,
zh = y .. "的" .. x, -- easier to add the "的" in every case
uk = x .. " такої особи: " .. y
}
return LangSwitch._langSwitch(switch, lang)
end
function p._kinship(args)
if args.item then subject["entity"] = args.item end
local lang = args.lang
subject["relations"] = {}
subject["props"] = {}
-- old template input
if args[1] and args[2] then
subject["props"]["template"] = {}
subject["props"]["template"]["data"] = {}
subject["props"]["template"]["data"]["outName"] = args[1]
subject["props"]["template"]["data"]["outID"] = relationDictionary[string.gsub(args[1], "-", "")]
subject["props"]["template"]["value"] = args[2]
end
-- Wikidata input
local itemrelations
local relSpec = ""
local PIDs = {"P22", "P25", "P26", "P451", "P40", "P3373", "P1038", "P1066", "P802"}
local QIDs = {}
local relNames = {}
if args["itemrelations"] then
relSpec = ": " .. relSpec .. args["itemrelations"] .. "; "
PIDs = {}
local itemrelationList = mw.text.split(args["itemrelations"], ",")
for i, relStr in pairs(itemrelationList) do
local PID = string.match(relStr, "[Pp]%d+")
local QID = string.match(relStr, "[Qq]%d+")
local relName = string.match(relStr, "[%a- ]+")
if PID then
table.insert(PIDs, PID)
relSpec = relSpec .. PID
elseif QID then -- not yet implemented
table.insert(QIDs, QID)
relSpec = relSpec .. QID
elseif relName then -- not yet implemented; TODO: normalize!
table.insert(relNames, relName)
relSpec = relSpec .. relName
end
end
end
for i, prop in pairs(PIDs) do -- TODO: sort?
local propContent = wd.formatStatements({item=subject["entity"], property=prop,link='wikipedia',lang=lang})
--[[ TODO: formatStatements shouldn't be used, it should be formatted later for gender distinction: ->
-- local propStatement = wd.getClaims({entity=subject["entity"], property=prop})
-- TO COME!!!! TODO: what does this give?
]]
if propContent then
subject["props"][prop] = {}
subject["props"][prop]["value"] = propContent
subject["props"][prop]["data"] = {}
-- symmetric property: "instance of (P31)": "symmetric property (Q18647518)"
local propInstanceOf = wd.getClaims({entity=prop, property="P31"})
local isSymmetric = false
for i,j in pairs(propInstanceOf) do
if wdGetClaims.hastargetvalue(j, "Q18647518") then
isSymmetric = true
end
end
if isSymmetric then
subject["props"][prop]["data"]["outID"] = prop
else
-- get "opposite of (P461)" of "subject item of this property (P1629)" of the property
local propSubjItem = p.oneEntity({entity=prop, property="P1629"})
-- assumes there is just one "subject item of this property (P1629)"
subject["props"][prop]["data"]["outID"] =
p.oneEntity({entity=propSubjItem, property="P461", lang=lang})
-- assumes there is just one "opposite of (P461)"
-- if that didn't work, get "subject item of this property (P1629)" of "inverse of (P1696)" of the property
if not subject["props"][prop]["data"]["outID"] then
local propInverseProp = p.oneEntity({entity=prop, property="P1696"})
-- assumes there is just one "inverse of (P1696)"
-- FIXME: this is wrong e.g. for "child (P40), but that isn't retrieved anyway
subject["props"][prop]["data"]["outID"] =
p.oneEntity({entity=propInverseProp, property="P1629", lang=lang})
end
end
end
end
-- build strings
for i, j in pairs(subject["props"]) do
local i18nStr = XofY(lang, j, args)
local relation = i18nStr
table.insert(subject["relations"], relation)
end
return table.concat(subject.relations, ", ") --.. relSpec, subject -- TODO: relSpec for testing
end
function p.kinship(frame)
local args = {}
for name, value in pairs(frame:getParent().args) do
local trimmedValue = value:gsub("^%s*(.-)%s*$", "%1")
if trimmedValue ~= "" then
args[name] = trimmedValue
end
end
for name, value in pairs(frame.args) do
local trimmedValue = value:gsub("^%s*(.-)%s*$", "%1")
if trimmedValue ~= "" then
args[name] = trimmedValue
end
end
-- if no language is set get user's chosen language
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
args.lang = frame:callParserFunction( "int", "lang" )
end
local results = p._kinship(args)
return results
end
function p.test()
local args = {}
args[1] = "child"
args[2] = "John Doe"
args["item"] = "Q981558"
args["lang"] = "de"
local results, subject = p._kinship(args)
return subject
end
return p