Module:External links/sandbox

require('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 -- we assume it's connected

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.label(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 " " .. mw.dumpObject(obj) .. " " 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 or {} -- get any qualifiers for this claim (we are interested in P1793 for		-- indication of which claim is correct) local qualifiers = claim.qualifiers or {} -- now let's check the qualifier we are interested in		local qualid = 'P1793' -- format as a regular expression -- 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' 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		local qualifiers = claim.qualifiers or {} -- get the content of the claim (the identifier) local langcode = linkTemplate.langcode if langcode and 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 valuee`.			I'm not sure if that functionality would've had any purpose, given how cryptic this function is. output[#output+1] = { value=stringFormatter(claim.mainsnak.datavalue) } 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 local url = '' output[#output+1] = { langcode = value.langcode, category = {} }			-- Search for a url formatter 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		regexConverterTest(linkTemplate.regex, sitelink)) then --mw.log("it's verified..") local url = '' output[1] = { langcode = sitelink.langcode, category = {} }		-- Search for a url-formatter 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 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) end if wikidata_property or (linkTemplate.url and linkTemplate.url ~= '') or (linkTemplate.url_f) then output[1] = { langcode = string.find(linkTemplate.langcode, "[pP]%d+") and "" or linkTemplate.langcode, category = {} }		local url = '' 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 if wikidata_values then hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim end -- Search for a url-formatter 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 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) end if wikidata_property or (linkTemplate.url and 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)) local url = '' 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 if wikidata_sitelink then hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim end -- Search for a url formatter 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 = '' 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