Module:Cite
-- Displays bibliographic metadata from Wikidata
 
 local p = {}
 local wikidata = require('Module:Wikidata')
 local linguistic = require('Module:Linguistic')
 local fb = require('Module:Fallback')
 
 local function formatpage(page, lang)
 -- same text for singular and plural, most of the time, they can be distinguished by the presence of a &quot;-&quot; but that does not always work, see Q11927173
 	if not page then 
 		return nil
 	end
 	return fb._langSwitch({ -- singular
 		de = 'S. ' .. page,
 		en = 'p. ' .. page,
 		fr = 'p. ' .. page,
 		nb = 's. ' .. page,
 		nn = 's. ' .. page,
 		}, lang)
 end
 
 local function getauthor(item, lang)
 	return wikidata.formatStatements{entity=item, property = 'P50', lang=lang}
 end
 
 local function getauthorstring(item, lang)
 	return wikidata.formatStatements{entity=item, property = 'P2093', lang=lang}
 end
 
 local function getISBN(item, lang)
 	local ISBN = wikidata.formatStatements{entity = item, property = 'P212', lang=lang, numval = 1}
 	if ISBN then 
 		return 'ISBN ' ..ISBN
 	end
 end
 
 local function getLink(item, lang)
 	local links = wikidata.formatStatements{entity = item, property = 'P854', numval = 1, lang=lang}
 	if links then
 		return fb._langSwitch({
 			de = '[' .. links .. ' online]',
 			en = '[' .. links .. ' read online]',
 			fr = '[' .. links .. ' lire en ligne]',
 			nb = '[' .. links .. ' les online]',
 			nn = '[' .. links .. ' les online]',
 			}, lang)
 	end
 end
 
 local function getVolume(item, lang)
 	local volume = wikidata.formatStatements{entity = item, property = 'P478', numval = 1, lang=lang}
 	if volume then
 		return fb._langSwitch({
 			de = 'Band ' .. volume,
 			en = 'vol. ' .. volume,
 			}, lang)
 	end
 end
 
 local function getDoi(item, lang)
 	local doi = wikidata.formatStatements({entity=item, property = 'P356', numval = 1, lang=lang}) -- what to do if several value
 	if not doi then
 		return nil
 	end
 	return '&lt;small&gt;' .. 'doi: [https://doi.org/' .. doi .. ' ' .. doi .. ']' .. '&lt;/small&gt;' -- needs i18n ?
 end
 
 local function getPmid(item, lang)
 	local pmid = wikidata.formatStatements({entity=item, property = 'P698', numval = 1, lang=lang}) -- what to do if several values
 	if not pmid then
 		return nil
 	end
 	return '&lt;small&gt; PubMed ID: [https://www.ncbi.nlm.nih.gov/pubmed/?term=' .. pmid .. ' ' .. pmid .. '] &lt;/small&gt;' -- needs i18n ?
 end
 
 local function getPmcid(item, lang)
 	local pmcid = wikidata.formatStatements({entity=item, property = 'P932', numval = 1, lang=lang}) -- what to do if several values
 	if not pmcid then
 		return nil
 	end
 	return '&lt;small&gt; PubMed Central ID: [https://www.ncbi.nlm.nih.gov/pmc/articles/PMC' .. pmcid .. ' ' .. pmcid .. '] &lt;/small&gt;' -- needs i18n ?
 end
 
 local function getArXivID(item, lang)
 	local arxivid = wikidata.formatStatements({entity=item, property = 'P818', numval = 1, lang=lang}) -- what to do if several values
 	if not arxivid then
 		return nil
 	end
 	return '&lt;small&gt; arXiv ID: [http://arxiv.org/abs/' .. arxivid .. ' ' .. arxivid .. '] &lt;/small&gt;' -- needs i18n ?
 end
 
 local function getEditor(item, lang)
 	local editortable = wikidata.getClaims({entity=item, property='P98'})
 	if not editortable then 
 		return nil
 	end
 	local editor = wikidata.formatStatements({entity=item, property='P98', lang=lang}) -- should have a &quot;formatClaims&quot; function to avoid double work
 	if #editortable &gt; 1 then return
 		fb._langSwitch({ --plural
 			de = editor .. ' (Hrsg.)',
 			en = editor .. ' (eds.)',
 			nb = editor .. ' (red.)',
 			nn = editor .. ' (red.)',
 			}, lang)
 	else
 		return fb._langSwitch({ -- singular
 			de = editor .. ' (Hrsg.)',
 			en = editor .. ' (ed.)',
 			nb = editor .. ' (red.)',
 			nn = editor .. ' (red.)',
 			}, lang)
 	end
 		
 end
 
 local function getedition(item, lang)
 	local ednumber = wikidata.formatStatements({entity=item, property = 'P393', lang=lang, numval = 1}) 
 	if not ednumber then 
 		return nil
 	end
 	local ord = require('Module:Ordinal')._ordinal
 	return fb._langSwitch({ 
 		de = ednumber .. '. Auflage', 
 		en = ord{ednumber, lang = 'en'} .. ' edition',
 		fr = ord{ednumber, lang = 'fr'} .. ' édition',
 		nb = ord{ednumber, lang = 'nb'} .. ' utgave',
 		nn = ord{ednumber, lang = 'nn'} .. ' utgave',
 		}, lang)
 end
 
 local function getarticletitle(item, lang)
 	local title = wikidata.formatStatements({entity=item, property = 'P1476', lang=lang}) or wikidata.formatStatements({entity=item, property = 'P357', lang=lang})
 	if not title then
 		return '[[' .. item.id .. ']] (no title property provided!)'
 	end
 	return fb._langSwitch({
 		de = '„' .. '[[' .. item.id .. '|' .. title .. ']]' .. '“',
 		en = '&quot;' .. '[[' .. item.id .. '|' .. title .. ']]' .. '&quot;',
 		fr = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
 		nb = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
 		nn = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
 		} , lang)
 end
 
 local function getbooktitle(item, lang)-- needs i18n some languages do not use this format
 	local title = wikidata.formatStatements({entity=item, property = 'P1476', lang=lang}) or wikidata.formatStatements({entity=item, property = 'P357', lang=lang})
 	if not title then
 		return '[[' .. item.id .. ']] (no title property provided!)'
 	end
 	return '&lt;i&gt;' .. '[[' .. item.id .. '|' .. title .. ']]' .. '&lt;/i&gt;'
 end
 
 local function getissue(item, lang)
 	local issue = wikidata.formatStatements({entity=item, property = 'P433', numval = 1, lang=lang}) -- what to do if several values
 	if not issue then
 		return nil
 	end
 	return 'iss. ' .. issue -- needs i18n 
 end
 
 local function getArticleID(item, lang)
 	local articleid = wikidata.formatStatements({entity=item, property = 'P2322', numval = 1, lang=lang}) -- what to do if several values
 	if not articleid then
 		return nil
 	end
 	return '&lt;small&gt; article ID: ' .. articleid .. '&lt;/small&gt;' -- needs i18n 
 end
 
 local function getpublisher(item, lang)
 	return wikidata.formatStatements({entity=item, property = 'P123', lang=lang})
 end
 
 local function getpublishdate(item, lang)
 	return  wikidata.formatStatements({entity=item, property = 'P577', lang=lang})
 end
 
 local function geturl(item, lang)
 	return wikidata.formatStatements({entity=item, property = 'P854', lang=lang})
 end
 
 local function getlicense(item, lang)
 	return wikidata.formatStatements{entity=item, property = 'P275', lang=lang}
 end
 
 local function getjournal(item, lang) -- get the title property rather than the label
 	local journal = wikidata.getClaims({entity = item, property = 'P1433', exlcudespecial = true})
 	if not journal then
 		return nil
 	end
 	if #journal &gt; 1 then 
 		return &quot;error, source has too much publishing info&quot;
 	end
 	local journaltitle
 	local journalid = 'Q' .. journal[1].mainsnak.datavalue.value[&quot;numeric-id&quot;]
 	-- find higher work (if any; for example [[Q19302303]])
 	local journallink = wikidata.formatStatements({item = journalid , property = 'P1433', lang=lang})
 	if journallink then
 		return journallink
 	else
 		journaltitle = wikidata._getLabel(journalid)
 		return '&lt;i&gt;[[' .. journalid .. '|' .. journaltitle .. ']]&lt;/i&gt;'
 	end
 end
 
 local function citebook(item, lang, page)
 	local publishdate = getpublishdate(item, lang)
 	local author = getauthor(item, lang)
 	local authorstring = getauthorstring(item, lang)
 	local editor = getEditor(item, lang)
 	local title = getbooktitle(item, lang)
 	local publisher = getpublisher(item, lang)
 	local edition = getedition(item, lang)
 	local isbn = getISBN(item, lang)
 	local doi = getDoi(item, lang)
 	local pmid = getPmid(item, lang)
 	local pmcid = getPmcid(item, lang)
 	local arxivid = getArXivID(item, lang)
 	local link = getLink(item, lang)
 	local volume = getVolume(item, lang)
 	local pagenumber = formatpage(page, lang)
 	local license = getlicense(item, lang)
 
 	local fields = {}
 	table.insert(fields, author)
 	table.insert(fields, authorstring)
 	table.insert(fields, editor)
 	table.insert(fields, title)
 	table.insert(fields, edition)
 	table.insert(fields, volume)
 	table.insert(fields, publisher)
 	table.insert(fields, publishdate)
 	table.insert(fields, pagenumber)
 	table.insert(fields, isbn)
 	table.insert(fields, doi)
 	table.insert(fields, pmid)
 	table.insert(fields, pmcid)
 	table.insert(fields, arxivd)
 	table.insert(fields, link)
 	table.insert(fields, license)
 	return linguistic.conj(fields, lang, &quot;citation_comma&quot;)
 end
 
 local function citearticle(item, lang, page)
 	local author = getauthor(item, lang)
 	local authorstring = getauthorstring(item, lang)
 	local title = getarticletitle(item, lang)
 	local publisher = getpublisher(item, lang)
 	local publishdate = getpublishdate(item, lang)
 	local pagenumber = formatpage(page, lang)
 	local journal = getjournal(item, lang)
 	local issue = getissue(item, lang)
 	local articleid = getArticleID(item, lang)
 	local publishdate = getpublishdate(item, lang)
 	local doi = getDoi(item, lang)
 	local pmid = getPmid(item, lang)
 	local pmcid = getPmcid(item, lang)
 	local arxivid = getArXivID(item, lang)
 	local link = getLink(item, lang)
 	local volume = getVolume(item, lang)
 	local pagenumber = formatpage(page, lang)
 	local license = getlicense(item, lang)
 	
 	local fields = {}
 	table.insert(fields, author)
 	table.insert(fields, authorstring)
 	table.insert(fields, title)
 	table.insert(fields, publisher)
 	table.insert(fields, journal)
 	table.insert(fields, volume)
 	table.insert(fields, issue)
 	table.insert(fields, articleid)
 	table.insert(fields, publishdate)
 	table.insert(fields, pagenumber)
 	table.insert(fields, doi)
 	table.insert(fields, pmid)
 	table.insert(fields, pmcid)
 	table.insert(fields, arxivid)
 	table.insert(fields, link)
 	table.insert(fields, license)
 	return linguistic.conj(fields, lang, &quot;citation_comma&quot;)
 end
 
 function p.citeitem(item, lang, page)
 	if not item then return nil end
 	if type(item) == 'string' then
 		item = mw.wikibase.getEntityObject(item)
 	end
 	if not item then
 		return &quot;invalid item id&quot;
 	end
 	if wikidata.getClaims({entity = item, property = 'P1433'}) then -- if item has &quot;edition of&quot; is a book, else an article, needs a better solution
 		return citearticle(item, lang, page)
 	else
 		mw.log('Citing as book')
 		return citebook(item, lang, page)
 	end
 end
 
 function p.cite(frame)
 	local lang = frame.args.lang
 	if not lang or lang == '' then
 		lang = frame:preprocess('{{int:lang}}')
 	end
 	local page = frame.args.page
 	if page == '' then
 		page = nil
 	end
 	return p.citeitem(frame.args.item, lang, page)
 end
 
 function p.reflist(frame)
 	local list = mw.text.split( frame.args[1], ' ')
 	local lang = frame.args.lang
 	if not lang or lang == '' then
 		lang = frame:preprocess('{{int:lang}}')
 	end
 	local str = ''
 	for i, j in pairs(list) do
 		str = str ..  '&lt;li&gt; ' .. p.citeitem(mw.text.trim(j),lang) .. '&lt;/li&gt;'
 	end
 	return str
 end