Module:Interwiki

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Back end to Template:Interwiki from Wikidata. Please do not use directly but through the template.

Purpose. This module provides a way to supply interwiki links to pages that cannot be fully served by Wikidata for a variety of reasons, such as:

  1. Two pages are substantially identical, but only one can be directly linked to Wikidata.
    Example: most Hebrew-script pages on this wiki, which are substantially identical to corresponding Latin-script pages.
  2. Pages that have exact analogues in only a few wikis, but near analogues in many wikis.
    This commonly happens in Template (Xablón), Project/Wikipedia (Vikipedya), and Help (Ayudo) name spaces.
  3. Page does not have its own entry in Wikidata.
    All pages are allowed to have entries in Wikidata, but in some of the cases above, it may or not seem entirely necessary to create them.

Instructions

In case of reason 1 above

  1. Open tabs in your browser for the following pages:
    • The page having Wikidata links (example: Astronomiya)
    • The substantially identical page without its own Wikidata links (example: אסטרונומייה)
    • The Wikidata item of the first page (example: d:Q333)
    • The Wikidata item of the second page (example: d:Q20819872)
  2. In the Wikidata item of the second page, add the following to "Statements": "said to be the same as" with the value of the Wikidata item of the first page. (Note: "said to be the same as" is property d:Property:P460.)
  3. Edit the second page on this Wiki with the following code, at the bottom, just before categories. (If the page is a template, be sure this code is included within the <noinclude> </noinclude> tags.)
    • {{#invoke:Interwiki|interwiki}}
  4. Save all changes.

The second page should now include all the interwiki links of the first page.

In case of reason 2 above

  1. Open tabs in your browser for the following pages:
  2. Edit the first page on this Wiki with the following code, at the bottom, just before categories. (If the page is a template, be sure this code is included within the <noinclude> </noinclude> tags.)
    • {{#invoke:Interwiki|interwiki|qid=Qnnnnnnn}}, where Qnnnnnnn is the Wikidata item number of the near-analogue page.
  3. Save all changes.

The first page should now include all the interwiki links of the second page, except where an exact analogue already exists in the first page's own Wikidata item.

In case of reason 3 above

  1. Consider creating a Wikidata item for the page, and proceed as in reason 1 above.
  2. Otherwise, proceed as in reason 2 above.

Code

--[[
  __  __           _       _        ___       _                     _ _    _  
 |  \/  | ___   __| |_   _| | ___ _|_ _|_ __ | |_ ___ _ ____      _(_) | _(_) 
 | |\/| |/ _ \ / _` | | | | |/ _ (_)| || '_ \| __/ _ \ '__\ \ /\ / / | |/ / | 
 | |  | | (_) | (_| | |_| | |  __/_ | || | | | ||  __/ |   \ V  V /| |   <| | 
 |_|  |_|\___/ \__,_|\__,_|_|\___(_)___|_| |_|\__\___|_|    \_/\_/ |_|_|\_\_| 
                                                                              
History:
 * Originally written by user:Innocent_bystander ( https://sv.wikipedia.org/wiki/Modul:Interwiki )
 * Forked and modified by user:Jarekt
]]

--------------------------------------------------------------------

-- Properties to use as redirects 
local redirectProperties = { 
	'P301', -- "category's main topic"
	'P460', -- "said to be the same as"
	'P1420', -- "taxon synonym"
	'P1753' -- "list related to category"
}

-- =======================================
-- === Local Functions ===================
-- =======================================

------------------------------------------------------------------------------
-- Based on frame structure create "args" table with all the input parameters.
-- All inputs are non case-sensitive. Input values are trimmed and empty string a 
-- re converted to nils. 
local function getArgs(frame)
	local function normalize_input_args(input_args, output_args)
		for name, value in pairs( input_args ) do 
			if type(name)=='string' and value ~= '' then 
				output_args[string.lower(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

-- convert from a list to a set
local function list2set(list, set) 
	set = set or {}
	for _, v in ipairs(list or {}) do set[v]=true end
	return set
end

--------------------------------------------------------------------
-- Collect one or more item ID from a property
local function getProperty(entity, prop) 
	propVal = {}
	if entity and entity.claims then
		for _, statement in pairs(entity:getBestStatements( prop )) do
			if statement.mainsnak.snaktype == 'value' then
				table.insert(propVal, statement.mainsnak.datavalue.value.id)
			end
		end
	end
	return propVal
end

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

--------------------------------------------------------------------
-- Purpose: create old wikitext stype interwiki links (links shown on the left 
-- side of the page) to add or replace interwiki links based on Wikidata 
-- sitelinks
-- Use as follows:
--  * {{#invoke:Interwiki|interwiki}} will examine wikidata item and see if 
--       any "redirectProperties" are present if any are than the first item 
--       ID will be used. We will than proceed to add to interwiki links in
--       addition to the ones based on Wikidata sitelinks 
--  * {{#invoke:Interwiki|interwiki|qid=Q5}} specify an item to draw interwikis from
--  * {{#invoke:Interwiki|interwiki|test=1}} will display interwikilinks as bullet list 
--        to allow debuging
function p._interwiki(args)
	-- process inputs
	local qid  = args.qid         -- get uses parameter "qid"  if provided
	local test = args.test or '0' -- get uses parameter "test" if provided
	test = (test=='yes' or test=='y' or test=='true'  or test=='1')    -- convert to boolean
	local fStr = (test and '*[[w:%s:%s]]') or '[[%s:%s]]'              -- link format: in normal or in test mode
	
	-- Excludes some wikiprojects that are not Wikipedia, even if their code ends with 'wiki'
	-- The last one is the name of the current project
	local excludedProjects = {'wikidatawiki', 'commonswiki', 'specieswiki', 'metawiki', 'simplewiki',
			'mediawikiwiki', 'sourceswiki', 'wikimaniawiki', 'incubatorwiki', mw.wikibase.getGlobalSiteId()}	
	excludedProjects = list2set(excludedProjects)  -- convert from a list to a set

	-- current page is connected through a sitelink to an wikidata entity
	local entity = mw.wikibase.getEntity()
	if entity then 
		-- find wikidata item from which to copy interwiki links
		if (not qid or qid == '') then
			for _, prop in ipairs(redirectProperties) do
				qid = getProperty(entity, prop)[1] -- follow wikidata's item redirect-like properties
				if qid then break end
			end
		end
		-- check if we are at category item
		local instanceOf = list2set(getProperty(entity, 'P31')) -- place item's instances-of in a set
		local isCat      = instanceOf['Q4167836']               -- this entity is a instance of Wikimedia category
		-- build a list of sites we will not link to,  so we do not overwrite existing interwiki links
		-- we will overwrite category sitelinks with article sitelinks if both are present
		if qid and (not isCat) then -- in case "entity" already has some sitelinks than exclude them
			excludedProjects = list2set(entity.sitelinks, excludedProjects)
		end
	end
	
	-- build interwiki table based on wikidata page with item ID 'qid'
	local intWikiTable = {}
	if qid then
		entity = mw.wikibase.getEntity(qid)
		if entity and entity.sitelinks then
			for _, sitelink in pairs(entity.sitelinks) do
				local site = sitelink.site -- site names usually have language+"wiki" like "enwiki", etc
				local lang = mw.ustring.sub( site, 1, -5) -- split site into language and project parts
				local proj = mw.ustring.sub( site, -4)
				if not excludedProjects[site] and proj=='wiki' then -- excludes sites on the list as well as Wikisource, Wikiquote, Wikivoyage etc
					lang = mw.ustring.gsub(lang, '_','-') -- if extracted language has any underscores replace it with a minus
					table.insert(intWikiTable, mw.ustring.format(fStr, lang, sitelink.title) ) -- put together a interwiki-link to other projects
				end
			end
		end
	end
	return table.concat(intWikiTable, '\n') -- change table of strings to a single string: one row per line
end

function p.interwiki(frame)
	return p._interwiki(getArgs(frame))
end

return p