Module:Cite Wikidata
Jump to navigation
Jump to search
Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
The template supports journal and book publications:
- books:
- Item instance of (P31) has to be one of: version, edition or translation (Q3331189), brochure (Q5173771), literary work (Q7725634), written work (Q47461344), encyclopedia (Q5292)
- Internationalization at Data:I18n/Cite Wikidata.tab is based on Template:Cite book (Q92570), with current translations:
- English: en:Template:Cite book
- Deutsch: de:Vorlage:Literatur
- Français : fr:Modèle:Ouvrage
- Polski: pl:Szablon:Cytuj książkę
- Русский: ru:Шаблон:Книга
- journal:
- Item instance of (P31) has to be one of: scholarly article (Q13442814), article (Q191067), scholarly work (Q55915575), scientific publication (Q591041)
- Internationalization at Data:I18n/Cite Wikidata.tab is based on Template:Cite journal (Q5624899), with current translations:
- English: en:Template:Cite journal
- Deutsch: de:Vorlage:Cite journal
- Français : fr:Modèle:Article
- Polski: pl:Szablon:Cytuj pismo
- Русский: ru:Шаблон:Статья
Code
--[[
__ __ _ _ ____ _ _ __ ___ _ _ _ _
| \/ | ___ __| |_ _| | ___ _ / ___(_) |_ ___ \ \ / (_) | _(_) __| | __ _| |_ __ _
| |\/| |/ _ \ / _` | | | | |/ _ (_) | | | __/ _ \ \ \ /\ / /| | |/ / |/ _` |/ _` | __/ _` |
| | | | (_) | (_| | |_| | | __/_| |___| | || __/ \ V V / | | <| | (_| | (_| | || (_| |
|_| |_|\___/ \__,_|\__,_|_|\___(_)\____|_|\__\___| \_/\_/ |_|_|\_\_|\__,_|\__,_|\__\__,_|
This module is intended for creating citation templates based on wikidata items.
Please do not modify this code without applying the changes first at Module:Cite Wikidata/sandbox and testing
at Module:Cite Wikidata/sandbox/testcases and Module talk:Cite Wikidata/sandbox/testcases.
Authors and maintainers:
* User:Jarekt
]]
require('strict') -- used for debugging purposes as it detects cases of unintended global variables
local ISOdate = require('Module:ISOdate')._ISOdate -- date localization
local core = require('Module:Core')
-- =======================================
-- === Local Functions ===================
-- =======================================
-------------------------------------------------------------------------------
local function getProperty(entity, prop, lang)
return (core.parseStatements(entity:getBestStatements( prop ), lang) or {nil})[1]
end
-------------------------------------------------------------------------------
local function getAllProperties(entity, prop, lang)
return core.parseStatements(entity:getAllStatements( prop ), lang)
end
-------------------------------------------------------------------------------
local function getItemProperty(item, prop)
return (core.parseStatements(mw.wikibase.getAllStatements( item, prop ), nil) or {nil})[1]
end
---------------------------------------------------------------------------
-- use different sitelink call depending if you already have an entity or not
-- INPUTS:
-- * item and entity - entity id and entity: if full entity already uploded than use that
-- otherwise use entity id to look up sitelink
-- * prop - property for which to return the best statment
-- OUTPUT:
-- * value of the best statment (only from the first one)
local function getAllProperties2(item, entity, prop)
local statements
if entity then
statements = entity:getBestStatements(prop)
else
statements = mw.wikibase.getBestStatements(item, prop)
end
return core.parseStatements(statements, nil)
end
-------------------------------------------------------------------------------
local function monolingualtext2table(statements, lang)
local Table = {}
for _, statement in pairs( statements ) do
if (statement.mainsnak.snaktype == "value") then
local val = statement.mainsnak.datavalue.value
Table[val.language] = val.text -- look for multiple values each with a language code
end
end
return Table
end
-- ===========================================================================
-- === harvest properties with qualifiers ===
-- ===========================================================================
local function getPropertyQual(entity, prop, qualifiers, lang)
local Output = {}
if entity.claims and entity.claims[prop] then
for _, statement in pairs( entity:getBestStatements( prop )) do
local output = {} -- table with fields: key, value, P... (qualifiers)
output.value = core.parseSnak(statement.mainsnak, lang)
for iQual, qual in ipairs( qualifiers ) do
if statement.qualifiers and statement.qualifiers[qual] then
output[qual] = core.parseSnak(statement.qualifiers[qual][1], lang)
end
table.insert(Output, output)
end
end
end
return Output
end
-- ===========================================================================
-- === Harvest wikidata properties matching creator template fields ===
-- === INPUTS: ===
-- === * entity - wikidata entity ==
-- === * itemID2 - item id or a q-code from SDC ===
-- === * lang - language id of the desired language ===
-- === * namespace - namespace number of the page calling the module ===
-- ===========================================================================
local function harvest_wikidata(entity, lang)
local data = {}
local comma = mw.message.new( "comma-separator"):inLanguage(lang):plain()
.. mw.message.new( "Word-separator" ):inLanguage(lang):plain()
-- harvest string or Q-code properties where a single value is expected
local property = { P123='publisher', P291='location', P629='edition_of', P1433='journal',
P275='license', P393='edition', P478='volume', P433='issue',
P356='doi', P698='PubMedID', P932='PMCID', P212='ISBN', -- IDs
P571='inc_date', P577='pub_date' } -- dates
for prop, field in pairs( property ) do
data[field] = getProperty(entity, prop, lang)
end
-- get External identifiers
local T = {}
local fields = {doi= 'doi: [https://dx.doi.org/%s %s]',
PubMedID = 'PubMed ID: [https://www.ncbi.nlm.nih.gov/pubmed/?term=/%s %s]',
PMCID = 'PubMed Central ID: [https://www.ncbi.nlm.nih.gov/pmc/articles/PMC?term=/%s %s]',
ISBN = 'ISBN [[Special:BookSources/%s|%s]]',
inc_date = 'date', pub_date = 'date'}
for field, val in pairs( fields ) do
if data[field] and val == 'date' then
data[field] = ISOdate(data[field], lang, '', 'dtstart', '100-999')
elseif data[field] then
table.insert(T, '<small>' .. string.format( val, data[field], data[field]) .. '</small>')
end
end
data.ident = table.concat(T, comma)
data.date = data.pub_date or data.inc_date
-- harvest string or Q-code properties where multiple values are expected
local property = { P407='lang', P98='editor'}
for prop, field in pairs( property ) do
local ids = getAllProperties(entity, prop, lang)
if ids then
data[field] = table.concat(ids, comma)
end
end
-- harvest monolingualtext text properties
local property = { P1476 = 'title', P1680='subtitle', P179='series_title'}
for prop, field in pairs( property ) do
local Table = monolingualtext2table( entity:getBestStatements( prop ), lang)
data[field] = core.langSwitch(Table, lang)
end
data.title = data.title or core.getLabel(entity.id, lang) -- if title not provided than use label
-- harvest author properties while using 'P1545' (series ordinal ) as sort key
local AuthorTable = {}
local property = { P50='author', P2093='authorStr'}
for prop, field in pairs( property ) do
local authors = getPropertyQual(entity, prop, {'P1545'}, lang)
if authors then
for _, author in ipairs(authors) do
author.P1545 = author.P1545 or (#AuthorTable+1000) -- if no P1545 than keep original order
table.insert(AuthorTable, author)
end
end
end
if #AuthorTable>0 then
local tableComp = function (a, b) return a.P1545<b.P1545 end
table.sort(AuthorTable, tableComp)
T = {}
for _, author in ipairs(AuthorTable) do
table.insert(T, author.value)
end
data.author = table.concat(T, comma)
end
return data
end
-- ===========================================================================
local function getFormatString(strType, lang)
-- fetch a text template for a given language from [[Data:I18n/Cite Wikidata.tab]]
local text
local key = (strType=='book' and 'book' ) or 'journal'
local tab = mw.ext.data.get('I18n/Cite Wikidata.tab', lang)
for _, row in pairs(tab.data) do
local id, _, msg = unpack(row)
if id == key then
text = msg
break
end
end
return mw.ustring.gsub(text, '\|', '!')
end
-- ===========================================================================
local function load_LUT()
-- fetch a look-up-table from [[Data:Cite Wikidata LUT.tab]]. The table is handy
-- so we can add more items easy without changing the source code
local LUT = {}
local tab = mw.ext.data.get('Cite Wikidata LUT.tab', 'en')
for _, row in pairs(tab.data) do
local item, _, template = unpack(row)
LUT[item] = template
end
return LUT
end
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================
-- ===========================================================================
function p.getCitationType(entity, item)
-- Determine if we should use book or article cite pattern
local iType
-- first check "instance_of" properties
local LUT =load_LUT()
for _, instance in pairs(getAllProperties2(item, entity, 'P31')) do
iType = LUT[instance]
if iType then
return iType
end
end
-- if that did not work check for presence of key properties
local P = { edition_of='P629', journal='P1433', issue='P433'}
if entity and entity.claims then
if (entity.claims[P.edition_of]) then
iType = 'book'
elseif (entity.claims[P.journal] or entity.claims[P.issue]) then
iType = 'article'
end
elseif item then
if getItemProperty(item, P.edition_of) then
iType = 'book'
elseif (getItemProperty(item, P.journal) or getItemProperty(item, P.issue)) then
iType = 'article'
end
end
return iType
end
-- ===========================================================================
function p._citeWikidata(item, lang, page)
local entity
if type(item) == 'string' then
entity = mw.wikibase.getEntity(item)
else
entity = item
end
if not entity then
return nil
end
local data = harvest_wikidata(entity, lang)
data.type = p.getCitationType(entity, nil)
page = tonumber(page)
if page and page>0 then
data.page = page
end
-- fetch a text template for a given language
local text = getFormatString(data.type, lang)
-- build text of the citation based on the text template
-- replace "$FIELD" in the "text" with data.field value
local fields = {'author', 'editor', 'title', 'edition', 'location', 'publisher',
'date', 'journal', 'volume', 'issue', 'lang', 'subtitle', 'ident', 'page'}
for _, field in ipairs(fields) do
if data[field] then
-- replace string like "$DATE" with data.date
text = mw.ustring.gsub(text, '$'..string.upper(field), data[field])
end
end
for i = 1,5,1 do
-- delete and cell bracketed with "|" (now changed to "!") so we do not break
-- links with a single | (!)
text = mw.ustring.gsub(text, '\![^$\!]*$[^\!]*\!', '!')
end
text = mw.ustring.gsub(text, '\!', '') -- remove all "|" (now changed to "!")
text = mw.ustring.gsub(text, "^[%s\.\,]*(.-)%s*$", "%1") -- trim leading whitespaces
return text
end
-- ===========================================================================
-- === Versions of the function to be called from template namespace
-- ===========================================================================
function p.debug(frame)
local args = core.getArgs(frame)
local entity = mw.wikibase.getEntity(args.item)
local data = harvest_wikidata(entity, args.lang)
local str = ''
for field, val in pairs( data ) do
if type(val)=='string' then
str = str .. '*' .. field .. ' = ' .. val .. '\n'
else
str = str .. '*' .. field .. ' = ' .. table.concat(val, ' / ') .. '\n'
end
end
local formatStr = getFormatString(data.type, args.lang)
str = str .. '* format string = ' .. formatStr .. ' for language ' .. args.lang .. '\n'
return str
end
-- ===========================================================================
function p.citeWikidata(frame)
local args = core.getArgs(frame)
return p._citeWikidata(args.item, args.lang, args.page)
end
-- ===========================================================================
function p.reflist(frame)
local args = core.getArgs(frame)
local str = ''
for i, j in pairs(arg.list) do
str = str .. '<li> ' .. p.citeitem(mw.text.trim(j),arg.lang) .. '</li>'
end
return str
end
return p