![]() | This is the module sandbox page for Module:External links (diff). |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module is designed for implementing templates to display external links in an English Wikipedia article, using the properties defined in that article's Wikidata item. It was based on the Norwegian Wikipedia module no:Modul:External links.
The first test implementation is Template:Sports links (based on no:Mal:Sportslenker). The sports-related link properties and formats are specified in Module:External links/conf/Sports (based on no:Modul:External links/conf/Sport).
Other subject-based implementations at the Norwegian Wikipedia include:
- Arts (no:Mal:Artslenker and no:Modul:External links/conf/Arter)
- Astronomy (no:Mal:Astronomilenker and no:Modul:External links/conf/Astronomi)
- Authority data (no:Mal:Autoritetsdata and no:Modul:External links/conf/Autoritetsdata)
- Film (no:Mal:Filmlenker and no:Modul:External links/conf/Film)
- Film person (no:Mal:Filmperson and no:Modul:External links/conf/Filmperson)
- Music (no:Mal:Musikklenker and no:Modul:External links/conf/Musikk)
- Official links (no:Mal:Offisielle lenker and no:Modul:External links/conf/Offisielle lenker)
- Games (no:Mal:Spill-lenker and no:Modul:External links/conf/Spill)
Usage
edit{{#invoke:External links|function_name}}
Submodules
editrequire('strict')
-- local genitive = require('Module:Genitive')._genitive
local contLangCode = mw.language.getContentLanguage():getCode()
local cmodule = {}
local conf = require 'Module:External links/conf'(contLangCode)
local hasdatafromwikidata = false
local hasdatafromlocal = false
local haswikidatalink = true -- whether or not this page has a wikidata entity(?); we assume there is one at first
local p = {}
local function getLabel(entity, use_genitive, pagetitle)
local label = (pagetitle ~= '') and pagetitle or nil
if not label and not entity then
label = mw.title.getCurrentTitle().text
elseif not label then
label = mw.wikibase.getLabel(entity.id) or mw.title.getCurrentTitle().text
end
-- return use_genitive and genitive(label, 'sitt') or label
return use_genitive and label .. "'s" or label
end
-- @todo cleanup, this is in production, use the console
local function dump(obj)
return "<pre>" .. mw.dumpObject(obj) .. "</pre>"
end
local function stringFormatter( datavalue )
if datavalue == nil or datavalue.type ~= 'string' then
return nil
end
return datavalue.value
end
-- This is a really makeshift crappy converter, but it'll do some basic
-- conversion from PCRE to Lua-style patterns (note that this only work
-- in very few cases)
local function regexConverterTest( regex, str )
regex = regex:gsub("\\d{(%d)}", function(num) return string.rep("%d", num) end)
return string.find(str, '^' .. regex .. '$')
end
local function getFormatterUrl( prop, value )
local fUrl = ""
local statements = mw.wikibase.getBestStatements(prop, "P1630")
-- to avoid deep tests
if #statements == 0 then
return ""
end
-- let's go through the claims
for _, claim in ipairs( statements ) do
local mainsnak = claim.mainsnak -- nil will be indexed if it doesn't exist
--[[
Checks P1793 (format as a regular expression) qualifier of formatter URL to
check if the given string matches the formatter URL's regex;
will prioritize that formatter URL if true
]]
local qualifiers = claim.qualifiers or {}
local qualid = 'P1793' -- format as a regular expression
if qualifiers[qualid] then
-- we have a regex qualifier, traverse all snaks
for _, qualsnak in ipairs( qualifiers[qualid] ) do
if qualsnak.snaktype == 'value'
and regexConverterTest(qualsnak.datavalue.value, value)
then
-- it matched, this is correct and overrides any other.
fUrl = mainsnak.datavalue.value
break
end
end
elseif fUrl == '' then -- if we don't have any other, use this one
fUrl = mainsnak.datavalue.value
end
end
return fUrl
end
local function getLanguageData(prop, qid, separator)
-- Formerly outputted a table, but this function was always run through table.concat() when invoked, so it has been simplified to yield a string
separator = separator or ''
local output = ''
if not mw.wikibase.entityExists(qid) then -- yield error, which would originally happen because table.concat(nil) errors
error("getLanguageData was given a nonexistent entity")
end
-- get claims
local statements = mw.wikibase.getBestStatements(qid, prop)
-- to avoid deep tests
if #statements == 0 then
return ''
end
-- mw.log("getLanguageData going through claims="..dump(statements))
-- let's go through the claims
for _, claim in ipairs( statements ) do
local mainsnak = claim.mainsnak
if mainsnak.snaktype == 'value' then
-- if this is the correct P-value, dive into it and get P218 (ISO 639-1)
if prop == 'P364' then -- original language of work
output = output .. separator .. getLanguageData('P218', mainsnak.datavalue.value.id, conf:a('mod-filter-separator'))
elseif prop == 'P218' or prop == 'P305' then -- ISO 639-1 code or IETF language tag
output = output .. separator .. stringFormatter(mainsnak.datavalue)
end
end
end
return output
end
local langqvalorder = {'P407','P364'} -- check `language of work or name` first, `original language of film or TV show` second
local otherqvalorder = {'P582'}
local function getValuesFromWikidata(linkTemplate)
local output = {}
-- mw.log("getValuesFromWikidata, linkTemplate="..dump(linkTemplate))
-- get statements
local entity = mw.wikibase.getEntity()
-- check if the entity exists
-- TODO: check if we can skip distinguishing between no entity vs. no statements
if not entity then -- check if the entity exists
return nil
end
local statements = entity:getBestStatements(linkTemplate.prop)
-- to avoid deep tests
if #statements == 0 then
return {}
end
-- let's go through the claims
for _, claim in ipairs( statements ) do
output[#output + 1] = { value=stringFormatter(claim.mainsnak.datavalue) }
--- Check if the linkTemplate wants us to search a qualifier for languagedata
local qualifiers = claim.qualifiers or {}
-- get the content of the claim (the identifier)
local langcode = linkTemplate.langcode
if langcode
and string.find(langcode, "[pP]%d+")
then
-- this is a P-value for language-code, so we'll check qualifiers for languagedata
-- first get any qualifiers
for _, qualid in ipairs( langqvalorder ) do
-- if the claim has this qualifier
if qualifiers[qualid] then
-- it's here, let's check it out!
-- traverse all snaks in this qualifier
for _, qualsnak in ipairs( qualifiers[qualid] ) do
if qualsnak.snaktype == 'value' then
-- now get the actual data
langcode = getLanguageData('P305', qualsnak.datavalue.value.id)
end
end
end
-- mw.log("langcode is now="..dump(langcode))
end
if string.find(langcode, "[pP]%d+") then
-- we still don't have any langcode, so we default to "en"
langcode = nil
end
end
--[[ EDITOR'S NOTE:
I trimmed the `stillvalid` check thinking it was just doing stuff already handled by Wikibase's built-in input constraints.
However, it would've also aborted the loop iteration if "end time" was provided with `no value` or `unknown value`.
I'm not sure if that functionality would've had any purpose, given how cryptic this function is.
]]
if langcode and langcode ~= '' then
output[#output].langcode = langcode
end
end
-- mw.log("getValuesFromWikidata returning head="..dump(head).." tail="..dump(tail))
return output
end
local function findMainLinksOnWikidata(linkTemplate, pagetitle, short_links)
local output = {}
-- get the entity we are checking
local entity = mw.wikibase.getEntity()
-- to avoid deep tests
if not entity then
return nil
end
local values = getValuesFromWikidata(linkTemplate)
for _, value in ipairs( values ) do
local verified_value = value.value
if not (linkTemplate.regex and
regexConverterTest(linkTemplate.regex, value.value))
then
output[#output+1] = {
langcode = value.langcode,
category = {}
}
-- Search for a url formatter
local url = ''
if linkTemplate.url_f then
-- we have a locally defined url-formatter function from the config, use it as first priority
url = linkTemplate.url_f(verified_value)
if linkTemplate.track and not string.find(linkTemplate.langcode, "[pP]%d+") then
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain()
elseif linkTemplate.track then
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain()
end
elseif linkTemplate.url then
-- we have a locally defined url-formatter string from the config, use it as second priority
url = mw.message.newRawMessage(linkTemplate.url, verified_value):plain()
if linkTemplate.track and not string.find(linkTemplate.langcode, "[pP]%d+") then
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain()
elseif linkTemplate.track then
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain()
end
else
-- config has no url formatter; check if Wikidata has one on the property
local formatterUrl = getFormatterUrl(linkTemplate.prop, verified_value)
if formatterUrl ~= '' then
url = mw.message.newRawMessage(formatterUrl, verified_value):plain()
if linkTemplate.track then
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain()
end
end
end
if url ~= '' then
local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= contLangCode)
and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, contLangCode))
or ""
output[#output].text =
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message,
getLabel(entity, linkTemplate.genitive, pagetitle),
url,
langlink,
verified_value,
mw.uri.encode(verified_value, 'PATH'))
:plain()
end
end
end
--mw.log("findMainLinksOnWikidata returning="..dump(output))
return output
end
local function getSitelinkFromWikidata(linkTemplate, entity)
-- to avoid deep tests
if not entity then
entity = mw.wikibase.getEntity()
if not entity then
--mw.log("getSitelinkFromWikidata no entity")
return nil
end
end
local requested_sitelink = string.match(linkTemplate.prop, "SL(%l+)") -- a specific wiki to be linked to can be specified by config; otherwise, default to this wiki
local sitelink = entity:getSitelink(requested_sitelink)
return sitelink or nil
end
-- This function has a bug: :getSitelink does not return an object - only a string; yet this function tries to access sitelink.langcode
local function findSiteLinksOnWikidata(linkTemplate, pagetitle, short_links)
local output = {}
local sitelink = getSitelinkFromWikidata(linkTemplate)
-- verify existence of sitelink
if not sitelink then
return nil
end
if not (linkTemplate.regex and
not regexConverterTest(linkTemplate.regex, sitelink))
then
output[1] = {
langcode = sitelink.langcode,
category = {}
}
-- Search for a url-formatter
local url = ''
if linkTemplate.url_f then
-- we have a locally defined url-formatter function from the config, use it as first priority
url = linkTemplate.url_f(sitelink)
elseif linkTemplate.url then
-- we have a locally defined url-formatter string from the config, use it as second priority
url = mw.message.newRawMessage(linkTemplate.url, sitelink):plain()
else
url = sitelink:gsub(' ','_')
end
if linkTemplate.track and not string.find(linkTemplate.langcode, "SL%l+") and (linkTemplate.url_f or linkTemplate.url) then
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain()
elseif linkTemplate.track then
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain()
end
if url ~= '' then
local langlink = (sitelink.langcode and sitelink.langcode ~= '' and sitelink.langcode ~= contLangCode)
and mw.message.newRawMessage(conf:g('msg-langcode'), sitelink.langcode, mw.language.fetchLanguageName(sitelink.langcode, contLangCode))
or ""
output[1].text =
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message,
getLabel(entity, linkTemplate.genitive, pagetitle),
url,
langlink,
sitelink,
mw.uri.encode(sitelink, 'PATH'))
:plain()
end
end
--mw.log("findSiteLinksOnWikidata returning="..dump(output))
return output
end
local function findMainLinksLocal(linkTemplate, pagetitle, short_links, local_value)
local output = {}
-- to avoid deep tests
if not local_value or local_value == '' -- bail out if no value is present
or (linkTemplate.regex
and not regexConverterTest(linkTemplate.regex, local_value))
then
return {}
end
local wikidata_property = string.find(linkTemplate.prop, "[pP]%d+")
local wikidata_values = nil
if wikidata_property then
-- get any wikidata values to see if they are equal to local values
wikidata_values = getValuesFromWikidata(linkTemplate)
if wikidata_values then
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim
end
end
if wikidata_property or (linkTemplate.url) or (linkTemplate.url_f) then
output[1] = {
langcode = string.find(linkTemplate.langcode, "[pP]%d+") and "" or linkTemplate.langcode,
category = {}
}
assert(not wikidata_values or type(wikidata_values) == 'table', "Something went wrong: wikidata_values is neither a table nor nil")
if linkTemplate.track and wikidata_values then
local local_value_in_wikidata = false
for _,value in ipairs( wikidata_values ) do
if value.value == local_value then
local_value_in_wikidata = true
break
end
end
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), linkTemplate.prop):plain()
end
-- Search for a url-formatter
local url = ''
if linkTemplate.url_f then
-- we have a locally defined url-formatter function from the config, use it as first priority
url = linkTemplate.url_f(local_value)
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain()
end
elseif linkTemplate.url then
-- we have a locally defined url-formatter string from the config, use it as second priority
url = mw.message.newRawMessage(linkTemplate.url, local_value):plain()
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain()
end
else -- we know wikidata_property exists
-- config has no url formatter; check if Wikidata has one on the property
local formatterUrl = getFormatterUrl(linkTemplate.prop, local_value)
if formatterUrl ~= '' then
url = mw.message.newRawMessage(formatterUrl, local_value):plain()
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-local'), linkTemplate.prop):plain()
end
end
end
local langlink = (output[1].langcode and output[1].langcode ~= '' and output[1].langcode ~= contLangCode)
and mw.message.newRawMessage(conf:g('msg-langcode'), linkTemplate.langcode, mw.language.fetchLanguageName(linkTemplate.langcode, contLangCode))
or ""
output[1].text =
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message,
getLabel(nil, linkTemplate.genitive, pagetitle),
url,
langlink,
local_value,
mw.uri.encode(local_value, 'PATH'))
:plain()
end
--mw.log("findMainLinksLocal returning="..dump(output))
return output
end
local function findSiteLinksLocal(linkTemplate, pagetitle, short_links, local_value)
local output = {}
-- to avoid deep tests
if not local_value or local_value == '' -- bail out if no value is present
or (linkTemplate.regex
and not regexConverterTest(linkTemplate.regex, local_value))
then
return {}
end
local wikidata_property = string.find(linkTemplate.prop, "SL.+")
local wikidata_sitelink = nil
if wikidata_property then
-- get any wikidata values to see if they are equal to local values
wikidata_sitelink = getSitelinkFromWikidata(linkTemplate)
if wikidata_sitelink then
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim
end
end
if wikidata_property or (linkTemplate.url) or (linkTemplate.url_f) then
output[1] = {
langcode = string.find(linkTemplate.langcode, "SL.+") and "" or linkTemplate.langcode,
category = {}
}
--mw.log("findSiteLinksLocal - linkTemplate="..dump(linkTemplate).." langcode="..output[#output].langcode .." wikidata_values="..dump(wikidata_values))
if linkTemplate.track and wikidata_sitelink then
local local_value_in_wikidata = (wikidata_sitelink == local_value)
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), linkTemplate.prop):plain()
end
-- Search for a url formatter
local url = ''
if linkTemplate.url_f then
-- we have a locally defined url-formatter function from the config, use it as first priority
url = linkTemplate.url_f(local_value)
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain()
end
elseif linkTemplate.url then
-- we have a locally defined url-formatter string from the config, use it as second priority
url = mw.message.newRawMessage(linkTemplate.url, local_value):plain()
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain()
end
else -- we know wikidata_property exists
url = local_value:gsub(' ','_')
if linkTemplate.track then
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-local'), linkTemplate.prop):plain()
end
end
local langlink = (output[1].langcode and output[1].langcode ~= '' and output[1].langcode ~= contLangCode)
and mw.message.newRawMessage(conf:g('msg-langcode'), linkTemplate.langcode, mw.language.fetchLanguageName(linkTemplate.langcode, contLangCode))
or ""
output[1].text =
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message,
getLabel(nil, linkTemplate.genitive, pagetitle),
url,
langlink,
local_value,
mw.uri.encode(local_value, 'PATH'))
:plain()
end
--mw.log("findSiteLinksLocal returning="..dump(output))
return output
end
local function addLinkback(str, property)
local id = mw.wikibase.getEntityIdForCurrentPage()
if not id then
return str
end
local class = ''
local url = ''
if property then
class = 'wd_' .. string.lower(property)
url = mw.uri.fullUrl('d:' .. id .. '#' .. property)
url.fragment = property
else
url = mw.uri.fullUrl('d:' .. id )
end
local title = conf:g('wikidata-linkback-edit')
local icon = '[%s [[File:Blue pencil.svg|%s|10px|text-top|link=]] ]'
url = tostring(url)
local v = mw.html.create('span')
:addClass(class)
:wikitext(str)
:tag('span')
:addClass('noprint plainlinks wikidata-linkback')
:css('padding-left', '.3em')
:wikitext(icon:format(url, title))
:allDone()
return tostring(v)
end
local function getArgument(frame, argument)
local args = frame.args
if args[1] == nil then
local pFrame = frame:getParent();
args = pFrame.args;
for k,v in pairs( frame.args ) do
args[k] = v;
end
end
return args[argument]
end
local function removeEntry(conf_claims, identifier, property)
for i, linkTemplate in ipairs(conf_claims) do
if linkTemplate[identifier] == property then
table.remove(conf_claims, i)
end
end
return conf_claims
end
function p.getLinks(frame, customClaims) --customClaims is a backdoor for testcases
local configured_conf = getArgument(frame, conf:a('arg-conf'))
if configured_conf then
cmodule = require ('Module:External_links/conf/'..configured_conf)
else
error(mw.message.newRawMessage(conf:g('missing-conf'), configured_conf):plain())
end
local conf_claims = customClaims or cmodule:getConfiguredClaims(contLangCode)
local limits = cmodule:getLimits()
assert(limits, mw.message.newRawMessage(conf:g('missing-limits'), configured_conf):plain())
local links_shown = tonumber(getArgument(frame, conf:a('arg-maxlink'))) or limits['links-shown'] or 10 -- maximum links to display
local pagetitle = getArgument(frame, conf:a('arg-title'))
-- get a list of tracked properties from the article itself
local requested_tracking = getArgument(frame, conf:a('arg-track'))
if requested_tracking and requested_tracking ~= '' then
-- the properties should be written as P1234, P2345 and other
-- version corresponding to the applicable property-identifiers in the config
for track_prop in string.gmatch(requested_tracking,"[^ ,;:]+") do
-- get the requested properties and be able to access them
-- like req_prop['P345'] to verify if it was requested
local remove_track = string.match(track_prop, "^%-(.*)")
for i,claim in ipairs ( conf_claims ) do
if remove_track == claim.prop or remove_track == conf:a('mod-filter-all') then
-- if a property starts with "-", then we'll simply remove that
-- property from the conf_claims
conf_claims[i].track = false
elseif track_prop == claim.prop or track_prop == conf:a('mod-filter-all') then
conf_claims[i].track = true
end
end
end
end
-- get a list of "approved" properties from the article itself
local requested_properties = getArgument(frame, conf:a('arg-properties'))
--mw.log("requested_properties="..dump(requested_properties))
-- assume all properties are allowed
local req_prop = {}
local no_req_prop = false -- we'll allow properties to be filtered for now
if requested_properties and requested_properties ~= '' then
-- the properties should be written as P1234, P2345 and other
-- version corresponding to the applicable property-identifiers in the config
for i in string.gmatch(requested_properties,"[^ ,;:]+") do
-- get the requested properties and be able to access them
-- like req_prop['P345'] to verify if it was requested
if i == conf:a('mod-filter-all') then
-- this is a special modifier, saying we should ignore
-- all previous and future positive filters and remove the
-- filter (with exception of negative filters)
req_prop = {}
no_req_prop = true
end
local remove_prop = string.match(i, "^%-(.*)")
if remove_prop then
-- if a property starts with "-", then we'll simply remove that
-- property from the conf_claims
conf_claims = removeEntry(conf_claims, 'prop', remove_prop)
elseif not no_req_prop then -- only if we are allowing properties to be filtered
req_prop[i] = true
-- cheat to make #req_prop indicate populated table
req_prop[1] = true
end
end
end
local requested_langs = getArgument(frame, conf:a('arg-languages'))
--mw.log("requested_langs="..dump(requested_langs))
-- assume all languages are allowed
local req_lang = {}
local no_req_lang = false -- we'll allow languages to be filtered for now
if requested_langs and requested_langs ~= '' then
-- the languages should be written as langcodes as used in the conf_claims
for i in string.gmatch(requested_langs,"[^ ,;:]+") do
-- get the requested languages and be able to access them
if i == conf:a('mod-filter-all') then
-- this is a special modifier, saying we should ignore
-- all previous and future positive filters and remove the
-- filter (with exception of negative filters)
req_lang = {}
no_req_lang = true
end
-- like req_lang['en'] to verify if it was requested
local remove_lang = string.match(i, "^%-(.*)")
if remove_lang then
-- if a language starts with "-", then we'll simply remove that
-- language from the conf_claims
conf_claims = removeEntry(conf_claims, 'langcode', remove_lang)
elseif not no_req_lang then -- only if we are allowing languages to be filtered
req_lang[i] = true
-- cheat to make #req_lang indicate populated table
req_lang[1] = true
end
end
end
local short_links = getArgument(frame, conf:a('arg-short'))
short_links = (short_links and short_links ~= '' or false)
local showinline = getArgument(frame, conf:a('arg-inline'))
showinline = (showinline and showinline ~= '' or false)
local somedataonwikidata = not short_links
--mw.log("conf_claims="..dump(conf_claims))
--mw.log("req_prop="..dump(req_prop))
--mw.log("req_lang="..dump(req_lang))
--mw.log("short_links="..dump(short_links))
local output = {}
local category = {}
for _, linkTemplate in ipairs(conf_claims) do
-- if we're called with a list of approved properties or languages, check if this one is "approved"
if (#req_prop==0 or req_prop[linkTemplate.prop]) and (#req_lang==0 or req_lang[linkTemplate.langcode] or string.find(linkTemplate.langcode, "[pP]%d+")) then
-- Error if linkTemplate.prop is nonexistent, as it is required
assert(linkTemplate.prop, "malformed linkTemplate from config (no .prop given): " .. dump(linkTemplate))
local links = {}
local checkedonwikidata = false
-- get the any local overriding value from the call
local wikivalue = getArgument(frame, linkTemplate.prop)
if (not wikivalue or wikivalue == "") and string.find(linkTemplate.prop, "[pP]%d+") then
-- the property is a Pnnn type, and therefore on Wikidata
links = findMainLinksOnWikidata(linkTemplate, pagetitle, short_links)
if links == nil then
-- a nil-value indicated no wikidata-link
haswikidatalink = false
links = {}
else
checkedonwikidata = true
end
elseif (not wikivalue or wikivalue == "") and string.find(linkTemplate.prop, "SL%l+") then
-- this is a sitelink-type (SLspecieswiki)
--mw.log("finding sitelinks..")
links = findSiteLinksOnWikidata(linkTemplate, pagetitle, short_links)
if links == nil then
-- a nil-value indicated no wikidata-link
haswikidatalink = false
links = {}
else
checkedonwikidata = true
end
elseif string.find(linkTemplate.prop, "SL%l+") then -- we know that wikivalue is set if this is true
-- this is a sitelink-type (SLspecieswiki)
links = findSiteLinksLocal(linkTemplate, pagetitle, short_links, wikivalue)
elseif wikivalue and wikivalue ~= '' then
-- the property is of another annotation, and therefore a local construct
links = findMainLinksLocal(linkTemplate, pagetitle, short_links, wikivalue)
end
--mw.log("links="..dump(links))
for _,v in ipairs(links) do
-- we'll have to check langcodes again as they may have come from wikidata
if (#req_lang==0 or req_lang[v.langcode]) then
if checkedonwikidata and not hasdatafromwikidata then
-- add a general tracking category for articles with data from wikidata
hasdatafromwikidata = true
category[#category+1] = cmodule:getMessage(contLangCode, 'with-data-cat')
elseif not checkedonwikidata and not hasdatafromlocal then -- not checkonwikidata
-- add a general tracking category for articles with data from template-calls in local articles
hasdatafromlocal = true
category[#category+1] = cmodule:getMessage(contLangCode, 'with-local-cat')
end
if short_links and linkTemplate.short and v.text and v.text ~= '' then
-- if short links were requested, and a short definition exists for this property, let's use it
if #output==0 then
output[1] = v.text
else
output[#output] = output[#output] .. cmodule:getMessage(contLangCode,'short-list-separator') .. v.text
end
somedataonwikidata = true
elseif not short_links and not showinline and v.text and v.text ~= '' then
-- only if short links were not requested
output[#output+1] = (#output ~= 0 and conf:g('msg-ul-prepend') or '') -- if this is the first link, we won't output a list-element (msg-ul-prepend)
.. (checkedonwikidata and addLinkback(v.text, linkTemplate.prop) or v.text) -- if the link comes from wikidata, also output a linkback.
elseif not short_links and v.text and v.text ~= '' then -- and showinline
-- only if short links were not requested
output[#output+1] = v.text
end
if linkTemplate.track then
-- add category if tracking is on for this property and a category exists in the link-result.
for _,cats in ipairs( v.category ) do
category[#category+1] = cats
end
end
if links_shown == 0 then -- abort if we've hit the maximum for number of links
break
end
links_shown = links_shown - 1
end
end
if links_shown==0 then
break
end
end
end
local outtext = ""
if short_links and #output>0 then
-- if these are short links, output the whole thing with linkback to wikidata
--mw.log("somedataonwikidata="..dump(somedataonwikidata).." and output="..dump(output).." and #output="..dump(#output))
outtext = (somedataonwikidata
and addLinkback(table.concat(output,cmodule:getMessage(contLangCode,'short-list-separator')), nil)
or table.concat(output,cmodule:getMessage(contLangCode,'short-list-separator')))
elseif not showinline and #output>0 then -- and not shortlinks
outtext = table.concat(output,"\n")
elseif #output>0 then -- and not short_links and showinline
outtext = table.concat(output,conf:g('msg-inline-separator'))
end
if not hasdatafromwikidata then
category[#category+1] = cmodule:getMessage(contLangCode, 'no-data-cat')
if not hasdatafromlocal and not short_links then
outtext = cmodule:getMessage(contLangCode, 'no-data-text')
end
end
if not haswikidatalink then
category[#category+1] = cmodule:getMessage(contLangCode, 'no-wikilink-cat')
if not hasdatafromlocal and not short_links then
outtext = cmodule:getMessage(contLangCode, 'no-wikilink')
end
end
local nocategory = getArgument(frame, conf:a('arg-no-categories'))
category = #category>0 and "\n" .. table.concat(category,"\n") or ""
--mw.log("nocategory="..dump(nocategory).." and outtext="..dump(outtext).." and category="..dump(category))
outtext = outtext .. (nocategory and '' or category)
return outtext
end
function p.getLanguageCode(frame)
local prop = getArgument(frame, conf:a('arg-properties'))
return getLanguageData(prop, nil, conf:a(mod-filter-separator))
end
return p