「モジュール:Wikidata label」の版間の差分

提供:脳科学辞典
ナビゲーションに移動 検索に移動
(1版 をインポートしました)
(1版 をインポートしました)
 
(3人の利用者による、間の3版が非表示)
1行目: 1行目:
--[[
--[[
   __  __          _      _      __        ___ _    _    _      _          _      _          _  
   __  __          _      _      __        ___ _    _    _      _          _      _          _
  |  \/  | ___  __| |_  _| | ___ \ \      / (_) | _(_) __| | __ _| |_ __ _  | | __ _| |__  ___| |
  |  \/  | ___  __| |_  _| | ___ \ \      / (_) | _(_) __| | __ _| |_ __ _  | | __ _| |__  ___| |
  | |\/| |/ _ \ / _` | | | | |/ _ (_) \ /\ / /| | |/ / |/ _` |/ _` | __/ _` | | |/ _` | '_ \ / _ \ |
  | |\/| |/ _ \ / _` | | | | |/ _ (_) \ /\ / /| | |/ / |/ _` |/ _` | __/ _` | | |/ _` | '_ \ / _ \ |
  | |  | | (_) | (_| | |_| | |  __/_ \ V  V / | |  <| | (_| | (_| | || (_| | | | (_| | |_) |  __/ |
  | |  | | (_) | (_| | |_| | |  __/_ \ V  V / | |  <| | (_| | (_| | || (_| | | | (_| | |_) |  __/ |
  |_|  |_|\___/ \__,_|\__,_|_|\___(_) \_/\_/  |_|_|\_\_|\__,_|\__,_|\__\__,_| |_|\__,_|_.__/ \___|_|
  |_|  |_|\___/ \__,_|\__,_|_|\___(_) \_/\_/  |_|_|\_\_|\__,_|\__,_|\__\__,_| |_|\__,_|_.__/ \___|_|
                                                                                                 
 
This module is intended to be the engine behind "Template:Label".
This module is intended to be the engine behind "Template:Label".
Thic module was copied from Commons please ask for changes there.
This module was copied from Commons please ask for changes there.


Please do not modify this code without applying the changes first at "Module:Wikidata label/sandbox" and testing  
Please do not modify this code without applying the changes first at "Module:Wikidata label/sandbox" and testing
at "Module:Wikidata label/testcases".
at "Module:Wikidata label/testcases".


Authors and maintainers:
Authors and maintainers:
* User:Jarekt - original version  
* User:Jarekt - original version


Dependencies:
* Module:Yesno - used only if "show_id" parameter present
]]
]]


require('strict') -- used for debugging purposes as it detects cases of unintended global variables
--=============================================
--=== Internal functions ======================
--=============================================
---------------------------------------------------------------------------
-- Normalize input arguments by converting them all to lower case and
-- replacing space with "_" in the argument name. Also empty strings are
-- converted to nils. Arguments are collected from arguments passed to the
-- module and if missing from the template that calls the module
local function getArgs(frame)
local function normalize_input_args(input_args, output_args)
for name, value in pairs( input_args ) do
value = mw.text.trim(value) -- trim whitespaces from the beggining and the end of the string
if value ~= '' then -- nuke empty strings
if type(name)=='string' then
name = string.gsub( string.lower(name), ' ', '_')
end
output_args[name] = value
end
end
return output_args
end
local args = {}
args = normalize_input_args(frame:getParent().args, args)
args = normalize_input_args(frame.args, args)
return args
end
---------------------------------------------------------------------------
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to Module:Yesno but does not assume val is a string
local function yesno(val, default)
if type(val) == 'boolean' then
return val
elseif type(val) == 'number' then
if val == 1 then
return true
elseif val == 0 then
return false
end
elseif type(val) == 'string' then
val = mw.ustring.lower(val)  -- put in lower case
if val == 'no'  or val == 'n' or val == 'false' or val == '0' then
return false
elseif val == 'yes' or val == 'y' or val == 'true' or val == '1' then
return true
end
end
return default
end
-------------------------------------------------------------------------
-- get message in a given language
-- INPUTS:
-- * msg  - name of a message. For it to work [[MediaWiki:msg]] page need to be set up
-- * lang - translate message to language "lang"
-- * default - string to return in case this module is moved to a project where this message is not set
-- OUTPUT:
--  * translated message
local function getMessage(msg, lang, default)
msg = mw.message.new(msg):inLanguage(lang):plain()
return (msg == nil and default) or msg
end
---------------------------------------------------------------------------
-- use different sitelink call depending if you already have an entity or not
-- 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
--  * lang - language of the project
-- OUTPUT:
--  * sitelink
local function getSitelink(item, entity, lang)
local function getSitelink(item, entity, lang)
if entity and entity.getSitelink then -- if we have entity than use it
if entity and entity.getSitelink then -- if we have entity then use it
return entity:getSitelink(lang .. 'wiki')  
return entity:getSitelink(lang .. 'wiki')
else -- if no entity than use different function
else -- if no entity then use different function
return mw.wikibase.sitelink( item, lang .. 'wiki' )
return mw.wikibase.getSitelink(item, lang .. 'wiki')
end
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 getBestStatementsValue(item, entity, prop)
local statments
if entity then
statments = entity:getBestStatements(prop)
else
statments = mw.wikibase.getBestStatements(item, prop)
end
for _, statment in ipairs(statments) do
if statment and statment.mainsnak.datavalue.value then
return statment.mainsnak.datavalue.value
end
end
end
 
---------------------------------------------------------------------------
-- change capitalization of the label
-- INPUTS:
--  * label - label string
--  * capitalization - capitalization to be applied: allowed values are "tc", "lc",
--      "uc", "lcfirst", and "ucfirst". Any other value will return original string
--  * lang - language of the label
-- OUTPUT:
--  * value of the best statment (only from the first one)
local function apply_capitalization(label, capitalization, lang)
capitalization = string.lower(capitalization or 'none')
if capitalization == 'none' then
return label
elseif capitalization == 'uc' then
return mw.language.new(lang):uc(label)
elseif capitalization == 'lc' then
return mw.language.new(lang):lc(label)
elseif capitalization == 'tc' then -- title case
local new_label = {}
for _, word in ipairs(mw.text.split(label, ' ')) do
table.insert(new_label, mw.language.new(lang):ucfirst(word))
end
return table.concat(new_label, ' ')
elseif capitalization == 'ucfirst' then
return mw.language.new(lang):ucfirst(label)
elseif capitalization == 'lcfirst' then
return mw.language.new(lang):lcfirst(label)
end
return label
end
 
--[[-------------------------------------------------------------------------
get link based on user preference
INPUTS:
* link_type - can be :
  * "wikidata" - link to wikidata
  * "wikipedia" - link to wikipedia (language dependent)
  * "wikidata talk" - link to wikidata talk page
  * "commons" - link to commons (try sitelink then commons category then commons gallery)
  * "commonscat" - link to commons (try commons category then commons gallery)
  * "-" - means no link
* item  - entity ID (always provided)
* entity - whole entity. It can be nil if whole entity is not loaded
* langList - language fallback list for preferred language (required)
OUTPUT:
* link - link to the wikimedia page
]]
local function getLink(link_type, item, entity, langList)
local link, eLink
link_type = mw.ustring.lower(link_type or '')
local item_type = mw.ustring.sub(item, 1, 1) -- first letter prefix of item entity ID: 'Q', 'P' or 'M'
if item_type == 'M' then
eLink='c:Special:EntityPage/'..item
elseif item_type == 'Q' then
eLink='d:'..item -- wikibase entity page link
elseif item_type == 'P' then
eLink='d:Property:'..item -- wikibase entity page link
else
eLink='d:Special:EntityPage/'..item
end
if link_type == '-' then -- allow different link formats
link = ''            -- no link
elseif link_type == 'wikidata' or item_type == 'M' then
link = eLink        -- link to wikibase entity page
elseif link_type == 'wikidata talk' and item_type == 'P' then
link = 'd:Property talk:'.. item        -- link to wikidata property talk page
elseif link_type == 'wikidata talk' then
link = 'd:Talk:'..item  -- link to wikidata talk page
elseif link_type == 'commons' or link_type == 'commonscat' then
--[[
When link_type == 'commons' we try the following links (in specified order):
  1) commons sitelink
  2) P373 "Commons Category" claims
  3) P935 "Commons Gallery"  claims
Since most items have a commons sitelink we never have to look for claims
When link_type == 'commonscat' we try to maximize chances of commons link being a category, so we
      try the following links (in specified order):
  1) commons sitelink, which is kept if it points to a category
  2) P373 "Commons Category" claims
  3) commons sitelink (which does not point to a category)
  4) P935 "Commons Gallery"  claims
Since most pages have a commons sitelink we never have to look for claims
]]
local sLink = getSitelink(item, entity, 'commons')  -- look for sitelink to commons
if sLink then
sLink = 'c:'..sLink
if (link_type == 'commons') or (link_type == 'commonscat' and mw.ustring.find(sLink, 'Category:')) then
link = sLink
end
end
if not link then -- try linking to P373 "Commons Category"
local cat = getBestStatementsValue(item, entity, 'P373')
link = (cat ~= nil and 'c:Category:' .. cat) or nil
end
link = link or sLink
if not link then -- try linking to P935 "Commons Gallery"
link = getBestStatementsValue(item, entity, 'P935')
end
end
end
if not link then -- apply default "Wikipedia" link type
for _, language in ipairs(langList) do
local sitelink = getSitelink(item, entity, language)
if sitelink then
link = 'w:'.. language ..':'.. sitelink
break
end
end
end
return link or eLink  -- no wiki sitelink, so link to wikidata
end
end


--=============================================
--=== External functions ======================
--=============================================
local p = {}
local p = {}
--======================================================================
--=== API functions for use from other Scribunto modules ===============
--======================================================================


--[[
--[[
36行目: 247行目:


Inputs:
Inputs:
1: item - wikidata's item's q-code or entity class
1: item - wikidata's item's q-id or entity class
2: lang - desired language of the label
2: lang - desired language of the label
3: link_type - link style. Possible values: "wikipedia", "Wikidata", "Commons", or "-" (no link)
3: link_type - link style. Possible values (case-insensitive): "wikipedia", "wikidata", "Commons", or "-" (no link)
4: capitalization - can be "uc" (upper case), "lc" (lower case), "ucfirst" (upper case for the first letter),  
4: capitalization - can be "uc" (upper case), "lc" (lower case), "ucfirst" (upper case for the first letter),
"lcfirst" (lower case for the first letter)
"lcfirst" (lower case for the first letter), or 'none' (default)
 
Error Handling:
Error Handling:
Bad q-code will result in displayed error
Bad q-id will result in displayed error
]]
]]
function p._getLabel(item, lang, link_type, capitalization, show_id)
function p._getLabel(item, lang, link_type, capitalization, show_id)
local entity, s, link, label, language
local entity, s, link, label, language, desc


-- clean up the input parameters
-- clean up the input parameters
if type(item)~='string' then -- "item" is not a q-code
if type(item) ~= 'string' then -- "item" is not a q-id
entity = item            -- "item" must be the entity
entity = item            -- "item" must be the entity
item  = entity.id      -- look-up q-code
item  = entity.id      -- look-up q-id
elseif tonumber(item) then  -- if it is just the number than add "Q" in front
elseif tonumber(item) then  -- if it is just the number then add "Q" in front
item = 'Q'..item
item = 'Q'..item
end
end
item = string.gsub( string.upper(item), 'PROPERTY:P', 'P') -- make all the properties the same and capitalize
item = mw.ustring.gsub(mw.ustring.upper(item), 'PROPERTY:P', 'P') -- make all the properties the same and capitalize
 
if not lang then
label, lang = mw.wikibase.getLabelWithLang(item)
end
if not lang then -- if still no language
lang  = mw.getCurrentFrame():callParserFunction("int","lang")  -- get user's chosen language
label = nil
end
 
-- build language fallback list
-- build language fallback list
lang = string.lower(lang) or 'en'
lang = mw.ustring.lower(lang)
local langList = mw.language.getFallbacksFor(lang)
local langList = mw.language.getFallbacksFor(lang)
table.insert(langList, 1, lang)
table.insert(langList, 1, lang)
 
-- get label (visible part of the link)
-- get label (visible part of the link)
for _, language in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
if not label then
if entity then
for _, language in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
label = entity:getLabel(language)
if entity then
else
label = entity:getLabel(language)
label = mw.wikibase.getLabelByLang(item, language)
else
label = mw.wikibase.getLabelByLang(item, language)
end
if label then break end                    -- label found and we are done
end
end
if label then break end                    -- label found and we are done
end
end
if not label then                              -- no labels found, so just show the q-code
if label then  -- wikitext-escape the label if we have one
label = mw.text.nowiki(label)
end
if not label then                              -- no labels found, so just show the q-id
label = item
label = item
elseif show_id then          -- add id
elseif show_id then          -- add id
local yesno = require('Module:Yesno')
show_id = yesno(show_id,false)
show_id = yesno(show_id,false)
if show_id then  
if show_id then
local id = mw.getCurrentFrame():preprocess( "{{int:parentheses|" .. item .."}}")
local wordsep = getMessage('Word-separator', lang, ' ')
local wordsep  = mw.message.new( "Word-separator" ):inLanguage(lang):plain()
local id = mw.message.new('parentheses', item):inLanguage(lang):plain()
id = (id~=nil and id) or ('('..item..')') -- in case this module is moved to a project where {{int:parenthesis}} is not set
label = label .. wordsep .. "<small>" .. id .. "</small>"
label = label .. wordsep .. "<small>" .. id .. "</small>"
end
end
end
end
label = apply_capitalization(label, capitalization, lang)
-- change capitalization of the label
-- look for description
if capitalization=='ucfirst' then
if entity and entity.descriptions and lang then  
label = mw.language.new(lang):ucfirst(label)
for _, language in ipairs(langList) do
elseif capitalization=='lcfirst' then
if entity.descriptions[language] then
label = mw.language.new(lang):lcfirst(label)
desc = entity.descriptions[language].value  
elseif capitalization=='uc' then
break
label = mw.language.new(lang):uc(label)
elseif capitalization=='lc' then
label = mw.language.new(lang):lc(label)
end
 
-- create URL part of the link
link_type = string.lower(link_type or '')
local dLink = 'd:'..item; -- create fallback wikidata link
local item_type = string.sub(item, 1, 1) -- item's first letter:Q, P or M
if item_type == 'P' then
dLink = 'd:Property:'.. item
elseif item_type == 'M' then
dLink = 'Special:Redirect/page/' .. string.sub(item, 2)
end
if link_type=='-' then -- allow different link formats
link = ''            -- no link
elseif link_type=='wikidata' or item_type=='M' then
link = dLink        -- link to wikibase page
elseif link_type=='wikidata talk' and item_type=='P' then
link = 'd:Property talk:'.. item        -- link to wikidata property talk page
elseif link_type=='wikidata talk' then
link = 'd:Talk:'..item        -- link to wikidata talk page
elseif link_type=='commons' or link_type=='commonscat' then
-- For link_type=='commons' we try the following links (in that order):
--  1) sitelink to commons
--  2) "Commons Category" P373 property
--  3) "Commons Gallery"  P935 property
-- Since most pages have a sitelink to commons we never have to call expensive mw.wikibase.getEntity
-- For link_type=='commonscat' we try to maximize chances of commons link beeing a category, so we
--      try the following links (in that order):
--  1) sitelink to commons, which is kept if it points to a category
--  2) "Commons Category" P373 property
--  3) sitelink to commons (which does not point to a category)
--  4) "Commons Gallery"  P935 property
-- Since most pages have a sitelink to commons we never have to call expensive mw.wikibase.getEntity
local sLink = getSitelink(item, entity, 'commons')  -- look for sitelink to commons
if sLink then
sLink = 'c:'..sLink
if (link_type=='commons') or (link_type=='commonscat' and string.find( sLink, 'Category:')) then
link = sLink
end
end
if not link then -- try linking to P373 category
-- this is potentially memory expensive operation
entity = entity or mw.wikibase.getEntity(item);
assert(entity, "Item ID " .. item .. " is not valid")
s = entity:getBestStatements( 'P373' )
if s[1] and s[1].mainsnak.datavalue.value then  
link = 'c:Category:' .. s[1].mainsnak.datavalue.value
end
end
link = link or sLink
if not link then -- try linking to P935 gallery
-- there is no need for mw.wikibase.getEntity(item) call since at this point it was already loded
s = entity:getBestStatements( 'P935' )
if s[1] and s[1].mainsnak.datavalue.value then
link = s[1].mainsnak.datavalue.value
end
end
end
end
else
desc = mw.wikibase.getDescription(item)
end
end
if not link then-- apply default "Wikipedia" link type
if desc and link_type ~= '-' then -- wikitext-escape the description if we have one
for _, language in ipairs(langList) do
desc = mw.text.nowiki(desc) -- add description as hover text
local sitelink = getSitelink(item, entity, language)
label = '<span title="' .. desc .. '">' .. label .. '</span>'
if sitelink then
link = mw.ustring.format('w:%s:%s', language, sitelink)
break
end
end
end
end
link = link or dLink  -- no wiki sitelink, so link to wikidata
 
