Die Dokumentation für dieses Modul kann unter Modul:Title/Doku erstellt werden

--[=[  Title 2022-11-04
	gather all title information from all sources available
	
	Autor: Vollbracht
	
* p.service	object
	fields
		CONTENT_LANG	as of mw.language.getContentLanguage():getCode()
		dataLink	Wikidata object identifier (Q123..., optional)
		wd			Wikidata link ([[d:Q123...|wd]], optional)
		title		P1476, object (most significant statement)
						text		monolingual title
						lang		language shortening (en, de, etc., optional)
						language	language of title (English, German, etc., or
									Englisch, Deutsch, etc., depending on
									content language)
		originalTitle	P1476, object,
					(statement marked P3831 = Q1294573, optional, see title)
		lang		P407, language shortening
					(en, de, etc., optional, fall back to title.lang)
		language	P407, language of service object
					(see title.language, fall back to title.language)
		oriLang		P364, language shortening
					(en, de, etc., optional, fall back to originalTitle.lang)
		originalLanguage	P364, original language of service object
					(see title.language, fall back to originalTitle.language)
	constructor
		new(source, language)
	methods
		__tostring()	returns string: ''<title>'' (<title language>)
		infoBrace		returns additional informations in braces
		titleLink()		returns link: [[''<title>'']] if available
---- template functions ----
* standard(object)		returns string: ''<title>'' (<title language>)
* full(object)			returns all relevant data (no 'lang'-fields)
* getTitle(object)		returns string: ''<title>''
* getLanguage(object)
* getOriginalTitle(object)
* getOriginalLanguage(object)
]=]

--Module globals

local p = {service = {
	PREF_LANG = 'de',
	--CONTENT_LANG = mw.language.getContentLanguage():getCode(),
	FIELDS = {
		'dataLink', 'wd', 'title', 'originalTitle',
		'lang', 'language', 'oriLang', 'originalLanguage'
	}
}}

local _, SDA = pcall(require, "Modul:SimpleDataAccess")

------------------------- local functions and objects -------------------------

-- just for documentation:
local transCode = {
	tcP = {
		P424='languageCode', P3831='role',
		P1476='title', P407='language', P364='originalLanguage'
	}
}

-- a title may have a role (P3831) "is original title" (Q1294573)
local function isOri(roles)
	for _, v in ipairs(roles) do
		if v.datavalue.value.id == 'Q1294573' then return true end
	end
	return false
end

------------------------ service functions and objects ------------------------

--[[
	getLanguage(wdID, property)
	shortening and German name of a language given by Wikidata ID and property
	parameters:
		wdID		Wikidata item ID ('Q123..') of an item with a language
		property	Wikidata item property ID ('P407' or 'P364')
	returns:	shortening, name ('en', 'Englisch' or 'de', 'Deutsch', e.g.)
]]
p.service.getLanguage = function(wdID, property)
	local src = mw.wikibase.getBestStatements(wdID, property)
	if not src then return nil, nil end
	src = src[1]
	if not src then return nil, nil end
	src = src.mainsnak
	if not src then return nil, nil end
	src = src.datavalue
	if not src then return nil, mw.wikibase.getLabel(Q19798647) end
	local id = src.value.id
	if not id then return nil, nil end
	src = mw.wikibase.getBestStatements(id, 'P424')
	if not src then return nil, nil end
	local l = src[1].mainsnak.datavalue.value
	return l, mw.language.fetchLanguageName(l, 'de')
end

--[[
	getTitle(source, language)
	simple struct containing a title and a title language
	parameters:
		source		title (string) or
					struct containing
						a title and a language shortening or
						a struct containing a value containing those or
						a struct containing a datavalue containing such a value
		language	language shortening or language name
						as value in combination with title string
						as preference to mark result based on source struct
	returns:	title struct, mark (as follows:)
					{text='<title>', lang='<shortening>', language='<name>'},
					<title language shortening == language parameter>
]]
p.service.getTitle = function(source, language)
	if not source then return nil end
	if not language then language = p.service.PREF_LANG end
	byString = function(s, l)
		local l2 = mw.language.fetchLanguageName(l, 'de')
		local result = {text = s}
		if l2 and l2 ~= '' then
			result.lang = l
			result.language = l2
		else result.language = l end
		return result
	end
		
	if type(source) == 'string' then return byString(source, language), true end
	if type(source) ~= 'table' then return nil, false end
	local q = nil
	if source.mainsnak then
		q = source.qualifiers
		source = source.mainsnak
	end
	if source.datavalue then source = source.datavalue end
	if source.value then source = source.value end
	if type(source) == 'string' then return byString(source, language), true end
	if type(source) ~= 'table' then return nil, false end
	if not source.text then return nil, false end
	if source.language then
		local result = byString(source.text, source.language)
		if result.lang == language then return result, true end
		if result.language == language then return result, true end
		if q then
			local p = q.P3831
			if p and isOri(p) then result.isOri = true end
		end
		return result, false
	end
	return byString(source.text, language), true
