יחידה:PropertyLink/sandbox
ניתן ליצור תיעוד על היחידה הזאת בדף יחידה:PropertyLink/sandbox/תיעוד
local FEMALE_FORM_PROPERTY = 'P2521'
local Date = require('Module:תאריך')
--[[
Fetch the "as of date" property of a associated with a property
]]
function asOfDateQualifier(claim)
local AS_OF_PROPERTY = 'P585'
local wikidataModule = require('Module:Wikidata')
local value
local error
value, error = wikidataModule.getValueOfClaim(claim, AS_OF_PROPERTY, nil)
if value then
return ' (נכון ל־'..value ..')'
end
return ''
end
local function formatQuantity(property)
local propValue = property.mainsnak and property.mainsnak.datavalue
local lang = mw.getContentLanguage()
local langCode = lang:getCode()
local asOfDate = asOfDateQualifier(property)
local localAmount = lang:formatNum( tonumber(propValue.value.amount) )
local unit = ''
if propValue.value.unit and string.match( propValue.value.unit, 'http://www.wikidata.org/entity/' ) then
local unitEntityId = string.gsub( propValue.value.unit, 'http://www.wikidata.org/entity/', '' )
if unitEntityId and #unitEntityId>0 then
-- name from label
unit = mw.wikibase.label( unitEntityId ) or ''
local unitSymbol = mw.wikibase.getBestStatements(unitEntityId, 'P5061')
-- name from properties
if unitSymbol then
local writingSystemElementId = 'Q33513' -- hebrew writing system
local langElementId = 'Q9288' -- hebrew
local labelFilter = 'P5061[language:'..langCode..'], P5061[P282:' .. writingSystemElementId .. ', P407:' .. langElementId .. ']'
local WDS = require( 'Module:WikidataSelectors' )
local labelClaims = WDS.filter( {['P5061']=unitSymbol }, labelFilter )
for r, claim in pairs( labelClaims ) do
if claim.mainsnak and claim.mainsnak.datavalue.type == 'monolingualtext' and claim.mainsnak.datavalue.value.text then
unit = claim.mainsnak.datavalue.value.text
break;
elseif claim.mainsnak and claim.mainsnak.datavalue and claim.mainsnak.datavalue.type == 'string' and claim.mainsnak.datavalue.value ~= '' then
unit = claim.mainsnak.datavalue.value
break;
end
end
end
unit = ' ' .. unit
end
end
return localAmount .. unit .. asOfDate
end
function getPropertyQualifier(property, qualifier)
local wikidataModule = require('Module:Wikidata')
local entity = mw.wikibase.getEntityIdForCurrentPage()
if not entity then return end --the entity doesnt exist or have no claims
local propertyVals = mw.wikibase.getAllStatements( entity, property )
if not propertyVals or not propertyVals[1] then return end --no such property for this item
value, error = wikidataModule.getValueOfClaim(propertyVals[1], qualifier, nil)
return value
end
local function missingLabelCategory(propertyName)
return '[[קטגוריה:ויקינתונים:ערכים_חסרי_תווית_בעברית: ' .. (mw.wikibase.label( propertyName) or propertyName) .. ']][[קטגוריה:ויקינתונים:ערכים_חסרי_תווית_בעברית]]'
end
local function getFemaleLabelForEntityId( entityId )
local WDS = require('Module:WikidataSelectors')
local femaleForm = mw.wikibase.getBestStatements(entityId, FEMALE_FORM_PROPERTY)
if not femaleForm then return nil, false end
local femLabels = WDS.filterByLanguage( femaleForm, 'he' )
if femLabels ~= nil and
femLabels[1] and
femLabels[1].mainsnak and
femLabels[1].mainsnak.datavalue and
femLabels[1].mainsnak.datavalue.value and
femLabels[1].mainsnak.datavalue.value.text then
return femLabels[1].mainsnak.datavalue.value.text
end
return nil, #femaleForm > 0
end
--[[
Get a link to specific entity. E.g sitelink|label.
* Missing label => use sitelink as fallback
* Missing sitelink => just show label
* Mssing gender form: adds category of missing gender label
@param {string} entityId - id of entity to link to (e.g Q42)
@param {string} genderAwareEntity - entity from which to fetch gender for gender form
@returns {string, bool} formattedValue, missingTranslation - the formatted value along with indicator of missing translation
]]
function formatEntity(entityId, genderAwareEntity)
local linkTarget = mw.wikibase.sitelink( entityId )
local localLabel, langLabel, missingFemaleForm
local formattedValue
local missingTranslation = false
local fallbackLanguage = false
if genderAwareEntity then
local gender = mw.wikibase.getBestStatements(genderAwareEntity, 'P21') -- P21 - gender
local isFemale = gender and
gender[1] and
gender[1].mainsnak and
gender[1].mainsnak.datavalue and
gender[1].mainsnak.datavalue.value and
(gender[1].mainsnak.datavalue.value["numeric-id"] == 6581072
or gender[1].mainsnak.datavalue.value["numeric-id"] == 1052281
or gender[1].mainsnak.datavalue.value["numeric-id"] == 15145779)
if isFemale then
localLabel, missingFemaleForm = getFemaleLabelForEntityId( entityId )
langLabel = 'he'
end
-- if we dont have/need female form label, use regular label
if localLabel == nil then
localLabel, langLabel = mw.wikibase.getLabelWithLang( entityId )
end
else
-- use Hebrew label
localLabel, langLabel = mw.wikibase.getLabelWithLang( entityId )
end
local isLocalLabel = langLabel=='he'
-- fallback if there is target but no label, use target as label
if linkTarget and not isLocalLabel then
localLabel = linkTarget
isLocalLabel = true
end
if localLabel and isLocalLabel then
if linkTarget and localLabel and linkTarget == localLabel then
formattedValue = mw.ustring.format( "[[%s]]", linkTarget )
else
formattedValue = linkTarget and localLabel and mw.ustring.format( "[[%s|%s]]", linkTarget, localLabel ) or localLabel
end
if missingFemaleForm then
mw.log(mw.ustring.format('חסרה צורת הנקבה ל"%s" (%s)', formattedValue, entityId))
formattedValue = formattedValue .. missingLabelCategory( FEMALE_FORM_PROPERTY )
end
else
missingTranslation = true
-- in that case we would unfourtanly can show only the entity id which is meaningless for users
if langLabel=='en' then
fallbackLanguage = true
formattedValue = mw.ustring.format('<span lang="en" dir="ltr">%s</span>', localLabel)
else
formattedValue = mw.ustring.format( "[[:d:%s|%s]]", entityId, entityId )
end
end
return formattedValue, missingTranslation, fallbackLanguage
end
function formatOptionalQualifiers(property, qualifiers, qualifiersSep)
if (qualifiers==nil) or (#qualifiers == 0) or (not property.qualifiers) then return '' end
qualifiersSep = qualifiersSep or ', '
local formmatedQualifiers = {}
local warnings = ''
for _, optionalQualifier in pairs( qualifiers ) do
-- handling case of "first or default" qualifier (e.g.: for 'P1/P2' take P1 if exists, otherwise - P2)
for selectableQualifier in string.gmatch(optionalQualifier, '[^/]+') do
if selectableQualifier and property.qualifiers[selectableQualifier] then
local optionalQualifierVal = mw.wikibase.formatValues(property.qualifiers[selectableQualifier])
local isQualLocalLabel = true
if optionalQualifierVal and property.qualifiers[selectableQualifier][1] and property.qualifiers[selectableQualifier][1]['datatype']=='wikibase-item' then
for i, optionalQValues in ipairs(property.qualifiers[selectableQualifier]) do
local qualLabel, qualLang = mw.wikibase.getLabelWithLang( optionalQValues['datavalue']['value']['id'] )
isQualLocalLabel = isQualLocalLabel and (qualLang=='he')
end
end
if optionalQualifierVal then
local formattedValue = '<span title="'.. mw.wikibase.label(selectableQualifier)..'" class="propertylink-wikidata-qualifier">'..mw.wikibase.formatValues(property.qualifiers[selectableQualifier]) ..'</span>'
table.insert(formmatedQualifiers, formattedValue)
break -- found first available value
end
elseif string.sub(selectableQualifier, 1, 1) ~= 'P' then
table.insert(formmatedQualifiers, selectableQualifier)
break -- found first available value
end
end
end
local res = table.concat( formmatedQualifiers, qualifiersSep)
if #formmatedQualifiers > 0 then
res = mw.ustring.format('<span style="font-size:0.9em;"> (%s)</span>', res)
end
return res .. warnings
end
--[[
Fetch property from wikidata and format it:
* if the entity or the claim doesn't exist - nil
* Formating rules:
- for entity reference - returns link to entity (using sitelink) with label as text, otherwise wikidata label as text
- for string - returns the string
- for quantity - returns the amount
- for time - returns the time as string
- for image - returns image inclusion with 250px size
* Multivalues:
Multivalue is supported with allowMulti. seperator between values defined by multiSeperator
@param {string} propertyName - name of property (e.g P123)
@param {bool} allowMulti - whether only first statement should be fetched are all statements.
@param {bool} allowNA - whether if is valid to fetch somevalue snaks: Default: nil/false
@param {string} entityId - Qid of the entity for which we fetch the data. Default: nil (page entity)
@param {string} multiSeperator - seperator between multiple values. Default: ,
@param {string} optionalQualifier - Property id of optional extra qualifier (e.g P123). will be formatted as propertyName (optionalQualifier)
@param {bool} genderAware - Fetch gender form instead of regular label
]]
function getProperty( propertyName, allowMulti, allowNA, entityId, multiSeperator, optionalQualifier, genderAware )
if propertyName==nil or #propertyName==0 then return end -- no property specified
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId == nil then return end -- entity doesnt exist
options = {
['allowMulti'] = allowMulti,
['allowNA'] = allowNA,
['seperator'] = multiSeperator or ', ',
['qualifier'] = optionalQualifier,
['entity-gender-aware'] = genderAware
}
if optionalQualifier then
options['qualifiers'] = {optionalQualifier}
end
return getPropertyByOptions(propertyName, entityId, options)
end
function property( frame )
if frame.args['entity']==nil and frame.args['title'] and #frame.args['title']>0 then
frame.args['entity'] = mw.wikibase.getEntityIdForTitle( frame.args['title'] )
if frame.args['entity']==nil then return end
end
return getProperty(string.upper(frame.args[1]), (frame.args[2] and string.len(frame.args[2])>0) or false, true, frame.args['entity'], frame.args['sep'], frame.args['q'])
end
function propertyWithGender(frame)
return getProperty(string.upper(frame.args[1]), (frame.args[2] and string.len(frame.args[2])>0) or false, true, frame.args['entity'], ', ', '', true)
end
-- formatted reference for statement. Only for non imported statements
function refStatement(statement)
if not statement.references or #statement.references == 0 then return '' end -- no reference
local formattedReferences = {}
local frame = mw.getCurrentFrame()
for j, curRef in ipairs(statement.references) do
local isImportedRef = curRef.snaks and (curRef.snaks['P143'] or curRef.snaks['P4656'])
if not isImportedRef then
if curRef.snaks['P854'] then
table.insert(formattedReferences, frame:extensionTag{ name = 'ref', content = mw.wikibase.renderSnak(curRef.snaks['P854'][1])})
elseif curRef.snaks['P2699'] then
table.insert(formattedReferences, frame:extensionTag{ name = 'ref', content = mw.wikibase.renderSnak(curRef.snaks['P2699'][1])})
else
table.insert(formattedReferences, frame:extensionTag{ name = 'ref', content = mw.wikibase.formatValues(curRef.snaks)})
end
end
end
return table.concat(formattedReferences, '')
end
--[[
Fetch property from specified entity.
@param {string} propertyName - name of property (e.g P123)
@param {string} entityId - Qid of the entity for which we fetch the data. Default: nil (page entity)
@param {table} options - table with following supported parameters:
- seperator - seperator between multiple values. Default: ,
- allowMulti - whether only first statement should be fetched are all statements.
- allowNA - whether if is valid to fetch somevalue snaks: Default: nil/false
- entity-gender-aware - Fetch gender form instead of regular label
- qualifiers - list of optional qualifers to append to property value (Example {'P1', 'P2'))
- qualifiers-sep - seperator between optional qualifiers
- img-width - width of image
]]
function getPropertyByOptions( propertyName, entityId, options )
-- verify entity exists
if entityId == nil then entityId = mw.wikibase.getEntityIdForCurrentPage() end
if entityId==nil then return end
-- defaults
options = options or {}
options['seperator'] = options['seperator'] or ', '
options['allowMulti'] = options['allowMulti'] or false
options['allowNA'] = options['allowNA'] or false
options['entity-gender-aware'] = options['entity-gender-aware'] or false -- Fetch gender form instead of regular label
options['qualifiers'] = options['qualifiers'] or {} -- fetch optional qualifiers
options['qualifiers-sep'] = options['qualifiers-sep'] or ', '
options['img-width'] = options['img-width'] or '250px'
options['source'] = options['source'] or false
options['filter'] = options['filter'] or nil
options['sort'] = options['sort'] or 'P1545'
local propertyVals = mw.wikibase.getBestStatements(entityId, propertyName)
if (not propertyVals) or (#propertyVals==0) then return end --no such property for this item
local resTable = {}
local missingTranslation = 0
local hasFallbackTransation = false
local sortByQualifier = function(t1, t2)
if t1 and t2 then
local q1 = t1.qualifiers
local q2 = t2.qualifiers
local c1 = nil
local c2 = nil
if q1 and q2 then
if q1[options['sort']] and q1[options['sort']][1] and q1[options['sort']][1].datavalue and q1[options['sort']][1].datavalue.value then
if q1[options['sort']][1].datavalue.type == 'string' then
c1 = q1[options['sort']][1].datavalue.value
elseif q1[options['sort']][1].datavalue.type == 'quantity' then
c1 = q1[options['sort']][1].datavalue.value.amount
elseif q1[options['sort']][1].datavalue.type == 'time' then
c1 = q1[options['sort']][1].datavalue.value.time
end
end
if q2[options['sort']] and q2[options['sort']][1] and q2[options['sort']][1].datavalue and q2[options['sort']][1].datavalue.value then
if q2[options['sort']][1].datavalue.type == 'string' then
c2 = q2[options['sort']][1].datavalue.value
elseif q2[options['sort']][1].datavalue.type == 'quantity' then
c2 = q2[options['sort']][1].datavalue.value.amount
elseif q2[options['sort']][1].datavalue.type == 'time' then
c2 = q2[options['sort']][1].datavalue.value.time
end
end
if c1 and c2 then
return c1<c2
elseif c1 then
return true
elseif c2 then
return false
end
elseif q1 then
return true
elseif q2 then
return false
end
else
if t1 then
return true
end
if t2 then
return false
end
end
return false
end
if options['sort'] then
table.sort(propertyVals, sortByQualifier)
end
if options['filter'] then
propertyVals = options['filter'](propertyVals)
end
for i, property in ipairs(propertyVals) do
local propValue = property.mainsnak and property.mainsnak.datavalue
if not propValue then
if options['allowNA'] and (property.mainsnak and property.mainsnak.snaktype)=='somevalue' then
return 'לא ידוע'
else
--property doesnt exist
return
end
end
local isImage = (property.mainsnak.datatype == 'commonsMedia')
if propValue['type'] == 'wikibase-entityid' then
local formattedValue, valueMissingTranslation, fallbackLang = formatEntity( propValue.value['id'], options['entity-gender-aware'] and entityId)
if not valueMissingTranslation or fallbackLang then
hasFallbackTransation = hasFallbackTransation or fallbackLang
if formattedValue then
formattedValue = formattedValue .. formatOptionalQualifiers(property, options['qualifiers'], options['qualifiers-sep'])
end
if options['source'] and property.references then
formattedValue = formattedValue.. refStatement(property)
end
table.insert(resTable, formattedValue)
else
missingTranslation = missingTranslation + 1
end
elseif propValue['type'] == 'string' then
if isImage then
table.insert(resTable, mw.ustring.format( '[[File:%s|%s]]', propValue.value, options['img-width'] ))
else
local formattedValue = propValue.value
if formattedValue then
formattedValue = formattedValue .. formatOptionalQualifiers(property, options['qualifiers'], options['qualifiers-sep'])
end
table.insert(resTable, formattedValue)
end
elseif propValue['type'] == 'monolingualtext' then
-- for monolingualtext print the language as title
local formattedValue = mw.ustring.format('<span lang="%s" title="%s">%s</span>', propValue.value.language,
mw.language.fetchLanguageName( propValue.value.language , 'he'), propValue.value.text)
table.insert(resTable, formattedValue)
elseif propValue['type'] == 'quantity' then
local formattedValue = formatQuantity(property)
if options['source'] and property.references then
formattedValue = formattedValue.. refStatement(property)
end
if formattedValue then
formattedValue = formattedValue .. formatOptionalQualifiers(property, options['qualifiers'], options['qualifiers-sep'])
end
table.insert(resTable, formattedValue)
elseif propValue['type'] == 'time' then
local timeValue = Date.newFromWikidataValue( property.mainsnak.datavalue.value ):toHebrewString()
local timeWarning = property['qualifiers'] and property['qualifiers']['P1480'] and property['qualifiers']['P1480'][1]
and property['qualifiers']['P1480'][1].datavalue and property['qualifiers']['P1480'][1].datavalue.value
if timeWarning then
timeWarning = timeWarning and timeWarning['id']
if timeWarning == 'Q5727902' then
timeValue = timeValue .. '[[Circa|?]]'
else
local circu = mw.wikibase.getLabelByLang( timeWarning, 'he' )
if circu then
timeValue = timeValue .. ' ' .. circu
end
end
end
--local timeValue = mw.wikibase.renderSnak( property.mainsnak )
timeValue = mw.ustring.gsub(timeValue, '^(%d+ %a+) (%d+)$', '[[%1]] [[%2]]')
table.insert(resTable, timeValue)
elseif propValue['type'] == 'globecoordinate' then
local frame = mw.getCurrentFrame()
local formattedValue
local globe = propValue.value.globe
if globe == 'http://www.wikidata.org/entity/Q2' then globe = nil
else
local globeMapping = require('Module:Wikidata/Globes')
if globeMapping[globe] then
globe = 'globe:' .. globeMapping[globe]
else
globe = nil
end
end
if globe then
local northSouth = (propValue.value.latitude>=0 and 'N') or 'S'
local eastWest = (propValue.value.longitude>=0) and 'E' or 'W'
formattedValue = frame:expandTemplate{ title = 'Coord', args = { math.abs(propValue.value.latitude), northSouth, math.abs(propValue.value.longitude), eastWest, globe, display = options['coord-display'] or 'inline' } }
else
formattedValue = frame:expandTemplate{ title = 'Coord', args = { propValue.value.latitude, propValue.value.longitude, display = options['coord-display'] or 'inline' } }
end
table.insert(resTable, formattedValue)
else
table.insert(resTable, mw.wikibase.formatValue( property.mainsnak ))
end
if not options['allowMulti'] then
break
end
end
if missingTranslation > 0 and #resTable> 0 then
if missingTranslation == 1 then
table.insert(resTable, 'בפסקה זו רשומה אחת נוספת שטרם תורגמה')
else
table.insert(resTable, 'בפסקה זו '..missingTranslation..' רשומות נוספות שטרם תורגמו')
end
end
-- bidi isolation - properly show mix or RTL and LTR statements
if #resTable>1 then
local isolateValues = {}
local needIsolation = false
for k,v in pairs(resTable) do
needIsolation = needIsolation or string.find( v, '[a-zA-Z]')
table.insert(isolateValues, mw.ustring.format('<span style="unicode-bidi:isolate">%s</span>', v))
end
if needIsolation then resTable = isolateValues end
end
local result = ''
-- special case * - listify
if options['seperator'] == '*' and #resTable>1 then
result = '*' .. table.concat( resTable, '\n*' )
else
result = table.concat( resTable, options['seperator'] )
end
if hasFallbackTransation or (missingTranslation > 0 ) then
result = result .. missingLabelCategory( propertyName )
end
return result
end
function getLabel( propertyName, entityId )
local entity = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not entity then return end--the entity doesnt exist or have no claims
local property = mw.wikibase.getBestStatements(entity, propertyName)
if not property or not property[1] then return end --no such property for this item
property = property[1]
local propValue = property.mainsnak.datavalue
if not propValue then return '' end --property doesnt exist
if propValue['type'] == 'wikibase-entityid' then
local label, lang = mw.wikibase.label( propValue.value['id'] )
return label
elseif propValue['type'] == 'string' then
return propValue.value
end
end
-- Return the label for property, or the label of the linked entiy of that property
function label( frame )
return getLabel( string.upper(frame.args[1] ))
end
function getItem( propertyName, entityId )
local entity = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not entity then return end--the entity doesnt exist or have no claims
local property = mw.wikibase.getBestStatements(entity, propertyName)
if not property or not property[1] then return end --no such property for this item
property = property[1]
local propValue = property.mainsnak.datavalue
if not propValue then return '' end --property doesnt exist
return propValue.value['id']
end
-- Return the Item for property, or the item of the linked entiy of that property
function item( frame )
return getItem( string.upper(frame.args[1] ))
end
function getImageLink( propName, width, align, description, border, entityId)
if not entityId then entityId = mw.wikibase.getEntityIdForCurrentPage() end -- entityId wasn't provided explicitly
if not entityId then return end --the entity doesnt exist or have no claims
local property = mw.wikibase.getBestStatements(entityId, propName or 'P18')
if property and property[1] then
if property[1].mainsnak and property[1].mainsnak.snaktype=='novalue' then
return '[[d:'..mw.wikibase.getEntityIdForCurrentPage()..'#'..(propName or "P18")..'|' ..'לא ידוע]]'
end
local width = width or "220"
local extraParameters = width..'px'
if align then extraParameters = extraParameters .. '|' .. align end
if description then extraParameters = extraParameters .. '|' .. description end
if border and (#border > 0) then extraParameters =extraParameters..'|' ..'border' end
return mw.ustring.format( '[[File:%s|%s]]', property[1].mainsnak.datavalue.value, extraParameters )
end
end
--use this function to get associated image to be used in the article
function imageLink( frame )
return getImageLink(string.upper(frame.args[1] or 'P18'), frame.args["width"], frame.args["align"], frame.args["description"], frame.args["גבול"])
end
-- returns "1" if the page has an associated wikidata entry, "" otherwise
function hasEntry()
local entity = mw.wikibase.getEntityIdForCurrentPage()
--if not entity or not entity.claims then return end --the entity doesnt exist or have no claims
if not entity then return end --the entity doesnt exist or have no claims
return 1
end
-- returns the wikidata Qid, if exists, "" otherwise
function getPageEntry(frame)
return mw.wikibase.getEntityIdForTitle(string.upper(frame.args[1] ))
end
function getSitelinksFromQid(frame)
resTable = mw.wikibase.getEntity(string.upper(frame.args[1] ))
resTable = resTable["sitelinks"]
s= "<table>\n"
for k,v in pairs(resTable) do
if v.title then
s=s.."<tr>".. "<td>" .. k.."</td>".. "<td>" .. v.title.."</td>".."</tr>" .. "\n"
end
end
return s .. "</table>"
end
local function createInterwikiForQid(frame)
local raw = mw.wikibase.getEntity( string.upper( frame.args[1] ) )["sitelinks"]
local interwikis = ''
for site, val in pairs(raw) do
truncated, found = string.gsub(site, 'wiki$', '')
truncated = string.gsub(truncated, '_', '-')
if found == 1 and truncated ~= 'he' and truncated ~= 'commons' then interwikis = interwikis .. '[[' .. truncated .. ':' .. val.title .. ']]' end
end
return interwikis
end
return {
imageLink = imageLink,
['תמונה'] = imageLink,
label = label,
['תווית'] = label,
item = item,
['פריט'] = item,
formatEntity = formatEntity,
property = property,
propertyWithGender = propertyWithGender,
['מאפיין'] = property,
getProperty = getProperty,
getPropertyByOptions = getPropertyByOptions,
getPropertyQualifier = getPropertyQualifier,
getItem = getItem,
getImageLink = getImageLink,
getLabel = getLabel,
hasEntry = hasEntry,
getPageEntry = getPageEntry,
getSitelinksFromQid = getSitelinksFromQid,
createInterwikiForQid = createInterwikiForQid,
['יש פריט'] = hasEntry
}