-- return the results
-- return the results
if link~='' then
if link_type == '-' then
return mw.ustring.format('[[%s|%s]]', link, label) -- return link
return label -- return just the label
else
else
return label -- return just a label
link = getLink(link_type, item, entity, langList)
return '[[' .. link .. '|' .. label .. ']]' -- return link
end
end
end
end


--[[
--[[-------------------------------------------------------------------------------
getLabel
_sitelinks
 
This function returns a label translated to desired language, created based on wikidata
This function returns a table of sitelinks for a single project organized by language


Usage:
Inputs:
{{#invoke:Wikidata label|getLabel|item=Q...|lang=..|link_style=..|capitalization=..}}
1: item - wikidata's item's q-id or entity class
2: project - (case-insensitive) one of: "wikipedia", "wikisource", "wikiquote", "wikibooks", "wikinews",
"wikiversity", "wikivoyage", "wiktionary", "commons", "mediawiki", "wikispecies", "wikidata", etc.


Parameters
Output:
1: wikidata's item's q-code (required)
Table of sitelinks with language fields
2: language (optional; default {{int:lang}} )
3: link_style: "wikipedia" (default), "Wikidata", "Commons", or "-" (no link)
4: capitalization - can be "uc", "lc", "ucfirst", "lcfirst"


Error Handling:
Output:
Bad q-code will result in displayed error
Table of sitelinks with language fields
See also
* [https://foundation.wikimedia.org/wiki/Special:SiteMatrix] for the full list of supported interwikis.
* [https://dumps.wikimedia.org/backup-index.html] for the full list of sitecodes (used in database dumps).
]]
]]
function p.getLabel(frame)
function p._sitelinks(item, project)
local args = frame.args
local entity, sitelink
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
-- get entity
args.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language
if type(item) == 'string' then -- "item" is a q-id
entity = mw.wikibase.getEntity(item)
else
entity = item              -- "item" is the entity
end
end
if (not args.link) or (mw.text.trim(args.link) == "") then
 
args.link = "wikipedia"
-- convert from english project name  to proproject code
local projLUT = {
wikipedia  = 'wiki',          commons  = 'commonswiki',
foundation  = 'foundationwiki', mediawiki = 'mediawikiwiki',
wikispecies = 'specieswiki',    wikidata  = 'wikidatawiki',
incubator  = 'incubatorwiki', oldwikisource = 'sourceswiki',
}
local langLUT = {
-- These are not language codes before the 'wiki' or 'wikiversity' suffix in a sitecode:
foundation = '~', commons = '~', -- they will be skipped
incubator  = '~', meta    = '~',
mediawiki  = '~', sources = '~',
species    = '~', beta    = '~',
-- Legacy language codes used in sitecodes, remapped to standard Wikimedia language codes:
-- See https://meta.wikimedia.org/wiki/Special_language_codes for details
als    = 'gsw', bat_smg      = 'sgs',
fiu_vro = 'vro', be_x_old    = 'be-tarask',
roa_rup = 'rup', zh_classical = 'lzh',
zh_yue  = 'yue', zh_min_nan  = 'nan',
zh_wuu  = 'wuu', no          = 'nb',
}
project = project:lower()
project = projLUT[project] or project -- correct the project name
local n = project:len()
local linkTable = {}
if entity and entity.sitelinks then  -- See if entity exists, and that it has sitelinks
for _, sitelink in pairs(entity.sitelinks) do -- loop over all sitelinks
local site = sitelink.site
local m    = site:len() - n
local proj = site:sub(m +1) -- project part of the siteID
if proj == project  then -- proj matches desired "project"
local lang = site:sub(1, m)  -- language part of the siteID
lang = langLUT[lang] or lang:gsub('_','-')
if lang ~= '~' then -- proj matches desired "project"
linkTable[lang] = sitelink.title
end
end
end
end
end
if (not args.capitalization) or (mw.text.trim(args.capitalization) == "") then
return linkTable
args.capitalization = "none"
end
args.item = mw.text.trim(args.item or '')
return p._getLabel(args.item, args.lang, args.link, args.capitalization, args.show_id)
end
end


--[[
--[[----------------------------------------------------------------
_sitelinks
_aliases


This function returns a table of sitelinks for a single project organized by language
This function returns a table of aliases for a single language


Inputs:
Inputs:
1: item - wikidata's item's q-code or entity class
1: item - wikidata's item's q-id or entity class
2: project - "wikipedia", "wikisource", "wikiquote", "wikibooks", "wikinews", "wikiversity",
2: lang - language code, like 'en' or 'de'
"wikivoyage", "wiktionary", "commons", "mediawiki", "wikispecies", "wikidata",  etc.


Output:
Output:
Table with language fields
Table of aliases with language fields
]]
]]
function p._sitelinks( item, project )
function p._aliases(item, lang)
local entity, sitelink
local entity
-- get entity
if type(item) == 'string' then -- "item" is a q-id
if type(item)=='string' then -- "item" is a q-code
entity = mw.wikibase.getEntity(item)
entity = mw.wikibase.getEntity(item);
else
else
entity = item            -- "item" is the entity
entity = item            -- "item" is the entity
item  = entity.id      -- look-up q-code
end
end
local aliasTable = {}
-- get project code
if entity and entity.aliases then -- See if there is an entity and that is has aliases
local LUT = {wikipedia='wiki', commons='commonswiki', mediawiki='mediawikiwiki', wikispecies='specieswiki', wikidata='wikidatawiki'}
if entity.aliases[lang] then -- See if it has English Aliases
project = string.lower(project)
for _, alias in pairs(entity.aliases[lang]) do -- Make a loop around the English aliases
if LUT[project] then -- correct the project name
table.insert(aliasTable, alias.value) -- Create a table of English aliases
project=LUT[project]
end
local n = string.len(project);
local s ={}
if entity and entity.sitelinks then   -- See if entity exists, and that it has sitelinks
for _, sitelink in pairs(entity.sitelinks) do -- loop over all sitelinks
  local site = sitelink.site
local lang = mw.ustring.sub( site, 1, mw.ustring.len(site) - n  )  -- language part of the siteID
local proj = mw.ustring.sub( site, mw.ustring.len(site) - n + 1 )  -- project part of the siteID
if proj == project then -- proj matches desired "project"
s[lang] = sitelink.title
end
end
end
end
end
end
return s
return aliasTable
end
end
--======================================================================
--=== Invoke functions for use from wikitext, e.g., templates ==========
---=====================================================================


--[[
--[[
getLabel
This function returns a label translated to desired language, created based on wikidata
Usage:
{{#invoke:Wikidata label|getLabel|item=Q...|lang=..|link_style=..|capitalization=..}}
Parameters
1: wikidata's item's q-id (required)
2: language (optional; default {{int:lang}})
3: link_style: "wikipedia" (default), "Wikidata", "Commons", or "-" (no link)
4: capitalization - can be "uc", "lc", "tc", "ucfirst", "lcfirst"
Error Handling:
Bad q-id will result in displayed error
]]
function p.getLabel(frame)
local args = getArgs(frame)
return p._getLabel(args.item, args.lang, args.link, args.capitalization, args.show_id)
end
--[[-------------------------------------------------------------------------------
sitelinks
sitelinks


254行目: 469行目:


Inputs:
Inputs:
1: item - wikidata's item's q-code or entity class
1: item - wikidata's item's q-id or entity class
2: project - "wikipedia" (or "wiki"), "wikisource", "wikiquote", "wikibooks", "wikinews", "wikiversity", "wikivoyage", "wiktionary", etc.
2: project - "wikipedia" (or "wiki"), "wikisource", "wikiquote", "wikibooks",
            "wikinews", "wikiversity", "wikivoyage", "wiktionary", etc.


Output:
Output:
261行目: 477行目:
]]
]]
function p.sitelinks(frame)
function p.sitelinks(frame)
local sitelinks = p._sitelinks(frame.args.item, frame.args.project)
local args = getArgs(frame)
local s = {}
local sitelinks = p._sitelinks(args.item, args.project)
for i, j in pairs(sitelinks) do
local sitelinkList = {}
table.insert(s, i .. ':' .. j)
for lang, sitelink in pairs(sitelinks) do
end
table.insert(sitelinkList, (lang=='' and sitelink) or (lang .. ':' .. sitelink))
return table.concat(s, ', ')
end
 
--[[
_aliases
 
This function returns a table of aliases for a single language
 
Inputs:
1: item - wikidata's item's q-code or entity class
2: lang - language code, like 'en' or 'de'
 
Output:
Table of aliases
]]
function p._aliases( item, lang )
local entity
if type(item)=='string' then -- "item" is a q-code
entity = mw.wikibase.getEntity(item);
else
entity = item            -- "item" is the entity
item  = entity.id      -- look-up q-code
end
end
local s = {}
return table.concat(sitelinkList, ', ')
if entity and entity.aliases then -- See if there is an entity and that is has aliases
if entity.aliases[lang] then -- See if it has English Aliases
for i, j in pairs(entity.aliases[lang]) do -- Make a loop around the English aliases
table.insert(s, j.value) -- Create a table of English aliases
end
end
end
return s
end
end


--[[
--[[----------------------------------------------------------------------------
aliases
aliases


310行目: 496行目:


Inputs:
Inputs:
1: item - wikidata's item's q-code or entity class
1: item - wikidata's item's q-id or entity class
2: lang - language code, like 'en' or 'de'
2: lang - language code, like 'en' or 'de'


317行目: 503行目:
]]
]]
function p.aliases(frame)
function p.aliases(frame)
return table.concat(p._aliases(frame.args.item, frame.args.lang), ', ')
local args = getArgs(frame)
return table.concat(p._aliases(args.item, args.lang), ', ')
end
end


return p
return p

2023年5月8日 (月) 09:09時点における最新版

このモジュールについての説明文ページを モジュール:Wikidata label/doc に作成できます

--[[
  __  __           _       _      __        ___ _    _     _       _          _       _          _
 |  \/  | ___   __| |_   _| | ___ \ \      / (_) | _(_) __| | __ _| |_ __ _  | | __ _| |__   ___| |
 | |\/| |/ _ \ / _` | | | | |/ _ (_) \ /\ / /| | |/ / |/ _` |/ _` | __/ _` | | |/ _` | '_ \ / _ \ |
 | |  | | (_) | (_| | |_| | |  __/_ \ V  V / | |   <| | (_| | (_| | || (_| | | | (_| | |_) |  __/ |
 |_|  |_|\___/ \__,_|\__,_|_|\___(_) \_/\_/  |_|_|\_\_|\__,_|\__,_|\__\__,_| |_|\__,_|_.__/ \___|_|

This module is intended to be the engine behind "Template:Label".
This module was copied from Commons please ask for changes there.

Please do not modify this code without applying the changes first at "Module:Wikidata label/sandbox" and testing
at "Module:Wikidata label/testcases".

Authors and maintainers:
* User:Jarekt - original version

]]

require('strict') -- used for debugging purposes as it detects cases of unintended global variables

--=============================================
--=== Internal functions ======================
--=============================================

---------------------------------------------------------------------------
-- Normalize input arguments by converting them all to lower case and
-- replacing space with "_" in the argument name. Also empty strings are
-- converted to nils. Arguments are collected from arguments passed to the
-- module and if missing from the template that calls the module
local function getArgs(frame)
	local function normalize_input_args(input_args, output_args)
		for name, value in pairs( input_args ) do
			value = mw.text.trim(value) -- trim whitespaces from the beggining and the end of the string
			if value ~= '' then -- nuke empty strings
				if type(name)=='string' then
					name = string.gsub( string.lower(name), ' ', '_')
				end
				output_args[name] = value
			end
		end
		return output_args
	end
	local args = {}
	args = normalize_input_args(frame:getParent().args, args)
	args = normalize_input_args(frame.args, args)
	return args
end

---------------------------------------------------------------------------
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to Module:Yesno but does not assume val is a string
local function yesno(val, default)
	if type(val) == 'boolean' then
		return val
	elseif type(val) == 'number' then
		if val == 1 then
			return true
		elseif val == 0 then
			return false
		end
	elseif type(val) == 'string' then
		val = mw.ustring.lower(val)  -- put in lower case
		if val == 'no'  or val == 'n' or val == 'false' or val == '0' then
			return false
		elseif val == 'yes' or val == 'y' or val == 'true' or val == '1' then
			return true
		end
	end
	return default
end

-------------------------------------------------------------------------
-- get message in a given language
-- INPUTS:
-- * msg  - name of a message. For it to work [[MediaWiki:msg]] page need to be set up
-- * lang - translate message to language "lang"
-- * default - string to return in case this module is moved to a project where this message is not set
-- OUTPUT:
--  * translated message
local function getMessage(msg, lang, default)
	msg = mw.message.new(msg):inLanguage(lang):plain()
	return (msg == nil and default) or msg
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
--  * lang - language of the project
-- OUTPUT:
--  * sitelink
local function getSitelink(item, entity, lang)
	if entity and entity.getSitelink then -- if we have entity then use it
		return entity:getSitelink(lang .. 'wiki')
	else -- if no entity then use different function
		return mw.wikibase.getSitelink(item, lang .. 'wiki')
	end
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 getBestStatementsValue(item, entity, prop)
	local statments
	if entity then
		statments = entity:getBestStatements(prop)
	else
		statments = mw.wikibase.getBestStatements(item, prop)
	end
	for _, statment in ipairs(statments) do
		if statment and statment.mainsnak.datavalue.value then
			return statment.mainsnak.datavalue.value
		end
	end
end

---------------------------------------------------------------------------
-- change capitalization of the label
-- INPUTS:
--  * label - label string
--  * capitalization - capitalization to be applied: allowed values are "tc", "lc",
--      "uc", "lcfirst", and "ucfirst". Any other value will return original string
--  * lang - language of the label
-- OUTPUT:
--  * value of the best statment (only from the first one)
local function apply_capitalization(label, capitalization, lang)
	capitalization = string.lower(capitalization or 'none')
	if capitalization == 'none' then
		return label
	elseif capitalization == 'uc' then
		return mw.language.new(lang):uc(label)
	elseif capitalization == 'lc' then
		return mw.language.new(lang):lc(label)
	elseif capitalization == 'tc' then -- title case
		local new_label = {}
		for _, word in ipairs(mw.text.split(label, ' ')) do
			table.insert(new_label, mw.language.new(lang):ucfirst(word))	
		end
		return table.concat(new_label, ' ')
	elseif capitalization == 'ucfirst' then
		return mw.language.new(lang):ucfirst(label)
	elseif capitalization == 'lcfirst' then
		return mw.language.new(lang):lcfirst(label)
	end
	return label
end

--[[-------------------------------------------------------------------------
get link based on user preference
INPUTS:
* link_type - can be :
   * "wikidata" - link to wikidata
   * "wikipedia" - link to wikipedia (language dependent)
   * "wikidata talk" - link to wikidata talk page
   * "commons" - link to commons (try sitelink then commons category then commons gallery)
   * "commonscat" - link to commons (try commons category then commons gallery)
   * "-" - means no link
* item   - entity ID (always provided)
* entity - whole entity. It can be nil if whole entity is not loaded
* langList - language fallback list for preferred language (required)
OUTPUT:
* link - link to the wikimedia page
]]
local function getLink(link_type, item, entity, langList)
	local link, eLink
	link_type = mw.ustring.lower(link_type or '')
	local item_type = mw.ustring.sub(item, 1, 1) -- first letter prefix of item entity ID: 'Q', 'P' or 'M'
	if item_type == 'M' then
		eLink='c:Special:EntityPage/'..item
	elseif item_type == 'Q' then
		eLink='d:'..item -- wikibase entity page link
	elseif item_type == 'P' then
		eLink='d:Property:'..item -- wikibase entity page link
	else
		eLink='d:Special:EntityPage/'..item
	end
	if link_type == '-' then -- allow different link formats
		link = ''            -- no link
	elseif link_type == 'wikidata' or item_type == 'M' then
		link = eLink        -- link to wikibase entity page
	elseif link_type == 'wikidata talk' and item_type == 'P' then
		link = 'd:Property talk:'.. item        -- link to wikidata property talk page
	elseif link_type == 'wikidata talk' then
		link = 'd:Talk:'..item   -- link to wikidata talk page
	elseif link_type == 'commons' or link_type == 'commonscat' then
		--[[
		When link_type == 'commons' we try the following links (in specified order):
		  1) commons sitelink
		  2) P373 "Commons Category" claims
		  3) P935 "Commons Gallery"  claims
		Since most items have a commons sitelink we never have to look for claims
		When link_type == 'commonscat' we try to maximize chances of commons link being a category, so we
		      try the following links (in specified order):
		  1) commons sitelink, which is kept if it points to a category
		  2) P373 "Commons Category" claims
		  3) commons sitelink (which does not point to a category)
		  4) P935 "Commons Gallery"  claims
		Since most pages have a commons sitelink we never have to look for claims
		]]
		local sLink = getSitelink(item, entity, 'commons')  -- look for sitelink to commons
		if sLink then
			sLink = 'c:'..sLink
			if (link_type == 'commons') or (link_type == 'commonscat' and mw.ustring.find(sLink, 'Category:')) then
				link = sLink
			end
		end
		if not link then -- try linking to P373 "Commons Category"
			local cat = getBestStatementsValue(item, entity, 'P373')
			link = (cat ~= nil and 'c:Category:' .. cat) or nil
		end
		link = link or sLink
		if not link then -- try linking to P935 "Commons Gallery"
			link = getBestStatementsValue(item, entity, 'P935')
		end
	end
	if not link then -- apply default "Wikipedia" link type
		for _, language in ipairs(langList) do
			local sitelink = getSitelink(item, entity, language)
			if sitelink then
				link = 'w:'.. language ..':'.. sitelink
				break
			end
		end
	end
	return link or eLink  -- no wiki sitelink, so link to wikidata
end

--=============================================
--=== External functions ======================
--=============================================
local p = {}

--======================================================================
--=== API functions for use from other Scribunto modules ===============
--======================================================================

--[[
_getLabel

This function returns a label translated to desired language, created based on wikidata

Inputs:
	1: item - wikidata's item's q-id or entity class
	2: lang - desired language of the label
	3: link_type - link style. Possible values (case-insensitive): "wikipedia", "wikidata", "Commons", or "-" (no link)
	4: capitalization - can be "uc" (upper case), "lc" (lower case), "ucfirst" (upper case for the first letter),
			"lcfirst" (lower case for the first letter), or 'none' (default)

Error Handling:
	Bad q-id will result in displayed error
]]
function p._getLabel(item, lang, link_type, capitalization, show_id)
	local entity, s, link, label, language, desc

	-- clean up the input parameters
	if type(item) ~= 'string' then -- "item" is not a q-id
		entity = item            -- "item" must be the entity
		item   = entity.id       -- look-up q-id
	elseif tonumber(item) then   -- if it is just the number then add "Q" in front
		item = 'Q'..item
	end
	item = mw.ustring.gsub(mw.ustring.upper(item), 'PROPERTY:P', 'P') -- make all the properties the same and capitalize

	if not lang then
		label, lang = mw.wikibase.getLabelWithLang(item)
	end
	if not lang then -- if still no language
		lang  = mw.getCurrentFrame():callParserFunction("int","lang")  -- get user's chosen language
		label = nil
	end

	-- build language fallback list
	lang = mw.ustring.lower(lang)
	local langList = mw.language.getFallbacksFor(lang)
	table.insert(langList, 1, lang)

	-- get label (visible part of the link)
	if not label then
		for _, language in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
			if entity then
				label = entity:getLabel(language)
			else
				label = mw.wikibase.getLabelByLang(item, language)
			end
			if label then break end                    -- label found and we are done
		end
	end
	if label then  -- wikitext-escape the label if we have one
		label = mw.text.nowiki(label)
	end
	if not label then                              -- no labels found, so just show the q-id
		label = item
	elseif show_id then           -- add id
		show_id = yesno(show_id,false)
		if show_id then
			local wordsep = getMessage('Word-separator', lang, ' ')
			local id = mw.message.new('parentheses', item):inLanguage(lang):plain()
			id = (id~=nil and id) or ('('..item..')') -- in case this module is moved to a project where {{int:parenthesis}} is not set
			label = label .. wordsep .. "<small>" .. id .. "</small>"
		end
	end
	label = apply_capitalization(label, capitalization, lang)
	
	-- look for description
	if  entity and entity.descriptions and lang then 
		for _, language in ipairs(langList) do
			if entity.descriptions[language] then
				desc = entity.descriptions[language].value 
				break
			end
		end
	else
		desc = mw.wikibase.getDescription(item)
	end
	if desc and link_type ~= '-' then  -- wikitext-escape the description if we have one
		desc = mw.text.nowiki(desc) -- add description as hover text
		label = '<span title="' .. desc .. '">' .. label .. '</span>'
	end

	-- return the results
	if link_type == '-' then
		return label -- return just the label
	else
		link = getLink(link_type, item, entity, langList)
		return '[[' .. link .. '|' .. label .. ']]' -- return link
	end
end

--[[-------------------------------------------------------------------------------
_sitelinks

This function returns a table of sitelinks for a single project organized by language

Inputs:
	1: item - wikidata's item's q-id or entity class
	2: project - (case-insensitive) one of: "wikipedia", "wikisource", "wikiquote", "wikibooks", "wikinews",
			"wikiversity", "wikivoyage", "wiktionary", "commons", "mediawiki", "wikispecies", "wikidata", etc.

Output:
	Table of sitelinks with language fields

Output:
	Table of sitelinks with language fields
See also
* [https://foundation.wikimedia.org/wiki/Special:SiteMatrix] for the full list of supported interwikis.
* [https://dumps.wikimedia.org/backup-index.html] for the full list of sitecodes (used in database dumps).
]]
function p._sitelinks(item, project)
	local entity, sitelink
	-- get entity
	if type(item) == 'string' then -- "item" is a q-id
		entity = mw.wikibase.getEntity(item)
	else
		entity = item              -- "item" is the entity
	end

	-- convert from english project name  to proproject code
	local projLUT = {
		wikipedia   = 'wiki',           commons   = 'commonswiki',
		foundation  = 'foundationwiki', mediawiki = 'mediawikiwiki',
		wikispecies = 'specieswiki',    wikidata  = 'wikidatawiki',
		incubator   = 'incubatorwiki',	oldwikisource = 'sourceswiki',
	}
	local langLUT = {
		-- These are not language codes before the 'wiki' or 'wikiversity' suffix in a sitecode:
		foundation = '~', commons = '~',	-- they will be skipped
		incubator  = '~', meta    = '~',
		mediawiki  = '~', sources = '~',
		species    = '~', beta    = '~',
		-- Legacy language codes used in sitecodes, remapped to standard Wikimedia language codes:
		-- See https://meta.wikimedia.org/wiki/Special_language_codes for details
		als     = 'gsw', bat_smg      = 'sgs',
		fiu_vro = 'vro', be_x_old     = 'be-tarask',
		roa_rup = 'rup', zh_classical = 'lzh',
		zh_yue  = 'yue', zh_min_nan   = 'nan',
		zh_wuu  = 'wuu', no           = 'nb',
	}
	project = project:lower()
	project = projLUT[project] or project -- correct the project name
	local n = project:len()
	local linkTable = {}
	if entity and entity.sitelinks then  -- See if entity exists, and that it has sitelinks
		for _, sitelink in pairs(entity.sitelinks) do -- loop over all sitelinks
			local site = sitelink.site
			local m    = site:len() - n
			local proj = site:sub(m +1)  -- project part of the siteID
			if proj == project  then -- proj matches desired "project"
				local lang = site:sub(1, m)  -- language part of the siteID
				lang = langLUT[lang] or lang:gsub('_','-')
				if lang ~= '~' then -- proj matches desired "project"
					linkTable[lang] = sitelink.title
				end
			end
		end
	end
	return linkTable
end

--[[----------------------------------------------------------------
_aliases

This function returns a table of aliases for a single language

Inputs:
	1: item - wikidata's item's q-id or entity class
	2: lang - language code, like 'en' or 'de'

Output:
	Table of aliases with language fields
]]
function p._aliases(item, lang)
	local entity
	if type(item) == 'string' then -- "item" is a q-id
		entity = mw.wikibase.getEntity(item)
	else
		entity = item            -- "item" is the entity
	end
	local aliasTable = {}
	if entity and entity.aliases then						-- See if there is an entity and that is has aliases
		if entity.aliases[lang] then						-- See if it has English Aliases
			for _, alias in pairs(entity.aliases[lang]) do  -- Make a loop around the English aliases
				table.insert(aliasTable, alias.value)				-- Create a table of English aliases
			end
		end
	end
	return aliasTable
end

--======================================================================
--=== Invoke functions for use from wikitext, e.g., templates ==========
---=====================================================================

--[[
getLabel

This function returns a label translated to desired language, created based on wikidata

Usage:
{{#invoke:Wikidata label|getLabel|item=Q...|lang=..|link_style=..|capitalization=..}}

Parameters
	1: wikidata's item's q-id (required)
	2: language (optional; default {{int:lang}})
	3: link_style: "wikipedia" (default), "Wikidata", "Commons", or "-" (no link)
	4: capitalization - can be "uc", "lc", "tc", "ucfirst", "lcfirst"

Error Handling:
	Bad q-id will result in displayed error
]]
function p.getLabel(frame)
	local args = getArgs(frame)
	return p._getLabel(args.item, args.lang, args.link, args.capitalization, args.show_id)
end

--[[-------------------------------------------------------------------------------
sitelinks

This function returns a comma separated list of sitelinks for a single project organized by language
Its main purpose is to help with testing of _sitelinks function.

Usage:
{{#invoke:Wikidata label|sitelinks|item=Q...|project=..}}

Inputs:
	1: item - wikidata's item's q-id or entity class
	2: project - "wikipedia" (or "wiki"), "wikisource", "wikiquote", "wikibooks",
	             "wikinews", "wikiversity", "wikivoyage", "wiktionary", etc.

Output:
	comma separated list
]]
function p.sitelinks(frame)
	local args = getArgs(frame)
	local sitelinks = p._sitelinks(args.item, args.project)
	local sitelinkList = {}
	for lang, sitelink in pairs(sitelinks) do
		table.insert(sitelinkList, (lang=='' and sitelink) or (lang .. ':' .. sitelink))
	end
	return table.concat(sitelinkList, ', ')
end

--[[----------------------------------------------------------------------------
aliases

This function returns a comma separated list of aliases for a single language
Its main purpose is to help with testing of _aliases function.

Usage:
{{#invoke:Wikidata label|aliases|item=Q...|lang=..}}

Inputs:
	1: item - wikidata's item's q-id or entity class
	2: lang - language code, like 'en' or 'de'

Output:
	Comma separated list of aliases
]]
function p.aliases(frame)
	local args = getArgs(frame)
	return table.concat(p._aliases(args.item, args.lang), ', ')
end

return p