Module:Wikidata4Bio
提供: VANGUARD FLIGHT wiki
Module:Wikidata4Bio (talk<dot-separator>edit<dot-separator>hist<dot-separator>links<dot-separator>doc<dot-separator>subpages<dot-separator>tests / results<dot-separator>sandbox<dot-separator>all modules)
- Usage
- This module is used by:
- {{VN}} to display all the different language vernaculare names
- Some templates of Biology external link templates (like {{NCBI}}) to compare their identifier parameter with the identifier stored in wikidata. When they are different, an error is displayed and Category:Pages with biology property different than on Wikidata is added.
- Module:Wikidata4Bio/sandbox is the sandbox of this module (to test new developments) which is used in the sandbox template {{VN/sandbox}}
- How to improve and test this module
- developp your modification in Module:Wikidata4Bio/sandbox, the sandbox of this module
- verify your changes in Module:Wikidata4Bio/sandbox/testcases
- verify your changes in {{VN}} in :
- Ailanthus altissima by replacing {{VN}} by {{VN/sandbox}}
- Bombycillidae, Cinclidae: multiple VN: Only the global one with useWikidata=true should have interwiki in VN
- Rhipiduridae: multiple VN though inclusion of Rhipidura: Only the global one with useWikidata=true should use wikidata in VN
- Eremogone congesta: the scientific name is Eremogone congesta but also Arenaria congesta
- verify your changes in {{ITIS}} in :
- Chionis alba: 2 ITIS should not display error
- Pternistis, Merlangius merlangus, Boreogadus saida: 2 ITIS should not display error even if included from their category (still a bug)
- report your modifications in Module:Wikidata4Bio
- verify your changes in Module:Wikidata4Bio/testcases
- verify your changes in Ailanthus altissima with normal {{VN}}
-- global variable which receives debug info if not nil
_debug=Nil
-- tableIsEmpty return true if the parameter mytable is Nil or empty
function tableIsEmpty(mytable)
if not mytable then
return true
end
for key, value in pairs(mytable) do
return false
end
return true
end
-- addDebug() adds debug/verbose/trace info to _debug
function addDebug(lang, functionName, text)
if not _debug then
return
end
local index
if lang then
index = 'Lang ' .. lang
else
index = functionName .. '()'
end
local previousText = _debug[index]
if previousText then
previousText = previousText .. ', '
else
previousText = ''
end
if functionName and lang then
previousText = previousText .. functionName .. ': ' .. text
else
previousText = previousText .. text
end
_debug[index] = previousText
end
-- getDebug() returns a formated version of _debug for the display
function getDebug()
if not _debug then
return ''
end
if tableIsEmpty(_debug) then
return ''
end
-- Sort _debug into debug2
debug2 = {}
for key, value in pairs(_debug) do
table.insert(debug2,{key,value})
end
table.sort(debug2, function(t1,t2) return t1[1] < t2[1] end)
-- Serialize debug2 in displayedDebug
displayedDebug = '<BR/>Debug:'
for key, value in pairs(debug2) do
displayedDebug = displayedDebug .. '<BR/>- ' .. value[1] .. ': ' .. mw.text.nowiki(value[2])
end
-- Clear debug:
_debug={}
return displayedDebug
end
-- dumpPath() is an advanced tostring(). It is recursive and displays 1 ligne per significant value.
-- For exemple dumpPath('entity', mw.wikibase.getEntity()) will generate:
-- entity.type=string:item
-- entity.sitelinks.nlwiki.title=string:Nachtorchis
-- entity.sitelinks.nlwiki.site=string:nlwiki
-- entity.sitelinks.plwiki.title=string:Podkolan
-- entity.sitelinks.plwiki.site=string:plwiki
-- ...
-- entity.descriptions.es.language=string:es
-- entity.descriptions.es.value=string:'género de plantas de la familia Orchidaceae'
-- entity.descriptions.de.language=string:de
-- entity.descriptions.de.value=string:'Gattung der Familie der Orchideen (Orchidaceae)'
-- ...
-- entity.id=string:Q161849
-- entity.claims.p910[0].mainsnak.snaktype=string:value
-- entity.claims.p910[0].mainsnak.property=string:P910
-- entity.claims.p910[0].mainsnak.datavalue.value.numeric-id=number:8765698
-- entity.claims.p910[0].mainsnak.datavalue.value.entity-type=string:item
-- entity.claims.p910[0].mainsnak.datavalue.type=string:wikibase-entityid
-- entity.claims.p910[0].type=string:statement
-- entity.claims.p910[0].id=string:Q161849$10B4A9CE-CF8C-4D2D-A0E0-AE494A71EBE1
function dumpPath(path,value)
if not value then
return path .. '=Nil'
end
local valueType = type(value)
local valueStr = path .. '=' .. valueType .. ':'
if valueType == 'table' then
valueStr = ''
for key, subvalue in pairs(value) do
if string.len(valueStr) < 60000 and value ~= subvalue then
if valueStr ~= '' then
valueStr = valueStr .. '\n'
end
if (type(key) == 'number') then
valueStr = valueStr .. dumpPath(path .. '[' .. key .. ']',subvalue)
else
valueStr = valueStr .. dumpPath(path .. '.' .. key,subvalue)
end
end
end
else
return valueStr .. dumpValue(value,false)
end
return valueStr
end
function dumpValue(value,withType)
if not value then
return 'Nil'
end
local valueType = type(value)
local valueStr = ''
if withType then
valueStr = valueType .. ':'
end
if valueType == 'table' then
elseif valueType == 'string' then
if string.find(value, ' ', 1, true) then
valueStr = valueStr .. "'" .. value .. "'"
else
valueStr = valueStr .. value
end
elseif valueType == 'number' then
return valueStr .. value
elseif valueType == 'boolean' then
return valueStr .. tostring(value)
end
return valueStr
end
-- getTextAsAsciiCode('Paphiopedilum') returns '112.104.105.111.112.101.100.105.108.117.109'
function getTextAsAsciiCode(stri)
local result = ''
for i = 1, string.len(stri) do
result = result .. '.' .. string.byte(string.sub(stri, i, i))
end
return result
end
-- getProperty(entity, true, {'claims','P301',0,'mainsnak','datavalue','value'}) does the same as
-- entity.claims.P301[0].mainsnak.datavalue.value except that it will never generate an error.
-- Instead of an error it will return Nil if verbose==false or an explanation (like 'entity.claims.P301[0] = Nil') if verbose
function getProperty(entity, verbose, propertyPath)
local property = entity
local currentPath = 'entity'
for index, propertyPathItem in pairs(propertyPath) do
property = property[propertyPathItem]
if verbose then
if (type(propertyPathItem) == 'number') then
currentPath = currentPath .. '[' .. propertyPathItem .. ']'
else
currentPath = currentPath .. '.' .. propertyPathItem
end
end
if not property then
if verbose then
return currentPath .. " = Nil"
else
return Nil
end
end
end
return property
end
-- suppressCategory() returns "Platanthera" out of "Category:Platanthera"
function suppressCategory(category)
local twoPointStartPos, twoPointEndPos = string.find(category, ':', 1, true)
if twoPointStartPos then
category = string.sub(category,twoPointEndPos+1)
end
return category
end
-- suppressDisambiguation() returns "Platanthera" out of "Platanthera (genus)"
function suppressDisambiguation(name)
name = string.gsub(name, '_', ' ')
local start = string.find(name, '(', 1, true)
if not start then
return name
end
local endp = string.find(name, ')', start, true)
if not endp then
return name
end
local part1 = mw.text.trim(string.sub(name, 1, start-1))
local part2 = mw.text.trim(string.sub(name, endp+1))
if string.len(part1) == 0 then
return part2
elseif string.len(part2) == 0 then
return part1
else
return part1 .. ' ' .. part2
end
end
-- isLink(name) return true when name is a link syntax like '[[sdfs|dfsfsd]]'
function isLink(name)
if not name then
return false
end
if string.find(name, ']]', 1, true) then
return true
end
if string.find(name,'[[', 1, true) then
return true
end
return false
end
-- tableToString() returns a string out of a table for debug and non regression purpose
-- sorted by keys, only values are dumped
function tableToString(mytable)
-- Sort mytable into mytable2
mytable2 = {}
for key, value in pairs(mytable) do
table.insert(mytable2,{key,value})
end
table.sort(mytable2, function(t1,t2) return t1[1] < t2[1] end)
-- Serialize mytable2 into display
local display = Nil
for key, value in pairs(mytable2) do
if display then
display = display .. ', ' .. value[2]
else
display = value[2]
end
end
if not display then
return ''
end
return display
end
-- global variable which stores the result of getScientificNamesFromWikidata()
_scientificNamesFromWikidata = Nil
-- getScientificNamesFromWikidata() return a dictionary containing all the scientific names described by wikidata property P225
function getScientificNamesFromWikidata()
if _scientificNamesFromWikidata then
return _scientificNamesFromWikidata
end
_scientificNamesFromWikidata = {}
if not mw.wikibase then
-- wikidata library is not enabled
return _scientificNamesFromWikidata
end
local entity = mw.wikibase.getEntity()
if entity then
local p225 = getProperty(entity, false, {'claims', 'P225'})
if p225 then
local index = 0
local name = ''
while name do
name = getProperty(p225, false, {index , 'mainsnak', 'datavalue', 'value'})
if name then
name = mw.text.trim(name)
_scientificNamesFromWikidata[name] = name
index = index + 1
end
end
end
end
addDebug(Nil,'getScientificNamesFromWikidata',tableToString(_scientificNamesFromWikidata))
return _scientificNamesFromWikidata
end
-- global variable which stores the result of getScientificNames()
_scientificNames = Nil
-- getScientificNames() return a dictionary containing all the possible lowercase scientific names of the taxon described out of:
-- * current category/gallery name (which is supposed to be a scientific name)
-- * {{pagename}}
-- * wikidata property P225 (via getScientificNamesFromWikidata())
function getScientificNames()
if _scientificNames then
return _scientificNames
end
_scientificNames = {}
local name = string.lower(suppressDisambiguation(mw.title.getCurrentTitle().text))
_scientificNames[name] = name
name = "''" .. name .. "''"
_scientificNames[name] = name
name = "{{pagename}}"
_scientificNames[name] = name
name = "''{{pagename}}''"
_scientificNames[name] = name
for key, value in pairs(getScientificNamesFromWikidata()) do
name = string.lower(value)
_scientificNames[name] = name
name = "''" .. name .. "''"
_scientificNames[name] = name
end
addDebug(Nil,'getScientificNames',tableToString(_scientificNames))
return _scientificNames
end
-- isScientificName(name) return true when name == the category/gallery name, which is supposed to be the scientific name
function isScientificName(name)
if not name then
return false
end
name = string.lower(suppressDisambiguation(mw.text.trim(name)))
getScientificNames()
if _scientificNames[name] then
return true
else
return false
end
end
-- getVNFromWikidataInterwiki() returns the VernacularName from wikidata interwiki for a specific lang
-- (if different from {{PAGENAME}} which is supposed to be the scientific name)
function getVNFromWikidataInterwiki(entity,lang,interwiki)
if interwiki then
interwiki = suppressCategory(interwiki)
if isScientificName(interwiki) then
-- this gallery/category interwiki is the scientific name (not vernaculare)
return Nil
else
return interwiki
end
else
return Nil
end
end
-- getVNFromWikidataLabel() returns the VernacularName from wikidata label for a specific lang
-- (if different from {{PAGENAME}} which is supposed to be the scientific name)
function getVNFromWikidataLabel(entity,lang)
local label = getProperty(entity, false, {'labels', lang, 'value'})
if label then
label = suppressCategory(label)
if isScientificName(label) then
-- this gallery/category label is the scientific name (not vernaculare)
return Nil
else
return label
end
else
return Nil
end
end
-- strContains(long,small) is an improvment of string.find(longlower, smalllower)
-- it is case insensitiv + also return true is long == small
function strContains(long,small)
if not long or not small then
return false
end
local longlower = string.lower(long)
local smalllower = string.lower(small)
return longlower == smalllower or string.find(longlower, smalllower, 1, true)
end
-- calcVNEntry() puts together the different info coming from VN parameters (lang & default) and wikidata (interwiki & vnFromWikidata)
function calcVNEntry(lang,interwiki,vnFromWikidata,vnSource,default)
local vnEntry = vnFromWikidata
local vnEntryDescription = vnSource
if interwiki then
vnEntry = '[[:' .. lang .. ':' .. interwiki .. '|' .. vnFromWikidata .. ']]'
vnEntryDescription = 'bis: [[interwiki|' .. vnSource .. ']]'
else
vnEntryDescription = ': ' .. vnEntryDescription
end
if default then
if strContains(vnFromWikidata,default) then -- strContains(long,small)
-- default is in vnFromWikidata => no need to display default
-- example: default='cat' vnFomInterwiki='common cat'
addDebug(lang,Nil,'VNparameter rejected as contained in ' .. vnSource .. ', Case1' .. vnEntryDescription)
return vnEntry
else
if strContains(default,vnFromWikidata) then -- strContains(long,small)
-- vnFromWikidata is in default => no need to display vnFromWikidata
-- example: default='[[:en:cat|]]' vnFomInterwiki='cat'
if isLink(default) then
addDebug(lang,Nil,vnSource .. ' rejected as contained in VNparameter which is a link, Case2: VNparameter')
return default
else
if interwiki then
addDebug(lang,Nil,vnSource .. ' rejected as contained in VNparameter, Case3: [[interwiki|parameter]]')
return '[[:' .. lang .. ':' .. interwiki .. '|' .. default .. ']]'
else
-- happens when VN is called with de= + wikidata has no 'de' interwiki + wikidata has a 'de' label + VN|de= contains 'de' label
addDebug(lang,Nil,vnSource .. ' rejected as contained in VNparameter + no interwiki, Case4: VNparameter')
return default
end
end
else
addDebug(lang,Nil,'Case5' .. vnEntryDescription .. ', VNparameter')
return vnEntry .. ', ' .. default
end
end
else
addDebug(lang,Nil,'Case6' .. vnEntryDescription)
return vnEntry
end
end
-- getVernacularNameFromWikidata() returns a vernacular name (often in form of a wiki link) for getVNEntry()
function getVernacularNameFromWikidata(entity,lang,default,useWikidata)
if not useWikidata then
return default
end
if not entity then
-- This gallery/category has no wikidata element (you are perhaps in the template page)
return default
end
if default and string.len(default) == 0 then
default = Nil
end
if isScientificName(default) then
addDebug(lang,Nil,'VNparameter is a scientificName')
default = Nil
end
-- First try entity.sitelinks.frwiki.title (interwiki)
local interwiki = getProperty(entity, false, {'sitelinks', lang .. 'wiki', 'title'})
local vnFomInterwiki = getVNFromWikidataInterwiki(entity,lang,interwiki)
if vnFomInterwiki then
return calcVNEntry(lang,interwiki,vnFomInterwiki,'interwiki',default)
else
-- Second try 'entity.labels.fr.value'
local vnFromLabel = getVNFromWikidataLabel(entity,lang)
if vnFromLabel then
return calcVNEntry(lang,interwiki,vnFromLabel,'label',default)
else
-- Interwiki and label are not provided or are scientific name
if default and not isLink(default) and interwiki then
addDebug(lang,Nil,'Case7: [[interwiki|VNparameter]]')
if lang == 'en-us' then
lang = 'en'
end
return '[[:' .. lang .. ':' .. interwiki .. '|' .. default .. ']]'
end
if default then
addDebug(lang,Nil,'Case8: VNparameter')
else
-- no need to to a trace if no interwiki, no label, no VNparameter
end
return default
end
end
end
-- getVNEntry() returns HTML for one language in getVN()
function getVNEntry(entity,lang,default,useWikidata,bold)
local vercularName = getVernacularNameFromWikidata(entity,lang,default,useWikidata)
if vercularName and string.len(vercularName) > 0 then
local success, langName = pcall(mw.language.fetchLanguageName, lang, lang)
if lang == 'en-us' then
success = true
langName = 'American'
lang = 'en'
end
if success and langName then
local entry = "'''" .. langName .. ":"
if not bold then
entry = entry .. "'''"
end
entry = entry .. ' <span class="vernacular" lang="' .. lang .. '">' .. vercularName .. "</span> "
if not bold then
entry = entry .. "'''"
end
entry = entry .. "·''' "
return entry;
else
return "Unknown lang '" .. lang .. "'"
end
else
return nil
end
end
local languages = {
'aa', 'ab', 'af', 'ak', 'als', 'am', 'an', 'ang', 'ar', 'arc', 'arn', 'arz', 'as', 'ast', 'av', 'ay', 'az',
'ba', 'bar', 'bat-smg', 'bcl', 'be', 'be-x-old', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'bpy', 'br', 'bs', 'bug', 'bxr',
'ca', 'cbk-zam', 'cdo', 'ce', 'ceb', 'ch', 'cho', 'chr', 'chy', 'co', 'cr', 'crh', 'cs', 'csb', 'cu', 'cv', 'cy',
'da', 'de', 'diq', 'dk', 'dsb', 'dv', 'dz',
'ee', 'el', 'eml', 'en', 'en-us', 'eo', 'es', 'et', 'eu', 'ext',
'fa', 'ff', 'fi', 'fiu-vro', 'fj', 'fo', 'fr', 'frp', 'frr', 'fur', 'fy',
'ga', 'gan', 'gd', 'gl', 'glk', 'gn', 'got', 'gu', 'gv',
'ha', 'hak', 'haw', 'he', 'hi', 'hif', 'ho', 'hr', 'hsb', 'ht', 'hu', 'hy', 'hz',
'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'ilo', 'io', 'is', 'it', 'iu',
'ja', 'jbo', 'jv',
'ka', 'kaa', 'kab', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'koi', 'kr', 'ks', 'ksh', 'ku', 'kv', 'kw', 'ky',
'la', 'lad', 'lb', 'lbe', 'lg', 'li', 'lij', 'lmo', 'ln', 'lo', 'lt', 'lv',
'map-bms', 'mdf', 'mg', 'mh', 'mhr', 'mi', 'mk', 'ml', 'mn', 'mo', 'mov', 'mr', 'mrc', 'mrj', 'ms', 'mt', 'mus', 'my', 'myv', 'mzn',
'na', 'nah', 'nan', 'nap', 'nb', 'nds', 'nds-nl', 'ne', 'new', 'ng', 'nl', 'nn', 'no', 'nov', 'nrm', 'nv', 'ny',
'oc', 'om', 'ood', 'or', 'os',
'pa', 'pag', 'pam', 'pap', 'pcd', 'pdc', 'pi', 'pih', 'pl', 'pms', 'pnt', 'ps', 'pt', 'pt-br',
'qu',
'rm', 'rmy', 'rn', 'ro', 'roa-rup', 'roa-tara', 'ru', 'rw',
'sa', 'sah', 'sc', 'scn', 'sco', 'sd', 'se', 'sei', 'sg', 'sh', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'srn', 'ss', 'st', 'stq', 'su', 'sv', 'sw', 'szl',
'ta', 'te', 'tet', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to', 'tp', 'tpi', 'tr', 'ts', 'tt', 'tum', 'tw', 'ty',
'udm', 'ug', 'uk', 'ur', 'uz',
've', 'vec', 'vi', 'vls', 'vo',
'wa', 'war', 'wo', 'wuu',
'xal', 'xh',
'yi', 'yo',
'za', 'zea', 'zh', 'zh-classical', 'zh-hans', 'zh-hant', 'zh-min-nan', 'zh-tw', 'zh-yue', 'zu'
}
-- isTrue() transforms a string into a bool
-- Nil, '', '0', 'false', 'no' return false
-- other values return true
function isTrue(stringValue)
if not stringValue then
return false
end
if string.len(stringValue) == 0 then
return false
end
stringValue = string.lower(mw.text.trim(stringValue))
if stringValue == '0' or stringValue == 'false' or stringValue == 'no' then
return false
end
return true
end
-- getCurrentNamespace() returns the current namespace ('gallery' instead of '')
function getCurrentNamespace()
local namespace = string.lower(mw.title.getCurrentTitle().nsText)
if string.len(namespace) == 0 then
namespace = 'gallery'
end
return namespace
end
-- isCurrentNamespaceACategoryOrAGallery() returns true for category and gallery
function isCurrentNamespaceACategoryOrAGallery()
local namespace = string.lower(mw.title.getCurrentTitle().nsText)
if string.len(namespace) == 0 then
return true
elseif namespace == 'category' then
return true
else
return false
end
end
-- findTemplate() return the position of the first call of <templateName> after startPos
function findTemplate(wikicode,templateName,templateForms,templateFormsDebug,startPos)
local firstPos = Nil
for index, templateForm in pairs(templateForms) do
local currentPos = string.find(wikicode,templateForm,startPos,true)
if currentPos then
--addDebug(Nil,'findTemplate','Found ' .. templateFormsDebug[index] .. ' at pos ' .. currentPos)
if firstPos then
firstPos = math.min(currentPos,firstPos)
else
firstPos = currentPos
end
end
end
--if firstPos then
--addDebug(Nil,'findTemplate','Finaly: Found ' .. templateName .. ' starting from ' .. startPos .. ' at pos ' .. firstPos)
--else
--addDebug(Nil,'findTemplate','Finaly: Found no ' .. templateName .. ' starting from ' .. startPos)
--end
return firstPos
end
-- isTemplateCalledOnlyOnce() returns true if there are 0..1 call of <templateName> in the calling page or false if there are 2 or more
function isTemplateCalledOnlyOnce(templateName,templateForms,templateFormsDebug)
local wikicode = mw.title.getCurrentTitle():getContent()
if not wikicode then
-- Called from preview before creation of page
return false
end
if not templateFormsDebug then
templateFormsDebug = templateForms
end
local firstPos = findTemplate(wikicode,templateName,templateForms,templateFormsDebug,1)
if not firstPos then
-- There is a bug
--addDebug(Nil,'isTemplateCalledOnlyOnce','no ' .. templateName .. ' found (strange)')
return true
end
firstPos = findTemplate(wikicode,templateName,templateForms,templateFormsDebug,firstPos+3)
if firstPos then
-- There is at least 2 calls
--addDebug(Nil,'isTemplateCalledOnlyOnce','multiple ' .. templateName .. ' found => return false')
return false
else
-- Only one call to template
--addDebug(Nil,'isTemplateCalledOnlyOnce','single ' .. templateName .. ' found => return true')
return true
end
end
nvForms = {'{{VN|', '{{VN\n', '{{VN ', '{{VN/', '{{VN}'}
nvFormsDebug = {'{{VN|', '{{VN<cr>', '{{VN<space>', '{{VN/', '{{VN}'}
-- isVnCalledOnlyOnce() returns true if there are 0..1 VN in the calling page or false if there are 2.. VN
function isVnCalledOnlyOnce()
return isTemplateCalledOnlyOnce('VN',nvForms,nvFormsDebug)
end
-- verifyVNParameter() returns Nil when a VN parameter is accepted or an error category when the parameter is incorrect
function verifyVNParameter(default)
if not default then
return Nil
end
if isScientificName(default) and default ~= 'Aves' then
return ' [[Category:Pages with incorrect biology template usage|VN]] '
elseif string.find(default, "'''", 1, true) then
-- default contains bold
return ' [[Category:Pages with incorrect biology template usage|BoldOrItalic]] '
elseif (string.sub(default, 1, 2) == "''") then
-- default starts with italic
if string.find(default, "'':", 1, true) then
-- Correct: |ja=''Vespa mandarinia japonica'': XXX
-- Incorrect: |en='''[[:en:whatever|]]'''
elseif string.find(default, 'fossil specimens', 1, true) then
-- Correct: |ja=''Oudenodon'' fossil specimens
elseif string.find(string.lower(default), 'hybrid', 1, true) then
-- Correct: |de=''Ara''-Hybride
-- Correct: |en=''Ara'' hybrids
elseif string.find(string.lower(default), 'cultivars', 1, true) then
-- Correct: |de=''Neoreglia'' cultivars
else
-- Incorrect: |en=''Vespa mandarinia japonica''
return ' [[Category:Pages with incorrect biology template usage|BoldOrItalic]] '
end
end
return Nil
end
function trimOrNullify(str)
if not str then
return Nil
end
str = mw.text.trim(str)
if str == '' then
return Nil
end
return str
end
-- getVN() is called by Template:VN
function getVN(options)
local useWikidata = isTrue(options.useWikidata)
local useWikidataIsCalculated = not options.useWikidata or string.len(options.useWikidata) == 0
if useWikidataIsCalculated and mw.wikibase then
local sciname = trimOrNullify(options.sciname)
if sciname then
-- isScientificName(sciname) returns true if sciname==<category or gallery name>
useWikidata = isScientificName(sciname)
addDebug(Nil,'getVN','useWikidata not set but sciname=' .. sciname .. ' => using useWikidata=equalsCategoryName()=' .. tostring(useWikidata))
else
useWikidata = isVnCalledOnlyOnce()
addDebug(Nil,'getVN','useWikidata not set and sciname not set => using useWikidata=isVnCalledOnlyOnce()=' .. tostring(useWikidata))
end
end
local entity = Nil
if mw.wikibase then
-- wikidata library is enabled
entity = mw.wikibase.getEntity()
end
local userLang = options.lang
local default = options[userLang]
local additionalCategory = ''
local vn = ''
local vnEntry = getVNEntry(entity,userLang,default,useWikidata,true)
if vnEntry then
vn = vnEntry
end
for index, lang in pairs(languages) do
default = options[lang]
local verification = verifyVNParameter(default,additionalCategory)
if verification then
additionalCategory = verification
end
if lang == userLang then
-- Already displayed in bold
else
vnEntry = getVNEntry(entity,lang,default,useWikidata,false)
if vnEntry then
vn = vn .. vnEntry
end
end
end
if string.len(vn) == 0 then
vn = 'No common name has yet been provided in this ' .. getCurrentNamespace()
if not mw.wikibase then
-- wikidata library is not enabled
vn = vn .. '. (Soon common names will be retrieved from wikidata)'
elseif useWikidata then
if entity then
vn = vn .. ' nor in [[wikidata:' .. entity.id .. '|wikidata]]'
else
vn = vn .. ' and no [https://www.wikidata.org/w/index.php?button=&title=Special%3ASearch&search=' .. string.gsub(mw.title.getCurrentTitle().text,' ','+') .. ' wikidata item] is associated with it'
end
else
if useWikidataIsCalculated then
-- useWikidata= not provided + (sciname!=<category or gallery name> or multiple VN in page) => don't display additional info in all VN
else
if entity then
vn = vn .. '. <small>(You could activate the search in [[wikidata:' .. entity.id .. '|wikidata]] by adding useWikidata=1 inside {{VN}} )</small>'
else
vn = vn .. '. <small>(No [https://www.wikidata.org/w/index.php?button=&title=Special%3ASearch&search=' .. string.gsub(mw.title.getCurrentTitle().text,' ','+') .. ' wikidata item] is associated with this ' .. getCurrentNamespace() .. ')</small>'
end
end
end
else
if not mw.wikibase then
-- wikidata library is not enabled
elseif not entity then
vn = vn .. ' <small>(Note: no [https://www.wikidata.org/w/index.php?button=&title=Special%3ASearch&search=' .. string.gsub(mw.title.getCurrentTitle().text,' ','+') .. ' wikidata item] is associated with this ' .. getCurrentNamespace() .. ')</small>'
end
end
return vn .. additionalCategory
end
-- Compares the ITIS identifior provided to {{ITIS}} with the id stored in wikidata by property p815
-- If there is a difference, the returned string displays an error + adds category 'Pages with incorrect biology template usage'
-- See https://www.wikidata.org/wiki/Wikidata:Taxonomy_task_force for sitePropertyId
function compareSiteIdWithWikidata(frame, sitePropertyId, siteName, templateName, templateForms)
if not isCurrentNamespaceACategoryOrAGallery() then
-- We do checks only in galleries and categories (When you look at Template, no param is provided
return ''
end
local commonsSiteId = trimOrNullify(frame.args['1'])
if not commonsSiteId then
return ' Error: no ' .. siteName .. ' id has been provided. [[Category:Pages with incorrect biology template usage|id]]'
end
local commonsSciName = trimOrNullify(frame.args['sciname'])
if not commonsSciName then
return ' Error: no ' .. siteName .. ' sciName has been provided. [[Category:Pages with incorrect biology template usage|sciname]]'
end
local validity = trimOrNullify(frame.args['validity'])
if validity then
validity = string.lower(validity)
if validity == 'nv' then
-- taxon is invalid => no check is possible
return ''
else
-- validity parameter has an incorrect value
return ' Error: Incorrect parameter validity [[Category:Pages with incorrect biology template usage|validity]]'
end
end
local checks = trimOrNullify(frame.args['checks'])
if checks and string.lower(checks) == 'no' then
-- checks have been disabled
return ''
end
if not mw.wikibase then
-- Wikidata library is not enabled => no check is possible
return ''
end
local entity = mw.wikibase.getEntity()
if not entity then
-- There is no link to wikidata => no check is possible
return ''
end
if not isTemplateCalledOnlyOnce(templateName,templateForms,templateForms) then
-- If template is called multiple times...
return ''
end
if commonsSciName ~= 'none' then
getScientificNamesFromWikidata()
if not tableIsEmpty(_scientificNamesFromWikidata) then
if not _scientificNamesFromWikidata[commonsSciName] then
return ' <small>(Warning: different scientific name between [[wikidata:' .. entity.id .. '|wikidata]] (' .. tableToString(_scientificNamesFromWikidata) .. ') and wikicommons (' .. commonsSciName .. '))</small>[[Category:Pages with biology property different than on Wikidata|' .. siteName .. ']]'
end
end
end
local wikidataSiteId = trimOrNullify(getProperty(entity, false, {'claims', sitePropertyId, 0 , 'mainsnak', 'datavalue', 'value'}))
if not wikidataSiteId then
-- Property (like p815 for 'identifiant ITIS') is not defined in wikidata => no check possible
return ''
elseif wikidataSiteId == commonsSiteId then
-- Both identifier are equal: perfect
return ''
else
return ' <small>(Warning: different ' .. siteName .. ' Id between [[wikidata:' .. entity.id .. '|wikidata]] (' .. wikidataSiteId .. ') and wikicommons (' .. commonsSiteId .. '))</small>[[Category:Pages with biology property different than on Wikidata|' .. siteName .. ']]'
end
end
-- This function is called by User:Liné1/sandbox2 to discover Lua ;-)
function test(frame,args)
--local text = ''
--return mw.text.nowiki(mw.title.getCurrentTitle():getContent())
addDebug('fr','myfunction','hello')
addDebug('fr','yourfunction','salut')
addDebug('de','myfunction','hello')
return getDebug()
end
----------------------------------------------------------------------------------------------------------------
---------- PUBLIC FUNCTIONS ------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
local p = {}
function p.getVN(frame)
local vn = getVN(frame.args)
-- Now add debug traces if activated
if _debug then
vn = vn .. getDebug()
end
return vn
end
function p.compareITISIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p815', 'ITIS', 'ITIS', {'{{ITIS'}) .. getDebug()
end
function p.compareNCBIIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p685', 'NCBI', 'NCBI', {'{{NCBI'}) .. getDebug()
end
function p.compareTPDBIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p842', 'TPDB', 'TPDB', {'{{TPDB'}) .. getDebug()
end
function p.compareWoRMSIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p850', 'WoRMS', 'WRMS', {'{{WRMS'}) .. getDebug()
end
function p.compareFishBaseSpeciesIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p938', 'FishBase', 'FishBase', {'{{FishBase'}) .. getDebug()
end
function p.compareMSWIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p959', 'MSW', 'MSW', {'{{MSW'}) .. getDebug()
end
function p.compareEOLIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p830', 'EOL', 'EOL', {'{{EOL'}) .. getDebug()
end
function p.compareGBIFIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p846', 'GBIF', 'GBIF', {'{{GBIF'}) .. getDebug()
end
function p.compareThePlantListIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p1070', 'ThePlantList', 'ThePlantList species', {'{{ThePlantList species'}) .. getDebug()
end
function p.compareTropicosIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p960', 'Tropicos', 'Tropicos', {'{{Tropicos', '{{tropicos'}) .. getDebug()
end
function p.compareMycoBankIdWithWikidata(frame)
return compareSiteIdWithWikidata(frame, 'p962', 'MycoBank', 'MycoBank', {'{{MycoBank'}) .. getDebug()
end
function p.test(frame)
return test(frame,frame.args)
end
function p.suppressCategory(frame)
-- for testcases
return suppressCategory(frame.args['1'])
end
function p.suppressDisambiguation(frame)
-- for testcases
return suppressDisambiguation(frame.args['1'])
end
function p.isLink(frame)
-- for testcases (return string when normal function returns boolean)
return tostring(not not isLink(frame.args['1']))
end
function p.strContains(frame)
-- for testcases (return string when normal function returns boolean)
return tostring(not not strContains(frame.args['long'],frame.args['small']))
end
function p.calcVNEntry(frame)
-- for testcases
return mw.text.nowiki(calcVNEntry(frame.args['lang'],frame.args['interwiki'],frame.args['vnFromWikidata'],frame.args['vnSource'],frame.args['default'])) .. getDebug()
end
function p.isTrue(frame)
-- for testcases (return string when normal function returns boolean)
return tostring(not not isTrue(frame.args['1']))
end
function p.getCurrentNamespace()
-- for testcases
return getCurrentNamespace()
end
function p.isCurrentNamespaceACategoryOrAGallery()
-- for testcases (return string when normal function returns boolean)
return tostring(not not isCurrentNamespaceACategoryOrAGallery())
end
function p.getScientificNames()
-- for testcases (return string when normal function returns table)
return mw.text.nowiki(tableToString(getScientificNames()))
end
return p