Modul:Official links/sandkasse
Utseende
Lua-feil i Modul:Documentation, linje 388: message: type error in message cfg.module-sandbox-category (string expected, got nil).
require('Module:No globals')
local contLang = mw.language.getContentLanguage()
local prioritize = {}
prioritize = {
['Q9043'] = true, -- norsk
['Q25167'] = true, -- bokmål (målform av norsk)
['Q25164'] = true, -- nynorsk (målform av norsk)
['Q9035'] = true, -- dansk (nærstående språk)
['Q9027']= true, -- svensk (nærstående språk)
['Q1860'] = true, -- engelsk (vanlig å kunne dette språket)
['Q7979'] = true, -- britisk-engelsk (variant av engelsk)
['Q7976'] = true, -- amerikansk-engelsk (variant av engelsk)
-- flere varianter av engelsk...
['Q188'] = true, -- tysk (vanlig å kunne dette språket)
['Q150'] = true, -- fransk (vanlig å kunne dette språket)
['Q33947'] = true, -- nordsamisk (offisielt språk i norge)
['Q13293'] = true, -- sørsamisk (offisielt språk i norge)
['Q56322'] = true, -- lulesamisk (offisielt språk i norge)
['Q165795'] = true, -- kvensk (offisielt språk i norge)
['Q36641'] = true, -- romani (offisielt språk i norge)
['Q13201'] = true, -- romanes (offisielt språk i norge)
}
local domain = {}
domain = {
['net'] = '«net-domene»',
['org'] = '«org-domene»',
['no'] = '«norsk domene»',
['sv'] = '«svensk domene»',
['dk'] = '«dansk domene»',
['de'] = '«tysk domene»',
['nl'] = '«nederlandsk domene»',
}
local messages = {}
messages = {
['qualifier-default-empty'] = 'tom verdi (en feil)',
['qualifier-P407-empty'] = 'tomt språk (en feil)',
['qualifier-default-missing'] = 'mangler kvalifikator',
['qualifier-default-missing-P407'] = 'ukjent språk',
['qualifier-P856-missing'] = 'ukjent språk',
['qualifier-P1019-missing'] = 'ukjent språk',
['qualifier-P1581-missing'] = 'ukjent språk',
['qualifier-P856-missing-P407'] = 'ukjent språk',
['qualifier-P1019-missing-P407'] = 'ukjent språk',
['qualifier-P1581-missing-P407'] = 'ukjent språk',
['ext-link-with-lang-normal'] = '<span class="bjeller" style="color: gray;cursor:help;" title="$2"><small>($1)</small></span> [$3 $4]',
['ext-link-with-lang-preferred'] = '<span class="bjeller" style="color: gray;cursor:help;" title="$2"><small>($1)</small></span> [$3 $4] (foretrukket)',
['ext-link-normal'] = '[$1 $2]',
['ext-link-preferred'] = '[$1 $2] (foretrukket)',
['initial-P407-combiner'] = '/',
['final-P407-combiner'] = '$1/$2',
['initial-default-combiner'] = ', ',
['final-default-combiner'] = '$1 og $2',
['first-list-item'] = '$1: $2',
['rest-list-item'] = '* $1: $2',
['first-list-item-with-additional'] = '$1: $2 $3',
['rest-list-item-with-additional'] = '* $1: $2 $3',
['no-list-available'] = 'Ikke noe $1 tilgjengelig',
['cat-inclusion'] = 'Artikler med $1',
['cat-exclusion'] = 'Artikler uten $1',
['no-links-available'] = 'Ingen automatiske lenker tilgjengelig',
['wikidata-linkback-edit'] = 'Redigere på wikidata',
}
local function pri(code)
return prioritize[code]
end
local function guess(uri)
-- this is for country codes
local _,_,code = uri:match('//([-%w]+)%.([-%w]+)%.(%w+)')
if code and domain[code] then
return domain[code]
end
local _,code = uri:match('//([-%w]+)%.(%w+)')
if code and domain[code] then
return domain[code]
end
return uri
end
local function shortenUri(uri)
-- get the domain-part of the URI
local domainpart = uri:match('//([^/]+)')
local retval = nil
if domainpart then
-- split it up
local splitTable = {}
for i in string.gmatch(domainpart,"[^%.]+") do
-- insert the tld, domain and subdomains in reverse order
table.insert(splitTable, i)
end
-- now we should have a list of the subdomains, domain and tld.
local t = {}
if #splitTable>=1 then
table.insert(t, 1, table.remove(splitTable))
end
if #splitTable>=1 then
table.insert(t, 1, table.remove(splitTable))
end
if #splitTable>=1 then
table.insert(t, 1, table.remove(splitTable))
end
if #splitTable>=1 then
table.insert(t, 1, "")
end
-- the rest we don't care about..
retval = table.concat(t, '.')
end
return retval
end
local function g(...)
for _,v in ipairs(arg) do
if messages[v] then
return messages[v]
end
end
return '<'..arg[1]..'>'
end
local labels = {}
local function buildList( pid, t )
if #t == 0 then
return ''
elseif #t == 1 then
if t[1].langcode and #t[1].langcode then
return t[1].text .. ' ' .. t[1].langcode
else
return t[1].text
end
end
local tt = t
if t[1].text then
for i,v in ipairs(t) do
tt[i] = v.text
end
end
local last = table.remove(tt)
local str = table.concat(tt, mw.message.newRawMessage(g('initial-' .. pid .. '-combiner', 'initial-default-combiner')):plain())
return mw.message.newRawMessage(g('final-' .. pid .. '-combiner', 'final-default-combiner'), str, last):plain()
end
-- todo: messy solution, refactor
local function wrap( content, marker )
if content == '' or content == nil then
return nil
end
return '<span class="mw-collapsible mw-collapsed" id="mw-customcollapsible-'..marker..'"><span class="mw-collapsible-content">' .. content .. '</span>'
.. ' <span class="mw-customtoggle-'..marker..'" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}" /></span>'
end
local function getEntityLabel( id )
local entity = mw.wikibase.getEntity( id )
if entity then
return entity:getLabel()
end
end
local function findEntityLabel( id )
if not labels[id] then
local label = getEntityLabel( id )
if label then
labels[id] = label -- labels is an outer structure
end
end
return labels[id]
end
local mainFormatter = {}
mainFormatter['string'] = function( pid, datavalue )
if datavalue['type'] ~= 'string' then
return nil
end
return datavalue.value
end
local qualLangCode = {}
qualLangCode['wikibase-entityid'] = function( pid, datavalue )
if datavalue['type'] ~= 'wikibase-entityid' then
return nil
end
if datavalue.value['entity-type'] ~= 'item' then
return nil
end
local claim = {}
local entity = mw.wikibase.getEntityObject('Q'..datavalue.value["numeric-id"])
if entity and entity.claims then
claim = entity.claims['P305'] -- IETF language tag
-- traverse all snaks in this claim
for _, claimsnak in ipairs( claim ) do
if claimsnak ~=nil and claimsnak.mainsnak ~= nil and claimsnak.mainsnak.snaktype == "value" and claimsnak.mainsnak.datatype == "string" then
return claimsnak.mainsnak.datavalue.value
else
return nil
end
end
else
return nil
end
end
local qualFormatter = {}
qualFormatter['wikibase-entityid'] = function( pid, datavalue )
if datavalue['type'] ~= 'wikibase-entityid' then
return nil
end
if datavalue.value['entity-type'] ~= 'item' then
return nil
end
return findEntityLabel( 'Q'..datavalue.value["numeric-id"] )
end
local qualPrefer = {}
qualPrefer['wikibase-entityid'] = function( pid, datavalue )
if datavalue['type'] ~= 'wikibase-entityid' then
return nil
end
if datavalue.value['entity-type'] ~= 'item' then
return nil
end
return pri( 'Q'..datavalue.value["numeric-id"] ) or false
end
local main = {}
main.P856 = {
types = {
snaktype = 'value',
datatype = 'url',
},
formatter = mainFormatter['string']
}
main.P1019 = {
types = {
snaktype = 'value',
datatype = 'url',
},
formatter = mainFormatter['string']
}
main.P1581 = {
types = {
snaktype = 'value',
datatype = 'url',
},
formatter = mainFormatter['string']
}
local qual = {}
qual.P407 = {
types = {
snaktype = 'value',
datatype = 'wikibase-item',
},
formatter = qualFormatter['wikibase-entityid'],
langcode = qualLangCode['wikibase-entityid'],
preferred = qualPrefer['wikibase-entityid']
}
local qorder = {'P407'}
local p = {}
function p.findMainLinks(pid, qid)
local head = {}
local tail = {}
-- get the entity we are checking
local entity = mw.wikibase.getEntityObject( qid )
-- to avoid deep tests
if not entity or not entity.claims then
return head, tail
end
-- get the claims for this entity
local statements = entity.claims[pid]
-- to avoid deep tests
if not statements then
return head, tail
end
-- let's go through the claims
for _, claim in ipairs( statements ) do
-- to avoid deep tests
if not claim then
claim = {}
end
local valid = true
if claim['type'] ~= 'statement' then
valid = valid and false
end
if claim['rank'] == 'deprecated' then
valid = valid and false
end
local mainsnak = claim.mainsnak or {}
if not mainsnak or not main[pid] then
valid = valid and false
end
if ((main[pid] and mainsnak.snaktype ~= main[pid].types.snaktype)
or (main[pid] and mainsnak.datatype ~= main[pid].types.datatype))
then
valid = valid and false
end
if valid then
local preferred = claim['rank'] == 'preferred'
-- get the content of the claim (the URL)
local mainStr = main[pid].formatter(pid, mainsnak.datavalue)
local optionals = {}
-- get any qualifiers for this claim (we are interested in P407 for indication of language on the site)
local qualifiers = claim.qualifiers or {}
-- now go through the qualifiers we are interested in (defined in the array qorder above this function)
for _, qualid in ipairs( qorder ) do
-- if the claim has this qualifier
if qualifiers[qualid] then
-- it's here, let's check it out!
local items = {}
-- traverse all snaks in this qualifier
for _, qualsnak in ipairs( qualifiers[qualid] ) do
if qualsnak and qual[qualid] then
-- check if the snak is of the correct snaktype and datatype
if not (qualsnak.snaktype ~= qual[qualid].types.snaktype
or qualsnak.datatype ~= qual[qualid].types.datatype)
then
-- it is, so let's get the label of the qualifier
items[1+#items] = {}
items[#items].text = qual[qualid].formatter(qualsnak.property, qualsnak.datavalue)
if qualid == 'P407' then
-- and the language-code
items[#items].langcode = qual[qualid].langcode(qualsnak.property, qualsnak.datavalue)
end
-- if wd hasn't ranked it as preferred, we'll make our own check in the prioritize-list
preferred = preferred or qual[qualid].preferred(qualsnak.property, qualsnak.datavalue)
end
end
end
-- special case for P407 (verkets eller navnets språk)
local text = nil
if qualid == 'P407' then
if #items == 0 then
-- this should never happen, unless it will be possible to add empty qualifiers
text = mw.message.newRawMessage(g('qualifier-'.. qualid..'-empty', 'qualifier-default-empty')):plain()
end
if items[1].langcode then
-- make the URL-link and if the link is ranked as "preferred", it will get a "(foretrukket)"-suffix from the ext-link-preferred format-string
text = mw.message.newRawMessage(g('ext-link-with-lang-' .. claim['rank']), items[1].langcode, items[1].text, mainStr, shortenUri(mainStr)):plain()
else
-- make the URL-link and if the link is ranked as "preferred", it will get a "(foretrukket)"-suffix from the ext-link-preferred format-string
text = mw.message.newRawMessage(g('ext-link-' .. claim['rank']), mainStr, shortenUri(items[1].text)):plain()
end
else
-- let's build a list of the qualifiers in the snak
text = buildList(qualid, items)
end
-- add the link to the array
optionals[1+#optionals] = {}
optionals[#optionals].text = text
else
-- we don't have the qualifier, make do anyway
local text = nil
-- special case for P407 (verkets eller navnets språk)
if qualid == 'P407' then
-- this will make the label either the URL itself or "no-domene" etc.
-- text = guess(mainStr)
text = shortenUri(mainStr)
end
if not text then
-- nothing available and I don't know how to treat this qualifier.
-- This shouldn't happen until qorder includes other qualifiers and I don't have any special-case handling beforehand.
text = mw.message.newRawMessage(
g('qualifier-'.. pid..'-missing-'..qualid,
'qualifier-default-missing-'..qualid,
'qualifier-default-missing')):plain()
end
-- make the URL-link and if the link is ranked as "preferred", it will get a "(foretrukket)"-suffix from the ext-link-preferred format-string
optionals[1+#optionals] = {}
optionals[#optionals].text = mw.message.newRawMessage(g('ext-link-' .. claim['rank']), mainStr, text):plain()
end
end
if #optionals > 0 then
-- build the list from the claims so far
mainStr = buildList(pid, optionals)
end
if preferred then
-- if these claims are "preferred" or in the prioritize list, let's put them in the "head"-queue
head[1+#head] = {}
head[#head].text = mainStr
else
-- else, let's put them in the "tail"-queue
tail[1+#tail] = {}
tail[#tail].text = mainStr
end
end
end
return head, tail
end
local function addLinkback(str, property)
local id = mw.wikibase.getEntityObject()
if not id then
return str
end
if type(id) == 'table' then
id = id.id
end
local class = ''
if property then
class = 'wd_' .. string.lower(property)
end
local title = g('wikidata-linkback-edit')
local icon = '[%s [[File:Blue pencil.svg|%s|10px|baseline|link=]] ]'
local url = mw.uri.fullUrl('d:' .. id .. '#' .. property)
url.fragment = property
url = tostring(url)
local v = mw.html.create('span')
:addClass(class)
:wikitext(str)
:tag('span')
:addClass('noprint plainlinks wikidata-linkback')
:css('padding-left', '.5em')
:wikitext(icon:format(url, title))
:allDone()
return tostring(v)
end
function p.links( frame )
local items = {}
local counts = {}
-- find all arguments to this function
for _,v in ipairs(frame.args) do
-- we expect arguments of the following kind: P856, Pxxx and so on (where xxx is a number)
local _, _, ch, num= v:find("([pP])(%d+)")
-- If it start with a "P", we'll assume it's a valid property
if ch then
-- let's get the property ID (Pxxx)
local pid = ch:upper()..num
-- now find the label for this property.
local label = findEntityLabel( pid )
if not counts[pid] then
counts[pid] = 0
end
if label then
-- now find the available links for this property, separated into two groups, a "head"-group which are the preferred links and a "tail"-group which are normal links
local head, tail = p.findMainLinks(pid)
if (head and #head > 0) or (tail and #tail > 0) then
-- we got something, so let's count it!
counts[pid] = counts[pid] + 1
end
if head and #head > 0 then
-- we have a "head"-group, so let's add it and the tail-group as well
items[1+#items] = { text = { contLang:ucfirst( label ), buildList('', head), wrap(buildList('', tail), pid) }, pid=pid }
elseif tail and #tail > 0 then
-- we only got a "tail"-group, so no head for you..
items[1+#items] = { text = { contLang:ucfirst( label ), buildList('', tail) }, pid=pid }
end
end
end
end
for i,v in ipairs(items) do
-- if we have three parts (label, head and tail), we'll use the format-string with 3 variables ($1, $2 and $3), which will map into the items as made before
-- if we have two parts (label and head or tail), we'll use the format-string with 2 variables ($1 and $2), which will map into the items as made before
-- this function will use the format-string and the items as input to output the correct strings.
items[i] = (i==1 and '' or '* ') .. addLinkback(mw.message.newRawMessage(
((#v.text >=3 and #v.text[3])
and g('first-list-item-with-additional')
or g('first-list-item')),
unpack(v.text))
:plain(), v.pid)
end
local cats = {}
for k,v in pairs(counts) do
cats[1+#cats] = '[[Category:' .. mw.message.newRawMessage(g(counts[k]==0 and 'cat-exclusion' or 'cat-inclusion'), findEntityLabel( k )):plain() .. ']]'
end
if #items > 0 then
return table.concat(items, "\n") .. table.concat(cats, "")
end
return "''" .. mw.message.newRawMessage(g('no-links-available')):plain() .. "''" .. table.concat(cats, "")
end
return p