模組:WikidataLink
local p={}
local lib_arg={};
local ilh = {}
local TrackingCategory = {}
local yesno = {}
local lib_va = {}
local wiki_db = {}
local wikidata_entity_namespaces = {['e']='EntitySchema', ['l']='Lexeme', ['p']='Property', ['q']=''}
local wikidata_namespaces_support = {['p']=true, ['q']=true}
local project_table = {
commons = ".wikimedia",
meta = ".wikimedia",
species = ".wikimedia"
}
function p.title2entity(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {parentFirst=true})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
if type(yesno) ~= type(type) then yesno = require('Module:Yesno') end
local with_nodata = yesno(args['with_nodata'] or args['with nodata'])
local input_title = mw.text.trim(tostring(args['1'] or args[1] or ''))
--如果內容為空,取消計算,回傳本模板所在頁面的維基數據項目
if mw.text.trim(input_title) == '' then
return mw.wikibase.getEntityIdForCurrentPage() or ''
end
local entity_id = mw.wikibase.getEntityIdForTitle(input_title)
if entity_id then return tostring(entity_id) end
local title_obj = mw.title.new(input_title)
--如果條目存在
if (title_obj or {}).exists == true then
--檢查原始頁面是否有維基數據項目
local title_id = mw.wikibase.getEntityIdForTitle(title_obj.prefixedText)
--如果有,則回傳
if title_id then return title_id end
--如果目標頁是重新導向頁
title_obj = title_obj.redirectTarget
--回傳目標頁的維基數據項目
if title_obj and type(title_obj)==type({"table"}) then
entity_id = mw.wikibase.getEntityIdForTitle(title_obj.prefixedText)
end
return entity_id
end
--如果本身已經是維基數據項目
local start,tail = mw.ustring.find(input_title,'[qQ]%d+')
if start then
local in_id = 'Q' .. mw.ustring.sub(input_title,start+1,tail)
if mw.wikibase.getLabel(in_id) ~= nil then return in_id
else return '' end
end
local try_parse = mw.ustring.gsub(input_title,'[.,]','')
if with_nodata then
--提供無值時,又不自我指向的數值
if mw.ustring.lower(input_title) == "noentity" then return 'Q28343326' end--無值
end
if type(lib_va.redirect_target) ~= type(type) then lib_va = require('Module:Va') end
--如果目標頁是繁簡差異的自動重新導向頁
title_obj = mw.title.new(lib_va.redirect_target(input_title))
--如果檢查繁簡差異後發現頁面存在
if (title_obj or {}).exists == true then
--嘗試取得存在之頁面的維基數據項目
local title_id = mw.wikibase.getEntityIdForTitle(title_obj.prefixedText)
--如果項目存在,則返回數值
if title_id then return title_id end
end
--嘗試讀取數字是否為維基數據項目
start,tail = mw.ustring.find(try_parse,'%d+')
if start then
local parseNum = tonumber(mw.ustring.sub(try_parse,start,tail) or '0') or 0
if mw.wikibase.getLabel('Q'..parseNum) ~= nil then return 'Q'..parseNum
else return '' end
end
--是非空字串,但都不是的情況
if mw.text.trim(try_parse) ~= '' then return '' end
--如果以上條件都不滿足,回傳本模板所在頁面的維基數據項目
return mw.wikibase.getEntityIdForCurrentPage() or ''
end
function _wikidata_ilh(arg)
if type(ilh._ilh) ~= type(type) then ilh = require('Module:Ilh') end
if type(yesno) ~= type(type) then yesno = require('Module:Yesno') end
local context={}
context["isMainPage"]=ilh.isMainPage()
context["localPage"]=arg[1]
context["foreignPage"]=arg[2] or arg[1] --如果{{{2}}}不传入的话
local _d=arg["d"]
local _1=arg[1] or arg["1"]
local _3=arg[3] or arg["3"]
local dpN1=_3 or _d
context["displayName"]=(dpN1 and {dpN1} or {_1})[1]
context["langCode"]=arg["lang-code"]
context["lang"]=arg["lang"]
context["nocat"]=yesno( arg["nocat"] , false )
context["isExist"]= (arg["$exist$"] and arg["$exist$"]==1) or ilh.isExist(context["localPage"])
local curPage_obj=mw.title.getCurrentTitle()
context["isNoCatWithNamespace"]=curPage_obj:inNamespaces(2,828) --User,Module
--context["curPageNamespace"]=curPage_obj.namespace
return (context["isMainPage"] and ilh.onlyLink(context)) or ilh.functionLink(context)
end
local function getEntitySitelink(entity)
local sitelinks = (entity or {}).sitelinks
if sitelinks then
local i = 0
for _,__ in pairs(sitelinks) do i = i + 1 end
if i <= 0 then return nil, nil end
if not wiki_db.data then wiki_db = mw.loadData('Module:NUMBEROF/data') end
local db_map, db_data = wiki_db.map, wiki_db.data
if not db_map or not db_data then return nil, nil end
local max_lang, max_sitelinkObj, max_article = nil, nil, -1
for lang, sitelinkObj in pairs(sitelinks) do
local lang_name = lang:match("^(.+)wiki$")
if lang_name and lang_name ~= "commons" then
local wikiCountObj = db_data[lang_name..(project_table[lang_name] or '.wikipedia')]
if wikiCountObj then
local wikiCount = tonumber(wikiCountObj[db_map.articles])
if type(wikiCount) == type(0) then
if wikiCount > max_article then
max_article = wikiCount
max_lang = lang_name
max_sitelinkObj = sitelinkObj
end
end
end
end
end
if max_sitelinkObj then
return max_lang, max_sitelinkObj.title
end
end
return nil, nil
end
local function getEntityLabel(entity)
local label = entity:getLabel()
if not label then
labels = entity.labels
if not labels then return nil end
local i = 0
for _,__ in pairs(labels) do i = i + 1 end
if i <= 0 then return nil end
if not wiki_db.data then wiki_db = mw.loadData('Module:NUMBEROF/data') end
local db_map, db_data = wiki_db.map, wiki_db.data
if not db_map or not db_data then return nil end
local max_lang, max_labelObj, max_article = nil, nil, -1
for lang, labelObj in pairs(labels) do
local wikiCountObj = db_data[lang..(project_table[lang_name] or '.wikipedia')]
if wikiCountObj then
local wikiCount = tonumber(wikiCountObj[db_map.articles])
if type(wikiCount) == type(0) then
if wikiCount > max_article then
max_article = wikiCount
max_lang = lang
max_labelObj = labelObj
end
end
end
end
return (max_labelObj or {}).value
end
return label
end
function p._getWikidataLink(wikidata_id, find_lang, display_text, articlename, templateflag)
local display_code = display_text or ''
local display_linkcode = (mw.text.trim(display_code) ~= '')and ('|'..display_code) or display_code
local namescape_end = mw.ustring.find(wikidata_id ,":")
local g_namespace = namescape_end and mw.ustring.sub(wikidata_id, 1, namescape_end-1) or ''
local namespace_head = mw.ustring.sub(wikidata_id,1,1):lower()
local entity_namespace = wikidata_entity_namespaces[namespace_head] or ''
local wikidata_pagename = entity_namespace .. ((mw.text.trim(entity_namespace)~='')and ':' or '') .. wikidata_id
if mw.text.trim(g_namespace)~='' then
wikidata_pagename = wikidata_id
entity_namespace = g_namespace
namespace_head = g_namespace
end
if wikidata_namespaces_support[mw.ustring.lower(namespace_head)] then
if mw.wikibase.entityExists( wikidata_id ) then
local entity = mw.wikibase.getEntity( wikidata_id )
if mw.text.trim(entity:getSitelink() or '') ~= '' then
if templateflag == "link-wd" then
--all pass to Module:ilh
else
return '[[' .. entity:getSitelink() .. display_linkcode .. ']]'
end
end
local interwiki = 'd'
local interwikiPage = wikidata_pagename
local force_wikidata = false
for ____,value in ipairs(find_lang) do
if mw.text.trim(entity:getSitelink( value ) or '') ~= '' then
interwiki, interwikiPage = value, entity:getSitelink( value )
break
elseif mw.text.trim(entity:getSitelink( value .. 'wiki' ) or '') ~= '' then
interwiki, interwikiPage = value, entity:getSitelink( value .. 'wiki' )
break
elseif value == 'wikidata' then
interwiki = 'd'
force_wikidata = true
end
end
if interwiki == 'd' then
local l_interwikiPage = interwikiPage
interwiki, interwikiPage = getEntitySitelink(entity)
interwiki, interwikiPage = (interwiki or 'd'), (interwikiPage or l_interwikiPage)
if force_wikidata then interwiki = 'd' end
if interwiki == 'd' then interwikiPage = wikidata_pagename end
end
if interwiki ~= 'd' then
local lang = mw.language.fetchLanguageName( interwiki, mw.getContentLanguage():getCode() )
if (lang or '') ~= '' then
return _wikidata_ilh({
[1] = articlename or getEntityLabel(entity) or interwikiPage,
[2] = interwikiPage,
[3] = (mw.text.trim(display_code) ~= '')and display_code or nil,
['lang'] = lang,
['lang-code'] = interwiki
})
end
end
local eLabel = entity:getLabel()
if mw.text.trim(eLabel or '') == '' then eLabel = interwikiPage end
local result = _wikidata_ilh({
[1] = articlename or eLabel,
[2] = interwikiPage,
[3] = (mw.text.trim(display_code) ~= '')and display_code or nil,
['lang'] = '維基數據',
['lang-code'] = interwiki
})
return mw.ustring.gsub(result,'(>維基數據)(<)','%1所列%2')
else return wikidata_id end
end
local page_name = (type(find_lang) == type("string")) and find_lang or wikidata_id
local result = _wikidata_ilh({
[1] = articlename or page_name,
[2] = wikidata_pagename,
[3] = (mw.text.trim(display_code) ~= '')and display_code or nil,
['lang'] = '維基數據',
['lang-code'] = 'd'
})
return mw.ustring.gsub(result,'(>維基數據)(<)','%1所列%2')
end
function p.linkwikidata(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {parentFirst=true})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_article = args[1] or args['1'] or args.id or ''
local find_lang_str = args[2] or args['2'] or args.lang or args.langs or 'en,de,fr,ja'
local find_lang = mw.text.split(find_lang_str, ',') or {}
if #find_lang <= 1 then find_lang[1] = find_lang_str end
local result = mw.ustring.gsub(input_article,'([Qq][%d]+)',function(wikidata_id)
return p._getWikidataLink(wikidata_id, find_lang)
end)
return result
end
function p.linkwikidata_single(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {parentFirst=true})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_article = args[1] or args['1'] or args.id or ''
local find_lang_str = args[3] or args['3'] or args.lang or args.langs or 'en,de,fr,ja'
local input_display = args[2] or args['2']
local articlename = args.page or args.pagename or args.page_name or args['page name'] or
args.articlename or args.article_name or args['article name'] or ''
if mw.text.trim(articlename) == '' then articlename = nil end
local find_lang = mw.text.split(find_lang_str, ',') or {}
if #find_lang <= 1 then find_lang[1] = find_lang_str end
local namescape_end = mw.ustring.find(input_article ,":")
local g_namespace = namescape_end and mw.ustring.sub(input_article, 1, namescape_end-1) or ''
local namespace_head = mw.ustring.sub(input_article,1,1):lower()
if mw.text.trim(g_namespace)~='' then
namespace_head = g_namespace
end
local title_check = ((mw.text.trim(args.title or '')~='')and args.title or find_lang_str)
local result=p._getWikidataLink(input_article,
(((not wikidata_namespaces_support[mw.ustring.lower(namespace_head)]) or mw.text.trim(g_namespace)~='')
and not(({mw.ustring.find(title_check,',')})[1]))
and title_check or find_lang, input_display, articlename, "link-wd")
return result
end
return p;