細
fix issue with errors in the source field
細 (1版 をインポートしました) |
bsd>Jarekt 細 (fix issue with errors in the source field) |
||
14行目: | 14行目: | ||
* User:Jarekt - original version | * User:Jarekt - original version | ||
]] | ]] | ||
local ISOdate = require('Module:ISOdate') | -- ======================================= | ||
-- === Dependencies ====================== | |||
-- ======================================= | |||
require('Module:No globals') -- 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 function langWrapper(text, textLang | -- === Internal functions =========================== | ||
-- ================================================== | |||
local function langWrapper(text, textLang) | |||
-- code equivalent to https://commons.wikimedia.org/wiki/Template:Description | -- code equivalent to https://commons.wikimedia.org/wiki/Template:Description | ||
local | local language = mw.language.new( textLang ) | ||
local str = | local dir = language:getDir() | ||
return | local LangName = language:ucfirst(mw.language.fetchLanguageName( textLang, textLang)) | ||
local str = mw.ustring.format('<span class="language %s"><b>%s:</b></span>', textLang, LangName) | |||
return mw.ustring.format('<div class="description mw-content-%s" dir="%s" lang="%s">%s %s</div>', dir, dir, textLang, str, text) | |||
end | |||
------------------------------------------------------------------------------- | |||
local function getBareLabel(id, userLang) | |||
-- code equivalent to require("Module:Wikidata label")._getLabel with Wikidata=- option | |||
local label, link | |||
-- build language fallback list | |||
local langList = mw.language.getFallbacksFor(userLang) | |||
table.insert(langList, 1, userLang) | |||
for _, lang in ipairs(langList) do -- loop over language fallback list looking for label in the specific language | |||
label = mw.wikibase.getLabelByLang(id, lang) | |||
if label then break end -- label found and we are done | |||
end | |||
return label or id | |||
end | |||
------------------------------------------------------------------------------- | |||
local function message(name, lang) | |||
return mw.message.new( 'wm-license-information-'..name ):inLanguage(lang):plain() | |||
end | end | ||
29行目: | 58行目: | ||
-- ==================================================================== | -- ==================================================================== | ||
local function Build_html(args) | local function Build_html(args) | ||
local lang = args.lang -- user's language | |||
local | local dir = mw.language.new( lang ):getDir() -- get text direction | ||
local desTag = mw.ustring.format('<span class="summary fn" style="display:none">%s</span>', args.pagename) | |||
local prmTag = mw.ustring.format("<br /><small>([[%s|%s]])</small>", message('permission-reusing-link', lang), | |||
message('permission-reusing-text', lang)) | |||
local dir = mw.language.new( | |||
-- | -- field specific preferences | ||
local params = { | local params = { | ||
{field='description' , id='fileinfotpl_desc' | {field='description' , id='fileinfotpl_desc', tag2=desTag, td='class="description"'}, | ||
{field='other_fields_1'}, | {field='other_fields_1'}, | ||
{field='date' , id='fileinfotpl_date' | {field='date' , id='fileinfotpl_date', td=mw.ustring.format('lang="%s"', lang)}, | ||
{field='source' , id='fileinfotpl_src | {field='source' , id='fileinfotpl_src'}, | ||
{field='author' , id='fileinfotpl_aut | {field='author' , id='fileinfotpl_aut'}, | ||
{field='permission' , id='fileinfotpl_perm' | {field='permission' , id='fileinfotpl_perm', tag2=prmTag }, | ||
{field='other_versions' , id='fileinfotpl_ver' | {field='other_versions' , id='fileinfotpl_ver', tag='other-versions'}, | ||
{field='other_fields'} | {field='other_fields'}, | ||
} | } | ||
local results = {} | local results = {} | ||
55行目: | 79行目: | ||
local field, tag, cell1, cell2, id | local field, tag, cell1, cell2, id | ||
field = args[param.field] | field = args[param.field] | ||
if param.id then -- skip "other fields" parameter | if param.id then -- skip "other fields" parameter | ||
if field then -- add "id" to first <td> cell only if the field is present | if type(field) == 'string' then -- add "id" to first <td> cell only if the field is present | ||
id = | id = mw.ustring.format('id="%s" ', param.id) | ||
elseif | elseif type(field) == 'table' then | ||
-- the field was initially not present, it contains only our | |||
-- warning text; flatten it so that mw.ustring.format() gets a string | |||
field = field.missing | |||
field = | |||
end | end | ||
if field or args.demo then -- skip the row if still no field | if field or (args.demo and param.tag) then -- skip the row if still no field | ||
tag = param.tag | tag = message(param.tag or param.field, lang) .. (param.tag2 or '') | ||
cell1 = mw.ustring.format('<td %sclass="fileinfo-paramfield" lang="%s">%s</td>\n', id or '', lang, tag) | |||
cell2 = mw.ustring.format('<td %s>\n%s</td>', param.td or '', field or '') | |||
field = mw.ustring.format('<tr style="vertical-align: top">\n%s%s\n</tr>\n\n', cell1, cell2) | |||
cell1 = | |||
cell2 = | |||
field = | |||
end | end | ||
end | end | ||
82行目: | 98行目: | ||
-- add table and outer layers | -- add table and outer layers | ||
local style = | local style = mw.ustring.format('class="fileinfotpl-type-information toccolours vevent '.. | ||
'mw-content-%s" style="width: 100%%; direction: %s;" cellpadding="4"', dir, dir) | 'mw-content-%s" style="width: 100%%; direction: %s;" cellpadding="4"', dir, dir) | ||
results = | results = mw.ustring.format('<table %s>\n\n%s\n</table>\n', style, table.concat(results)) | ||
results = | results = mw.ustring.format('<div class="hproduct commons-file-information-table">\n%s\n</div>', results) | ||
return results | return results | ||
end | end | ||
97行目: | 113行目: | ||
-- === Version of the function to be called from other LUA codes | -- === Version of the function to be called from other LUA codes | ||
-- =========================================================================== | -- =========================================================================== | ||
------------------------------------------------------------------------------- | |||
-- _information function creates a wikicode for {{Information}} template based on | |||
-- passed arguments (through "args") and data extracted from SDC. Allowed fields of | |||
-- "args" are : 'description', 'date', 'permission', 'author', 'other_versions', | |||
-- 'source','other_fields', 'other_fields_1', 'demo' and 'lang' | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: p._SDC_Description, p._SDC_Source, p._SDC_Author, p._SDC_Date, | |||
-- Build_html, Module:ISOdate (_date) | |||
------------------------------------------------------------------------------- | |||
function p._information(args) | function p._information(args) | ||
105行目: | 131行目: | ||
-- ============================================================================================ | -- ============================================================================================ | ||
local page = mw.title.getCurrentTitle() | local page = mw.title.getCurrentTitle() | ||
local lang = args.lang | |||
local namespace = page.namespace -- get page namespace | local namespace = page.namespace -- get page namespace | ||
if namespace==6 or namespace==10 then | if namespace==6 or namespace==10 then | ||
local allowedFields = {'description', 'date', 'permission', 'author', 'other_versions', | local allowedFields = {'description', 'date', 'permission', 'author', 'other_versions', | ||
'source','other_fields', 'other_fields_1', 'demo', 'lang | 'source','other_fields', 'other_fields_1', 'demo', 'lang'} | ||
local set, badField = {}, {} | local set, badField = {}, {} | ||
for _, field in ipairs(allowedFields) do set[field] = true end | for _, field in ipairs(allowedFields) do set[field] = true end | ||
117行目: | 144行目: | ||
end | end | ||
if #badField>0 then | if #badField>0 then | ||
cats = | cats = mw.ustring.format('\n;<span style="color:red">Error in [[Template:Information|{{Information}}'.. | ||
' template]]: unknown parameter "%s".</span>', table.concat(badField,'", "')) | ' template]]: unknown parameter "%s".</span>', table.concat(badField,'", "')) | ||
cats = cats .. '\n[[Category:Pages using Information template with incorrect parameter]]' | cats = cats .. '\n[[Category:Pages using Information template with incorrect parameter]]' | ||
end | end | ||
end | end | ||
if | if args.date then | ||
-- apply ISODate to function to date string to convert date in ISO format to translated date string | |||
args.date = ISOdate(args.date, lang, '', 'dtstart', '100-999') | |||
end | |||
args.pagename = page.text | |||
135行目: | 159行目: | ||
-- === harvest structured data === | -- === harvest structured data === | ||
-- ==================================================== | -- ==================================================== | ||
local entity = mw.wikibase.getEntity() | |||
if namespace==6 and | if namespace==6 and entity then -- file namespace | ||
-- call SDC functions only when needed | |||
local icon = true | |||
-- local field is missing -> get it from SDC | |||
args.description = args.description or p._SDC_Description(entity, lang, icon) | |||
args.source = args.source or p._SDC_Source(entity, lang, icon) | |||
args.author = args.author or p._SDC_Author(entity, lang, icon) | |||
args.date = args.date or p._SDC_Date(entity, lang, icon) | |||
end | |||
end | |||
-- ==================================================== | -- ==================================================== | ||
-- === add | -- === add tracking templates and categories === | ||
-- ==================================================== | -- ==================================================== | ||
-- add the template tag (all official infoboxes transclude {{Infobox template tag}} so files without that tag do not have an infobox | -- add the template tag (all official infoboxes transclude {{Infobox template tag}} so files without that tag do not have an infobox | ||
mw.getCurrentFrame():expandTemplate{ title = 'Infobox template tag' } | |||
if args. | |||
-- | -- files are required to have at least the 3 fields below | ||
args. | local reqFields = {description='Media lacking a description', author='Media lacking author information', source='Images without source'} | ||
end | for field, errCat in pairs(reqFields) do | ||
if args[field] and mw.ustring.match(args[field],"^[%s%p]+$") then | |||
args[field]=nil; | |||
end -- ignore punctuation only fields | |||
if not args[field] then | |||
-- code equivalent to Template:Source missing, Template:Author missing, Template:Description missing | |||
local tag1 = 'class="boilerplate metadata" id="cleanup" style="text-align: center; background: #ffe; '.. | |||
'margin: .75em 15%; padding: .5em; border: 1px solid #e3e3b0;' | |||
local tag2 = message(field..'-missing', lang) | |||
local tag3 = message(field..'-missing-request', lang) | |||
local dir = mw.language.new( lang ):getDir() -- get text direction | |||
args[field] = {missing = mw.ustring.format('<div %s direction: %s;" lang="%s">%s\n%s\n</div>', tag1, dir, lang, tag2, tag3)} | |||
cats = cats .. '\n[[Category:'.. errCat ..']]' | |||
end | |||
end | |||
if namespace~=6 then | |||
cats = '' -- categories are added only to files | |||
end | |||
return Build_html(args) .. cats | return Build_html(args) .. cats | ||
end | end | ||
-- =============================== | ------------------------------------------------------------------------------- | ||
-- | -- interface for other Lua codes to 5 functions for extracting description, source, | ||
-- =================== | -- author, date and location information from SDC. | ||
function p. | -- INPUTS: | ||
-- | -- - "entity" - structure created by mw.wikibase.getEntity function | ||
local | -- - "lang" - users language | ||
------------------------------------------------------------------------------- | |||
-- Dependencies: langWrapper | |||
------------------------------------------------------------------------------- | |||
function p._SDC_Description(entity, lang, icon) | |||
-- create {{en|1=...}} template with SDC's caption | |||
local description, _ | |||
if entity and entity.labels then -- get label in users language or one of that language fallback list | |||
local label = core.langSwitch(entity.labels, lang) | |||
local labels, D = {}, {} | |||
if label then -- show either matching language | |||
labels[lang] = label | |||
else -- or if missing then show all | |||
labels = entity.labels | |||
end | |||
for _, label in pairs(labels) do -- add {{en|1=....}} like wrapper | |||
if icon and #D==0 then -- add editAtSDC icon to the first description | |||
label.value = label.value .. core.editAtSDC('ooui-php-4', lang) | |||
end | |||
table.insert(D, langWrapper(label.value, label.language, lang)) | |||
end | |||
description = table.concat(D, '\n') | |||
end | |||
return description | |||
end | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: Module:Wikidata_date "_date" function, Module:ISOdate "_ISOdate" function | |||
------------------------------------------------------------------------------- | |||
function p._SDC_Date(entity, lang, icon) | |||
-- get creation date from P571 (inception) | |||
-- Code can handle YYYY-MM-DD, YYYY-MM, and YYYY dates without any additional resources | |||
-- But can load [[Module:Wikidata date]] if needed | |||
local Date | |||
if entity and entity.claims and entity.claims.P571 then | |||
local snak = entity.claims.P571[1].mainsnak | |||
if (snak.snaktype == "value") then | |||
local v = snak.datavalue.value | |||
if v and (v.calendarmodel=='http://www.wikidata.org/entity/Q1985727') and (mw.ustring.sub(v.time,1,1)=='+') then | |||
if v.precision >= 11 then -- day | |||
Date = mw.ustring.sub(v.time,2,11) -- date in YYYY-MM-DD format | |||
elseif v.precision == 10 then -- month | |||
Date = mw.ustring.sub(v.time,2,8) -- date in YYYY-MM format | |||
elseif v.precision == 9 then -- year | |||
Date = mw.ustring.sub(v.time,2,5) -- date in YYYY format | |||
end | |||
if Date then -- translate | |||
Date = ISOdate(Date, lang, '', 'dtstart', '100-999') | |||
end | |||
end | |||
end | |||
if entity.claims.P571[1].qualifiers then -- non-trivial case: call heavy cavalery | |||
local getDate = require("Module:Wikidata date")._date -- lazy loading: load only if needed | |||
local result = getDate(entity, 'P571', lang) -- display the date in user's language | |||
Date = result.str | |||
end | |||
end | |||
if icon and Date then | |||
Date = Date .. core.editAtSDC('P571', lang) | |||
end | |||
return Date | |||
end | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: none | |||
------------------------------------------------------------------------------- | |||
function p._SDC_Source(entity, lang, icon) | |||
-- get source from P7482 (source of file) | |||
-- Code can handle {{Own}} template and URLs | |||
local source, label | |||
if entity and entity.claims and entity.claims.P7482 then | |||
local statement = entity.claims.P7482[1] | |||
-- get URL is source is " file available on the internet (Q74228490) " | |||
if statement.mainsnak.datavalue.value.id=='Q74228490' and statement.qualifiers and statement.qualifiers.P973 then | |||
source = statement.qualifiers.P973[1].datavalue.value -- described at URL | |||
if statement.qualifiers.P137 then -- "operator" | |||
local id = statement.qualifiers.P137[1].datavalue.value.id | |||
label = getBareLabel(id, lang) | |||
source = '[' .. source ..' ' .. label ..']' | |||
end | |||
end | |||
-- add {{tl|own}} if source is "original creation by uploader (Q66458942)" | |||
if statement.mainsnak.datavalue.value.id=='Q66458942' then | |||
label = mw.message.new( 'Wm-license-own-work'):inLanguage(lang):plain() | |||
source = mw.ustring.format('<span class="int-own-work" lang="%s">%s</span>',lang, label) | |||
end | |||
-- add {{tl|Own work by the original uploader}} if source is " Own work by the original uploader (Q87402110)" | |||
if statement.mainsnak.datavalue.value.id=='Q87402110' then | |||
label = getBareLabel('Q87402110', lang) | |||
source = mw.ustring.format('<span class="int-own-work" lang="%s">%s</span>',lang, label) | |||
end | |||
end | |||
if icon and source then | |||
source = source .. core.editAtSDC('P7482', lang) | |||
end | |||
return source | |||
end | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: Module:Core "getLabel" function | |||
------------------------------------------------------------------------------- | |||
function p._SDC_Author(entity, lang, icon) | |||
-- get author from P170 (creator) | |||
-- Code can handle usuall cases of "[[User:Example|Example]]" as well as users with Wikidata Item IDs | |||
local author | |||
if entity and entity.claims and entity.claims.P170 then | |||
local creators = {} | |||
for _,statement in ipairs(entity.claims.P170) do | |||
if statement.mainsnak.snaktype == "value" then -- Creator has item ID | |||
local val = statement.mainsnak.datavalue.value.id | |||
table.insert(creators, core.getLabel(val, lang)) | |||
elseif statement.mainsnak.snaktype == "somevalue" then -- Creator defined by username | |||
if statement.qualifiers then -- author name string (P2093) | |||
local qual = {} | |||
local properties = {P2093='authorStr', P4174='username', P3831='role', P2699='url'} | |||
for prop, field in pairs( properties ) do | |||
if statement.qualifiers[prop] then | |||
qual[field] = statement.qualifiers[prop][1].datavalue.value | |||
end | |||
end | |||
local role = '' | |||
if qual.role and entity.claims.P170[2] then -- add role only is multiple creators | |||
role = ' (' .. core.getLabel(qual.role.id, lang) .. ')' | |||
end | |||
if qual.username and qual.authorStr then -- author name string (P2093) & Wikimedia username (P4174) | |||
table.insert(creators, '[[User:'..qual.username..'|'..qual.authorStr..']]'..role) | |||
elseif qual.username and not qual.authorStr then -- no author name string (P2093) & Wikimedia username (P4174) | |||
table.insert(creators, '[[User:'..qual.username..'|'..qual.username..']]'..role) | |||
elseif qual.url and qual.authorStr then -- author name string (P2093) & URL (P2699) | |||
table.insert(creators, '['..qual.url..' '..qual.authorStr..']'..role) | |||
elseif qual.url and not qual.authorStr then -- no author name string (P2093) & URL (P2699) | |||
table.insert(creators, qual.url..role) | |||
elseif qual.authorStr then -- author name string (P2093) | |||
table.insert(creators, qual.authorStr..role) | |||
end | |||
end | |||
end | |||
end -- end for | |||
author = table.concat(creators, ', ') | |||
end | |||
if icon and author then | |||
author = author .. core.editAtSDC('P170', lang) | |||
end | |||
return author | |||
end | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: Module:Code "getLabel" function | |||
------------------------------------------------------------------------------- | |||
function p._SDC_Location(entity, lang, icon) | |||
-- get location P276 (location) | |||
local location, prop | |||
if entity and entity.claims and entity.claims.P1071 then | |||
local snak = entity.claims.P1071[1].mainsnak | |||
if (snak.snaktype == "value") then | |||
location = core.getLabel(snak.datavalue.value.id, lang) | |||
prop = 'P1071' | |||
end | end | ||
end | end | ||
if entity and entity.claims and entity.claims.P276 then | |||
if value | local snak = entity.claims.P276[1].mainsnak | ||
if (snak.snaktype == "value") then | |||
location = core.getLabel(snak.datavalue.value.id, lang) | |||
prop = 'P276' | |||
end | end | ||
end | end | ||
if icon and location then | |||
if | location = location .. core.editAtSDC(prop, lang) | ||
end | end | ||
return location | |||
end | |||
return p._information(args) | |||
-- =========================================================================== | |||
-- === Version of the functions to be called from template namespace | |||
-- =========================================================================== | |||
------------------------------------------------------------------------------- | |||
-- information function creates a wikicode for {{Information}} template based on | |||
-- passed arguments (through "frame") and data extracted from SDC. Allowed template | |||
-- arguments are : 'description', 'date', 'permission', 'author', 'other_versions', | |||
-- 'source','other_fields', 'other_fields_1', 'demo' and 'lang'. All inputs do not | |||
-- depend on capitalization and all "_" can be replaced with spaces. | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: p._information | |||
------------------------------------------------------------------------------- | |||
function p.information(frame) | |||
return p._information(core.getArgs(frame)) | |||
end | |||
------------------------------------------------------------------------------- | |||
-- interface for templates to 5 functions for extracting description, source, | |||
-- author, date and location information from SDC. | |||
-- INPUTS (templaate parameters): | |||
-- * "mid" - pageID defining a file. Optional, defaulting to the current file. | |||
-- * "lang" - users language. Optional defaulting to the language of the user | |||
-- * "icon" - add "Edit this at Wikidata" icon? boolean ( 'true'/'false', 'yes'/'no', 1/0 | |||
------------------------------------------------------------------------------- | |||
-- Dependencies: getEntity | |||
------------------------------------------------------------------------------- | |||
local function parseFrame(frame) | |||
local args = core.getArgs(frame) | |||
local entity = mw.wikibase.getEntity( args.mid ) | |||
local icon = core.yesno(args.icon, true) | |||
return {entity, args.lang, icon} | |||
end | |||
function p.SDC_Description(frame) | |||
return p._SDC_Description(unpack(parseFrame(frame))) | |||
end | |||
function p.SDC_Source(frame) | |||
return p._SDC_Source(unpack(parseFrame(frame))) | |||
end | |||
function p.SDC_Author(frame) | |||
return p._SDC_Author(unpack(parseFrame(frame))) | |||
end | |||
function p.SDC_Date(frame) | |||
return p._SDC_Date(unpack(parseFrame(frame))) | |||
end | |||
function p.SDC_Location(frame) | |||
return p._SDC_Location(unpack(parseFrame(frame))) | |||
end | end | ||
return p | return p | ||
------------------------------------------------------------------------------- | |||
-- List of exported functions | |||
------------------------------------------------------------------------------- | |||
-- information | |||
-- SDC_Description | |||
-- SDC_Source | |||
-- SDC_Author | |||
-- SDC_Date | |||
-- SDC_Location |