end
------------------------------ procedural variant ------------------------------
--[[
	getStruct
	variant to new object
	parameters:
		source		text or table for a new title / language struct
		language	value of a new language struct or
					preferred search criterium within source table
					(optional)
	returns:	structure with title text, title language, item language
				original title text original title language and original item
				language
]]
p.service.getStruct = function(source, language)
	if not source then source = mw.wikibase.getEntityIdForCurrentPage() end
	if not source then return nil end
	local result = {}
	if type(source) == 'string' then
		result.dataLink = source:match('^Q%d+')
		if not result.dataLink then
			result = {title = p.service.getTitle(source, language)}
			result.language = language
			return result
		end
		result.wd = '[[d:' .. result.dataLink .. '|wd]]'
		source = mw.wikibase.getAllStatements(result.dataLink, 'P1476')
		result.lang, result.language
								= p.service.getLanguage(result.dataLink, 'P407')
		result.oriLang, result.originalLanguage
								= p.service.getLanguage(result.dataLink, 'P364')
	end
	if type(source) ~= 'table' then return nil end
	local hasPreferred = false
	for _, v in ipairs(source) do
		local t, isPref = p.service.getTitle(v, language)
		if not t then
			if not result.title then return nil end
			return result
		end
		if isPref or not result.title then result.title = t end
		if not hasPreferred then hasPreferred = isPref end
		if t.isOri then result.originalTitle = t end
		if hasPreferred and result.originalTitle then return result end
	end
	if not result.title then return nil end
	return result
end

------------------------------ object variant ------------------------------

function p.service:new(source, language)
	local result = p.service.getStruct(source, language)
	if not result then return nil end
	self.__index = self
	return setmetatable(result, self)
end

p.service.__tostring = function(this)
	return this.title:__tostring()
end

p.service.infoBrace = function(this, beforeLang, afterLang, test)
	local result = '('
	local comma = false
	add = function(value)
		if value and value ~= '' then
			if comma then result = result .. ', ' end
			result = result .. value
			comma = true
		end
	end
	add(beforeLang)
	local scheme = 0
	if this.language and this.lang and this.lang ~= this.PREF_LANG then
		scheme = 1
	end
	if this.originalTitle and this.originalTitle.text ~= this.title.text then
		scheme = scheme + 2
	end
	if this.originalLanguage and this.oriLang and this.oriLang ~= this.lang then
		scheme = scheme + 4
	end
	if scheme == 1 then add(this.language)
	elseif scheme == 2 then
		add("Original: ''" .. this.originalTitle.text .. "''")
	elseif scheme == 3 then
		add (this.language)
		add("Original: ''" .. this.originalTitle.text .. "''")
	elseif scheme == 4 then
		add('Original: ' .. this.originalLanguage)
	elseif scheme == 5 then
		if this.lang == this.oriLang then add(this.language)
		else add(this.language .. ' / Original: ' .. this.originalLanguage) end
	elseif scheme == 6 then
		add("Original: ''" .. this.originalTitle.text .. "''")
		add(this.originalLanguage)
	elseif scheme == 7 then
		add(this.language)
		add("Original: ''" .. this.originalTitle.text .. "''")
		add(this.originalLanguage)
	end
	add(afterLang)
	add(this.wd)
	if not comma then return '' end
	return result .. ')'
end

p.service.titleLink = function(this)
	if not this.dataLink then return "''" .. this.title.text .. "''" end
	local link = mw.wikibase.getSitelink(this.dataLink)
	if not link then return "''" .. this.title.text .. "''" end
	if link == this.title.text then return "''[[" .. link .. "]]''" end
	return "''[[" .. link .. "|" .. this.title.text .. "]]''"
end

------------------------------ template functions ------------------------------

p.standard = function(frame)
	if frame.args.title then
		return p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		return p.service:new(frame.args[1])
	end
end

p.full = function(frame)
	local result = ''
	if frame.args.title then
		result = p.service.getStruct(	frame.args.title, frame.args.language,
										frame.args.test)
	else
		result = p.service.getStruct(frame.args[1])
	end
	if result and result.dataLink then
		return result.title.text .. ' ' .. p.service.infoBrace(result)
	else return result end
end

p.fullO = function(frame)
	local result = ''
	if frame.args.title then
		result = p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		result = p.service:new(frame.args[1])
	end
	if result and result.dataLink then
		return result.title.text .. ' ' .. result:infoBrace()
	else return result end
end

p.getTitle = function(frame)
	local result = nil
	if frame.args.title then
		result = p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		result = p.service:new(frame.args[1])
	end
	if result and result.title then return result.title.text end
end

p.getLanguage = function(frame)
	local result = nil
	if frame.args.title then
		result = p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		result = p.service:new(frame.args[1])
	end
	if result and result.language then return result.language end
end

p.getOriginalTitle = function(frame)
	local result = nil
	if frame.args.title then
		result = p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		result = p.service:new(frame.args[1])
	end
	if result and result.originalTitle then return result.originalTitle.text end
end

p.getOriginalLanguage = function(frame)
	local result = nil
	if frame.args.title then
		result = p.service:new(	frame.args.title, frame.args.language,
								frame.args.test)
	else
		result = p.service:new(frame.args[1])
	end
	if result and result.originalLanguage then return result.originalLanguage end
end

return p