Modul:VCard

Aus Wikivoyage
Zur Navigation springen Zur Suche springen
Template-info.png Dokumentation für das Modul VCard[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]

Anmerkungen

Versionsbezeichnung auf WikiData: 2019-09-08

Anwendung

Das Modul wird direkt von der Vorlage {{vCard}} aufgerufen. Parameterbeschreibung siehe dort.

Experimentalbeispiele

* {{vCard | name= Ein Hotel | type = hostel | url= http://hotel.de | lat = 52.5144 | long = 13.389722 | show = all, subtype | address = Hauptstraße 1 | directions = Abzweig von der Nebenstraße | description = Das in der Innenstadt gelegene Hotel besitzt großzügige Räume, bietet aber nur {{Abk|ÜF}}. | phone = +49 (0)30 2345 1234 | fax = +49 (0)30 2345 9876, +49 0176 345 1234 | before = {{flagicon|Deutschland}} | image = Berlin Friedrichstraße Galeries Lafayette.jpg | email = info@hotel.de | comment = j | lastedit = 2016-11-17 | hours = 7/24. | checkin = ab 14 Uhr | checkout = bis 12 Uhr | payment = Visa, Master, AmEx, Maestro | subtype = wlan, bar, pool | skype = nutzer.name; nutzer2.name }}

* {{vCard | wikidata = Q201219 | auto = j | name = [[Kairo/Ägyptisches Museum|Ägyptisches Museum Kairo]] | comment = auch Nationalmuseum | alt = Egyptian Museum | name-latin = al-Matḥaf al-Miṣrī | address = Mīdān et-Taḥrīr | address-local = ميدان التحرير | directions = im Stadtzentrum | directions-local = بوسط البلد }}
* {{vCard | wikidata = Q201219 | name = [[Kairo/Ägyptisches Museum|Ägyptisches Museum Kairo]] | facebook = j | twitter = j }} <​!-- Marker-Modus -->
* {{vCard | wikidata = Q1142142 | auto = j | name = Nordiska museet }} Noch weiterer Text.
* {{vCard | wikidata = Q1142142 | auto = j | price = n }}
* {{vCard | wikidata = Q257342 | auto = j }}
* {{vCard | wikidata = Q28934 | auto = j | description = Test Durchhangeln. }}
* {{vCard | wikidata = Q4872 | auto = j }}
* {{vCard | wikidata = Q10697 | auto = j }}
* {{vCard | wikidata = Q12508 | auto = j | description = Test Durchhangeln. }}
* {{vCard | wikidata = Q46033 | description = Test Flughafen. }}
* {{vCard | wikidata = Q13218762 | auto = j | description = Anzeige englische Wikipedia. }}
* {{vCard | wikidata = Q47429618 | auto = j | description = Ausgabe Anschriften. | show = subtype | payment = Visa, Master }}
* {{vCard | wikidata = Q47429618 | address = | address-local = | directions = | phone = | description = Test eingeschränkte WD-Ausgabe. }}
* {{vCard | wikidata = Q637739 | auto = j | show = subtype | description = Rollstuhl aus WD. }}
  • DeutschlandFlagge Deutschland 1 Ein Hotel, Hauptstraße 1 (Abzweig von der Nebenstraße). Tel.: +49 (0)30 2345 1234, Fax: +49 (0)30 2345 9876, +49 (0)176 345 1234, E-Mail: , Skype: nutzer.name, nutzer2.name. Das in der Innenstadt gelegene Hotel besitzt großzügige Räume, bietet aber nur ÜF. Geöffnet: 7/24. Check-in: ab 14 Uhr. Check-out: bis 12 Uhr. Akzeptierte Zahlungsarten: Visa, Master, AmEx, Maestro. Merkmale: WLAN [bar] [pool]. (52° 30′ 52″ N 13° 23′ 23″ O)

Parameter show

  • Mögliche Werte: none, poi, coord, all, subtype, nosubtype, indent, inline. Eine kommaseparierte Liste mehrerer Werte ist möglich.
  • Man kann die Standardwerte überschreiben.
  • Darstellung von Marker und Koordinaten.
    • poi und coord sind stärker als all. none ist stärker als poi, coord und all.
  • Die Ausgabe der Subtypen ist vorbereitet, wird aber zurzeit nicht standardmäßig durchgeführt (nosubtype).
    • nosubtype ist stärker als subtype.
  • Block-/Inline-Darstellung
    • Zukünftig wird die vCard standardmäßig im Block-Modus (css: display = block) angezeigt werden. Gegenwärtig Inline-Modus aufgrund zahlreicher Verwendung in diesem Modus. Dies schließt Beschränkungen bei den Darstellungsmöglichkeiten der Beschreibung description ein. inline schaltet vom Block- in den Inline-Modus.
    • Zukünftig bewirkt indent im Blockmodus einen eingerückten Absatz mit hängender erster Zeile. Das POI-Symbol wirkt dann wie ein Aufzählungszeichen.

Benötigte weitere Module

Dieses Modul benötigt folgende weitere Module: CountryData • Failsafe • FastWikidata • Languages • LinkMail • LinkPhone • LinkSkype • MarkerBase • MarkerBase/i18n • VCard/Cards • VCard/Currencies • VCard/Defaults • VCard/i18n • VCard/Params • VCard/Subtypes • Wikidata2/POITypes • Yesno
Hinweise
-- documentation
local vCard = {
	suite  = 'vCard',
	serial = '2019-09-08',
	item   = 58187507
}
-- module import
local mb = require( 'Module:MarkerBase' )
local mi = require( 'Module:MarkerBase/i18n' )
local vp = require( 'Module:VCard/Params' ) -- parameter lists
local vi = require( 'Module:VCard/i18n' ) -- parameter translations
local vs = require( 'Module:VCard/Subtypes' ) -- features of a location
local vr = mw.loadData( 'Module:VCard/Cards') -- payment types
local vd = mw.loadData( 'Module:VCard/Defaults' ) -- country-specific show defaults
local vm = mw.loadData( 'Module:VCard/Currencies' ) -- additional currency symbols

local cm = require( 'Module:CountryData' )
local fs = require( 'Module:Failsafe' )
local fw = require( 'Module:FastWikidata' )
local lg = require( 'Module:Languages' )
local lp = require( 'Module:LinkPhone' )
local lm = require( 'Module:LinkMail' )
local ls = require( 'Module:LinkSkype' )
local pt = mw.loadData( 'Module:Wikidata2/POITypes' ) -- WD types to vCard/Poi types
local yn = require( 'Module:Yesno' )

-- module variable
local vc = {
	wdContent       = {},
	catArray        = {},
	unknownLanguage = false
}

-- Splitting comma separated lists to an array
-- convert = true: conversion to lowercase characters, spaces to low lines
-- toValue = true: list items handled as array values
-- toValue = false: list items handled as array keys
function vc.split( s, convert, toValue )
	local arr = {}, i, t
	if not s or s == '' then
		return arr
	end
	local arr2 = mw.text.split( s, ',', true )
	for i = 1, #arr2, 1 do
		t = mw.text.trim( arr2[ i ] )
		if t ~= '' then
			if convert then
				t = t:lower():gsub( ' ', '_' )
			end
			if toValue then
				table.insert( arr, t )
			else
				arr[ t ] = ''
			end
		end
	end
	return arr
end

-- Splitting comma separated lists to an array of key items
-- checking items with allowed key values of validValues array
function vc.splitAndCheck( s, validValues )
	local arr = {}, k, v
	local err = ''
	if not s or s == '' or not validValues then
		return arr, err
	end
	arr = vc.split( s, true )
	for k, v in pairs( arr ) do -- error handling
		if not validValues[ k ] then
			err = vc.addComma( err ) .. k
			v = nil
		end
	end
	return arr, err
end

-- p : property id
-- tp: data value type
-- mx: maximum count
-- f : format
function vc.getWDvalues( p, tp, mx, f, l, entity, wikiLang, clang )
	-- clang = country.lang
	-- function returns an array in any case
	local r = '', a, i, t, u, w
	local ar = {}

	-- getting values
	if l == 'wiki' then
		ar, vc.catArray = fw.getValuesByLang( entity, p, mx, wikiLang, vc.catArray )
	elseif l == 'local' then
		ar, vc.catArray = fw.getValuesByLang( entity, p, mx, clang, vc.catArray )
	elseif l == true and mx == 1 then
		t = lg.getProperty( wikiLang, 'q' )
		u = lg.getProperty( clang, 'q' )
		if u == '' then
			vc.unknownLanguage = true
		else
			a, vc.catArray = fw.getValuesWithQualifierIds( entity, p, 'P407', u, vc.catArray )
			if next( a ) then
				i = a[ t ] -- item in wikiLang
				if not i then
					i = a[ u ] -- item in country lang
					if not i then
						i = a[ next( a, nil ) ] -- first item
					end
				end
				ar = { i }
			end
		end
	else
		ar, vc.catArray = fw.getValues( entity, p, mx, vc.catArray )
	end
	if #ar == 0 then
		return ar
	end

	if p == 'P31' then -- instance of
		p, vc.catArray = fw.typeSearch( ar, pt, mi.searchLimit, vc.catArray )
		return { p }
	else
		for i = 1, #ar, 1 do
			if tp == '' or tp == 'il' then -- value, monolingual text
				if ar[ i ] ~= '' and f ~= '' and f:find( '$1', 1, true ) then
					ar[ i ] = mw.ustring.gsub( f, '($1)', ar[ i ])
				end

			elseif tp == 'id' then -- identifier
				ar[ i ] = ar[ i ].id
				if ar[ i ] ~= '' and f ~= '' and f:find( '$1', 1, true ) then
					ar[ i ] = mw.ustring.gsub( f, '($1)', ar[ i ])
				end

			elseif tp == 'au' then -- amount with unit
				a = ar[ i ].amount
				a = a:gsub( '+', '' )
				if mi.texts.decimalPoint ~= '.' then
					a = a:gsub( '%.', mi.texts.decimalPoint )
				end
				u = ar[ i ].unit
				u = u:gsub( 'http://www.wikidata.org/entity/', '' )
				if u:match( '^Q[%d]+$' ) then
					t, vc.catArray = fw.getValue( u, 'P558', vc.catArray ) -- unit
					if t == '' then
						t, vc.catArray = fw.getValue( u, 'P498', vc.catArray ) -- currency code
					end
					if t ~= '' then
						u = t
					end
				end
				if a ~= '' and u ~= '' then
					if f ~= '' and f:find( '$1', 1, true ) and f:find( '$2', 1, true ) then
						a = mw.ustring.gsub( f, '($1)', a)
						a = mw.ustring.gsub( a, '($2)', u)
					else
						a = a .. ' ' .. u
					end
				else
					a = a .. ' ' .. u
				end
				if a == '' or a == ' ' then
					ar[ i ] = nil
				else
					ar[ i ] = a
				end
			end
		end
	end
	return ar
end

function vc.getFromWD( parWDitem, entity, wikiLang, clang )
	local arr = {}, subArr, result, i, p

	local function singleProperty( pr, f, c, v, l )
		if #arr == 0 then
			arr = vc.getWDvalues( pr, v or '', c or 1, f or '', l, entity, wikiLang, clang )
		else
			subArr = vc.getWDvalues( pr, v or '', c or 1, f or '', l, entity, wikiLang, clang )
			for i = 1, #subArr, 1 do -- move to arr
				table.insert( arr, subArr[ i ] )
			end
		end
		return
	end

	p = parWDitem
	if not p then
		return ''
	end
	p.c = p.c or 1 -- count

	i = type( p.p )
	if i == 'string' then
		singleProperty( p.p, p.f, p.c, p.v, p.l )
	elseif i == 'table' then
		for key, value in pairs( p.p ) do
			if type( value ) == 'table' then
				singleProperty( value.p, value.f, value.c, value.v, value.l )
			end
		end
	end

	result = ''
	if #arr > p.c then
		for i = #arr, p.c + 1, -1 do -- delete supernumerary values
			table.remove( arr, i )
		end
	end
	if not p.m then
		p.m = ', '
	end
	if p.m == 'no' then
		result = arr
	else
		result = table.concat( arr, p.m )
	end
	return result
end

function vc.getAddressesFromWD( vcEntity, country, wikiLang )
	local addresses = {}, i, key, value, t, u, w, weight

	if vp.ParMap.auto then
		if vp.ParMap.address == '' then
			vp.ParMap.address = true
		end
		if vp.ParMap.addressLocal == '' then
			vp.ParMap.addressLocal = true
		end
	end

	-- getting addresses from Wikidata but only if necessary
	if vp.ParMap.wikidata ~= '' and
		( vp.ParMap.address == true or vp.ParMap.addressLocal == true ) then
		-- new address property P6375
		addresses, vc.catArray = fw.getValuesWithLanguages( vcEntity, 'P6375', vc.catArray )
		if next( addresses ) then -- sometimes addresses contain <br> tag(s)
			for key, value in pairs( addresses ) do
				addresses[ key ] = mw.ustring.gsub( value, '<br%s*/*>', ' ' )
			end
		else
			addresses = nil
		end
	end

	if addresses and vp.ParMap.address == true then
		vp.ParMap.address = addresses[ wikiLang ]
		-- select address if the same writing system is used
		if not vp.ParMap.address then
			weight = -1
			u = lg.getProperty( wikiLang, 'w' ) -- writing entity id
			for key, value in pairs( addresses ) do
				-- same writing entity id as wikilang
				w = lg.getProperty( key, 'w' )
				if w == '' then
					vc.unknownLanguage = true
				else
					if key and w == u then -- same writing entity id
						w = lg.getProperty( key, 'c' ) -- getting language weight
						if w > weight then -- compare language weight
							vp.ParMap.address = value
							vp.ParMap.addressLang = key
							weight = w
						end
					end
				end
			end
		end
		if not vp.ParMap.address then
			for i = 1, #mi.langs.address, 1 do
				t = mi.langs.address[ i ]
				if addresses[ t ] then
					vp.ParMap.address = addresses[ t ]
					vp.ParMap.addressLang = t
					break
				end
			end
		end
		if not vp.ParMap.address then
			vp.ParMap.address = ''
			vp.ParMap.addressLang = ''
		end
		if vp.ParMap.address ~= '' then
			vc.wdContent.address = true
		end
	elseif type( vp.ParMap.address ) == 'boolean' then
		vp.ParMap.address = ''
	end

	t = true
	for i = 1, #mi.langs.address, 1 do
		if country.lang == mi.langs.address[ i ] then
			t = false
		end
	end
	if addresses and vp.ParMap.addressLocal == true
		and country.lang ~= wikiLang and t then
		if country.lang ~= '' then
			vp.ParMap.addressLocal = addresses[ country.lang ] or ''
		else
			-- unknown language, maybe missing in Module:Languages
			vp.ParMap.addressLocal = addresses.unknown or ''
		end
		if vp.ParMap.addressLocal ~= '' then
			vc.wdContent.addressLocal = true
		end
	elseif type( vp.ParMap.addressLocal ) == 'boolean' then
		vp.ParMap.addressLocal = ''
	end

	-- analysing addressLocal vs address
	if vp.ParMap.address == vp.ParMap.addressLocal or
		( vp.ParMap.addressLang and vp.ParMap.addressLang == country.lang ) then
		vp.ParMap.addressLocal = ''
	end
	if vp.ParMap.addressLocal ~= '' and vp.ParMap.address == '' then
		vp.ParMap.address =
			vc.languageSpan( vp.ParMap.addressLocal, mi.texts.hintAddress, wikiLang, country )
		vp.ParMap.addressLocal = ''
		vc.wdContent.address = vc.wdContent.addressLocal
	end
	return
end

function vc.addComma( t )
	if t == '' then
		return t
	else
		return t .. ', '
	end
end

function vc.addWdClass( key )
	if vc.wdContent[ key ] then
		return ' wikidata-content'
	else
		return ''
	end
end

function vc.formatText( key, class )
	if vp.ParMap[ key ] == '' then
		return ''
	end
	
	local r = ' <span class="' .. class .. vc.addWdClass( key ) .. '">'
		.. mw.ustring.format( mi.texts[ key ], vp.ParMap[ key ] )
	if not vp.ParMap[ key ]:find( '%.$' ) then
		r = r .. '.'
	end
	return r .. '</span>'
end

function vc.formatPhone( key, country, text )
	if vp.ParMap[ key ] == '' then
		return text
	end
	
	local t
	local pArgs = {
		phone = vp.ParMap[ key ],
		cc = country.cc,
		nocc = true,
		isFax = false,
		isTollfree = false,
		format = false
	}
	if vc.wdContent[ key ] then
		pArgs.format = true
		pArgs.size = country.phoneDigits or 2
	end

	if key == 'fax' then
		t = '<span class="p-tel-fax fax listing-fax'
		pArgs.isFax = true
	else
		t = '<span class="p-tel tel listing-phone'
		if key == 'phone' then
			t = t .. ' listing-landline'
		elseif key == 'tollfree' then
			t = t .. ' listing-tollfree'
			pArgs.isTollfree = true
		elseif key == 'mobile' then
			t = t .. ' listing-mobile'
		end
	end
	t = t .. vc.addWdClass( key ) .. '">' .. lp.linkPhoneNumberSet( pArgs ) .. '</span>'
	return vc.addComma( text ) .. mw.ustring.format( mi.texts[ key ], t )
end

function vc.formatSocial( key, url, name )
	local t = vp.ParMap[ key ]
	if t == '' then
		return ''
	end
	if not t:find( key, 1, true ) then
		t = url .. t
	end
	return '<span style="' .. mi.texts.socialStyle
		.. '" class="listing-social-media' .. vc.addWdClass( key ) .. '">['
		.. t .. mw.ustring.format( mi.icons[ key ], name ) .. ']</span>'
end

function vc.makeIcons( sisters, name, id, withFullStop )
	local r = '', s, t, u
	t, s = mb.addSisterIcons( sisters, name, id )
	u = vc.formatSocial( 'facebook', 'https://www.facebook.com/', name )
		.. vc.formatSocial( 'flickr', 'https://www.flickr.com/photos/', name )
		.. vc.formatSocial( 'instagram', 'https://www.instagram.com/', name )
		.. vc.formatSocial( 'twitter', 'https://twitter.com/', name )		
		.. vc.formatSocial( 'youtube', 'https://www.youtube.com/channel/', name )
	t = t .. u

	if t == '' or not withFullStop then
		return t
	end
	if t == s then
		-- only Wikidata icon. This is not visible for readers who are not logged in.
		return mw.ustring.gsub( t, '</span>', '.</span>' )
	end
	if u ~= '' then -- with social media
		return t .. '<span class="listing-social-media listing-full-stop">.</span>'
	else
		return t .. '<span class="listing-sister-icon listing-full-stop">.</span>'
	end
end

-- bdi and bdo tags are not working properly on all browsers. Adding marks
-- (lrm, rlm) is maybe the only way for a correct output
function vc.languageSpan( s, titleHint, wikiLang, country )
	local c = country.lang, t, isR2L
	s = s or ''
	if s == '' or c == '' or c == wikiLang then
		return s
	end

	isR2L = lg.isR2L( c )
	t = '<span lang="' .. c .. '" xml:lang="' .. c .. '"' ..
		' title="' .. mw.ustring.format( titleHint , country.langName ) .. '"'
	if isR2L then
		t = t .. ' dir="rtl"'
	elseif wikiLangR2L then
		t = t .. ' dir="ltr"'
	end
	t = t .. '>' .. s .. '</span>'
	if isR2L and not wikiLangR2L then
		t = '&rlm;' .. t .. '&lrm;'
	elseif not isR2L and wikiLangR2L then
		t = '&lrm;' .. t .. '&rlm;'
	end
	return t
end

function vc.formatDate( aDate, aFormat )
	return mw.getContentLanguage():formatDate( aFormat, aDate, true )
end

function vc.removeFullStops( s )
	-- closing (span) tags between full stops
	s = mw.ustring.gsub( s, '%.+(</[%l<>/]+>)%.+', '%1.' )
	return mw.ustring.gsub( s, '%.%.+', '.' )
end

-- create unesco image with link and title
function vc.getUnescoImage( country, continent )
	local title = mi.imgTitles[ continent ]
	if title then
		title = title .. '|link=' .. mi.articles[ continent ] .. '#' .. country
	else
		title = mi.imgTitles.default .. '|link=' .. mi.articles.default
	end
	return mw.ustring.format( mi.icons.unesco, title )
end

-- vCard main function

function vc.vCard( frame )
	local wikiLang = mw.getContentLanguage():getCode()
	local wikiLangR2L = lg.isR2L( wikiLang )
	local vcEntity = nil -- location (vCard/listing) entity
	local wrongQualifier = false

	-- text parts
	local leading = '' -- leading part (names)
	local contacts = '' -- all contacts
	local body = '' -- additional information

	local r, s, t, u, key, value, key2, value2,
		errShow, arrShow, addShow, arrSubtype

	local args = frame:getParent().args
	args[ vi.p.name ] = args[ vi.p.name ] or ''
	args[ vi.p.nameLocal ] = args[ vi.p.nameLocal ] or ''
	vp.ParMap.nameLocal = args[ vi.p.nameLocal ]

	local extra = 'type:landmark_globe:earth'
	local thisWiki = ''  -- current Wikivoyage branch
	local sisters = {
		wikivoyage = '', -- link to another branch, usually en, as a sister link
		commons    = '', -- link to Commons category
		wikipedia  = ''  -- link to Wikipedia
	}

	local titleObj = mw.title.getCurrentTitle()
	local ns = titleObj.namespace

	local function addNameExtra()
		if vp.ParMap.nameExtra == '' then
			return ''
		else
			return ' ' .. vp.ParMap.nameExtra
		end
	end

	mb.initMaintenance( 'VCard' )

	vp.ParMap.wikidata, vcEntity, wrongQualifier = fw.getEntity( args[ vi.p.wikidata ] or '' )
	if wrongQualifier then
		mb.addMaintenance( mi.maintenance.wrongQualifier )
	elseif vp.ParMap.wikidata ~= '' then
		mb.addMaintenance( mi.maintenance.wikidata )
	end
	if not args[ vi.p.auto ] then
		args[ vi.p.auto ] = 'n'
	elseif args[ vi.p.auto ] == '' then
		args[ vi.p.auto ] = 'y'
	end
	vp.ParMap.auto = yn( args[ vi.p.auto ], false )

	t = yn( args[ vi.p.name ], nil )
	if t ~= nil then
		args[ vi.p.name ] = ''
	end

	-- getting name from Wikidata
	local officialNames = nil
	if vp.ParMap.wikidata == '' then
		vp.ParMap.auto = false
	else
		if args[ vi.p.name ] == '' then
			-- getting official names
			officialNames, vc.catArray = fw.getValuesWithLanguages( vcEntity, 'P1448', vc.catArray )
			args[ vi.p.name ] = officialNames[ wikiLang ] or mi.langs.name ~= ''
				and officialNames[ mi.langs.name ] or ''

			if args[ vi.p.name ] == '' then
				if wikiLang == mi.langs.name then
					args[ vi.p.name ] = vcEntity:getLabel() or ''
				else
					args[ vi.p.name ] = vcEntity:getLabel() or mi.langs.name ~= ''
						and vcEntity:getLabel( mi.langs.name ) or ''
				end
			end
			vp.ParMap.name = args[ vi.p.name ]
			vc.wdContent.name = ''
		end
	end

	-- checking for expensive sites and countries and getting country-specific data

	-- country-specific technical parameters
	local country
	country, vc.catArray = cm.getCountryData( vcEntity, vc.catArray )
	if country.fromWD then
		mb.addMaintenance( mi.maintenance.countryFromWD )
	end
	if country.iso_3166 ~= '' then
		extra = extra .. '_region:' .. country.iso_3166
		t = vd[ country.iso_3166 ]
		if t then
			vp.ParMap.show = t
		end
	end
	if country.lang ~= '' then
		country.langName = lg.getProperty( country.lang, 'n' )
		if country.langName == '' then
			vc.unknownLanguage = true
		end
	end

	-- getting wiki links
	if vp.ParMap.wikidata ~= '' and vcEntity.sitelinks then
		t = vcEntity.sitelinks[ wikiLang .. 'wikivoyage' ]
		if t then
			thisWiki = t.title
			if thisWiki == titleObj.text then
				thisWiki = '' -- no link to the article itself
			end
		end
		sisters.wikipedia = mb.getWikiLink( { wikiLang, mi.langs.name, country.lang }, 'wiki', vcEntity )
		if thisWiki == '' then
			sisters.wikivoyage = mb.getWikiLink( { mi.langs.name, country.lang }, 'wikivoyage', vcEntity )
		end
	end

	-- handling args and vp.ParMap show arrays
	arrShow = vc.split( vp.ParMap.show, true )
	addShow, errShow = vc.splitAndCheck( args[ vi.p.show ], vp.show )
	if addShow.none or addShow.coord or addShow.all then
		arrShow.poi = nil -- overwriting default
	end
	if addShow.inline then
		mb.addMaintenance( mi.maintenance.inlineSelected )
	end
	for key, value in pairs( addShow ) do
		arrShow[ key ] = value
	end
	if arrShow.none or arrShow.coord or arrShow.poi then
		arrShow.all = nil
	end
	if arrShow.none then
		arrShow.coord = nil
		arrShow.poi = nil
	end
	if arrShow.nosubtype then
		arrShow.subtype = nil	
	end
	if arrShow.subtype then
		vp.ParMap.subtypeAdd = not args[ vi.p.subtypeAdd ]
	end

	-- force getting data from Wikidata for missing parameters
	if vp.ParMap.auto == true then
		if ( args[ vi.p.nameLocal ] or '' ) == '' and wikiLang ~= country.lang then
			args[ vi.p.nameLocal ] = true
			vp.ParMap.nameLocal = true
		end
		for key, value in pairs( vp.ParWD ) do
			if vi.p[ key ] then
				if ( args[ vi.p[ key ] ] or '' ) == '' then
					args[ vi.p[ key ] ] = true
					vp.ParMap[ key ] = true
				end
			end
		end
	end

	-- copying args parameters to vp.ParMap parameters
	local translKey
	local descrDiv = false -- description with div or span tag
	for key, value in pairs( args ) do
		translKey = nil
		for key2, value2 in pairs( vi.p ) do
			if value2 == key then
				translKey = key2
				break
			end
		end

		value, t =
			mb.removeCtrls( value, arrShow.inline or translKey ~= 'description' )
		if t then
			descrDiv = true
		end

		if translKey then
			if translKey ~= 'auto' and translKey ~= 'show' and translKey ~= 'wikidata' then
				if value == '' then
					value = true
				elseif not value then
					value = false
				end
				t = yn( value, nil )
				if t ~= nil then
					if vp.ParMap.wikidata ~= '' then
						vp.ParMap[ translKey ] = t
					else
						vp.ParMap[ translKey ] = ''
					end
				else
					vp.ParMap[ translKey ] = value
				end
			end
		else
			mb.addWrongParameter( key )
		end
	end

	-- getting addresses from Wikidata
	vc.getAddressesFromWD( vcEntity, country, wikiLang )

	-- image check
	if type( vp.ParMap.image ) ~= 'boolean' and vp.ParMap.image ~= '' then
		vp.ParMap.image, vc.catArray =
			mb.checkImage( vp.ParMap.image, vcEntity, vc.catArray )
	end

	-- handling linked names like [[article|text]]
	local name = mb.getName( vp.ParMap.name, thisWiki )

	-- getting data from Wikidata
	if vp.ParMap.wikidata ~= '' then
		for key, value in pairs( vp.ParMap ) do
			if key ~= 'auto' and key ~= 'show' and key ~= 'wikidata'
				and key ~= 'name' and vp.ParMap[ key ] == true then
				if key == 'nameLocal' then
					if not officialNames then
						officialNames, vc.catArray = fw.getValuesWithLanguages( vcEntity, 'P1448', vc.catArray )
					end
					if officialNames then
						vp.ParMap.nameLocal = officialNames[ country.lang ] or ''
					end
					if vp.ParMap.nameLocal == '' then
						vp.ParMap.nameLocal = vcEntity:getLabel( country.lang ) or ''
					end
					if vp.ParMap.nameLocal ~= '' then
						t = mw.ustring.upper( vp.ParMap.nameLocal )
						if t == mw.ustring.upper( name.name ) then
							vp.ParMap.nameLocal = ''
						elseif t == mw.ustring.upper( vp.ParMap.alt ) then
							vp.ParMap.alt = ''
						end
					end
					vc.wdContent.nameLocal = ''
				elseif vp.ParMap[ key ] and vp.ParWD[ key ] then
					vp.ParMap[ key ] =
						vc.getFromWD( vp.ParWD[ key ], vcEntity, wikiLang, country.lang )
					vc.wdContent[ key ] = ''
				else
					vp.ParMap[ key ] = ''
				end
			end
		end
		if vp.ParMap.type == '' then
			vp.ParMap.type =
				vc.getFromWD( vp.ParWD.type, vcEntity, country.lang )
		end
	end
	for key, value in pairs( vp.ParMap ) do
		if type( vp.ParMap[ key ] ) == 'boolean' then
			vp.ParMap[ key ] = ''
		end		
	end

	-- use local name if name is not given
	if name.name == '' and vp.ParMap.nameLocal ~= '' then
		vp.ParMap.name = vp.ParMap.nameLocal
		name = mb.getName( vp.ParMap.name, thisWiki )
		vp.ParMap.nameLocal = ''
	end
	-- missing name
	if name.name == '' then
		vp.ParMap.name = mi.maintenance.missingName
		name = mb.getName( vp.ParMap.name, thisWiki )
		mb.addMaintenance( mi.maintenance.missingNameMsg )
	end
	-- names shall not contain tags or template calls
	if vp.ParMap.name:find( '<', 1, true ) or vp.ParMap.name:find( '{{', 1, true ) or 
		vp.ParMap.nameLocal:find( '<', 1, true ) or vp.ParMap.nameLocal:find( '{{', 1, true ) then
		mb.addMaintenance( mi.maintenance.malformedName )
	end

	-- error handling of subtype array
	arrSubtype, t = vc.splitAndCheck( vp.ParMap.subtype, vs.f )
	if t ~= '' then
		mb.addMaintenance( mw.ustring.format( mi.maintenance.unknownSubtype, t ) )
	end
	if errShow ~= '' then
		mb.addMaintenance( mw.ustring.format( mi.maintenance.unknownShow, errShow ) )
	end

	-- checking and getting coordinates
	vp.ParMap.lat, vp.ParMap.long = mb.checkCoordinates( vp.ParMap.lat, vp.ParMap.long )
	if ( vp.ParMap.lat == '' or vp.ParMap.long == '' ) and vp.ParMap.wikidata ~= '' then
		t, vc.catArray = fw.getValue( vcEntity, 'P625', vc.catArray )
		if t ~= '' then
			vp.ParMap.lat = t.latitude
			vp.ParMap.long = t.longitude
			vc.wdContent.lat = ''
		end
	end
	if vp.ParMap.lat == '' or vp.ParMap.long == '' then
		arrShow.all = nil
		arrShow.coord = nil
		arrShow.poi = nil
		mb.addMaintenance( mi.maintenance.missingCoordVc )
	end

	-- getting Marker type and group
	vp.ParMap.type, vp.ParMap.group = mb.checkTypeAndGroup( vp.ParMap.type, vp.ParMap.group )
	vp.ParMap.groupTranslated = mb.translateGroup( vp.ParMap.group )

	-- generating output
	-- leading part for marker mode: only location names and comment

	vp.ParMap.zoom = math.floor( tonumber( vp.ParMap.zoom ) or mi.defaultZoomLevel )
	if vp.ParMap.zoom < 0 or vp.ParMap.zoom > mi.maxZoomLevel then
		vp.ParMap.zoom = mi.defaultZoomLevel
	end
	
	-- wrapping tag
	r = 'vCard vcard h-card'
	if arrShow.indent then
		r = r .. ' listing-indent'
	end
	if arrShow.inline then
		r = '<span class="' .. r .. '"'
	else
		r = '<div class="' .. r .. '"'
	end

	-- adding metadata to the wrapping tag
	r = r .. mb.data( 'data-region', country.iso_3166 )
		.. mb.data( 'data-country', country.country )
		.. mb.data( 'data-country-calling-code', country.cc )
		.. mb.data( 'data-lang', country.lang )
		.. mb.data( 'data-wikilang', wikiLang )
		.. mb.data( 'data-location', mb.htmlReplace( titleObj.subpageText ) )
		.. mb.data( 'data-name', mb.htmlReplace( name.name ) )
		.. mb.data( 'data-symbol', '-number-' .. vp.ParMap.group )
	if country.currency ~= '' then
		r = r .. ' data-currency="' .. country.currency
		if vm[ country.currency ] then
			r = r .. ', ' .. vm[ country.currency ]
		end
		r = r .. '"'
	end
	if country.lang == '' then
		vc.unknownLanguage = true
	end
	for key, value in pairs( vi.vcardData ) do
		r = r .. mb.data( value, vp.ParMap[ key ] )
	end
	local color = mb.getColor( vp.ParMap.group )
	r = r .. mb.data( 'data-color', '#' .. color )
	if vp.ParMap.commonscat ~= '' then
		mb.addMaintenance( mi.maintenance.commonscat )
	end
	if vp.ParMap.wikidata ~= '' then
		r = r .. mb.data( 'data-wikidata', vp.ParMap.wikidata )
		t, vc.catArray = fw.getValue( vcEntity, 'P373', vc.catArray )
		if t == '' and vcEntity.sitelinks and vcEntity.sitelinks.commonswiki then
			t = vcEntity.sitelinks.commonswiki.title
			if mw.ustring.find( t, 'Category:', 1, true ) then
				t = mw.ustring.gsub( t, 'Category:', '' )
			else
				t = ''
			end
		end
		if t ~= '' and vp.ParMap.commonscat ~= '' then
			mb.addMaintenance( mi.maintenance.commonscatWD )
		end
		if vp.ParMap.commonscat == '' then
			vp.ParMap.commonscat = t
		end
	end
	if vp.ParMap.commonscat ~= '' then
		t = mw.ustring.gsub( vp.ParMap.commonscat, ' ', '_' )
		r = r .. mb.data( 'data-commonscat', t )
		sisters.commons = tostring( mw.uri.fullUrl( 'c:Category:' .. mw.uri.encode( t, 'WIKI' ) ) )
	end
	r = r .. mb.data( 'data-url', mw.text.nowiki( vp.ParMap.url ) )
		.. mb.data( 'data-image', mw.ustring.gsub(  vp.ParMap.image, ' ', '_' ) )
		.. '>' -- tag closing

	-- inserting content

	if vp.ParMap.image ~= '' then
		r = r .. '<span class="listing-image" style="display: none">[[File:' .. vp.ParMap.image
			.. '|350px|class=noviewer|' .. name.all .. ']]</span>'
	end

	if vp.ParMap.lat ~= '' and vp.ParMap.long ~= '' then
		r = r .. '<span class="p-geo geo listing-coordinates" style="display: none">'
			.. '<span class="p-latitude latitude">' .. vp.ParMap.lat .. '</span>'
			.. '<span class="p-longitude longitude">' .. vp.ParMap.long .. '</span></span>'
			.. frame:callParserFunction{ name = '#coordinates',
			args = { vp.ParMap.lat, vp.ParMap.long, extra, name = name.name } }
	end
	if vp.ParMap.before ~= '' then
		r = r .. vp.ParMap.before .. '&#160;'
	end

	-- adding POI marker
	if arrShow.all or arrShow.poi then
		r = r ..
			mb.addingMarkerSymbol( vp.ParMap, name.all, '', '-number-' .. vp.ParMap.group,
				false, color, frame ) .. ' '
	end
	
	-- adding names, url, comment and airport codes
	-- url check
	vp.ParMap.url = mb.checkUrl( vp.ParMap.url )
	s = '<bdi id="vCard_' .. mw.uri.anchorEncode( name.name )
		.. '" class="p-name p-org fn org listing-name">'
	if vp.ParMap.url ~= '' then
		if name.pageTitle == '' then
			s = s .. '[' .. vp.ParMap.url .. ' ' .. mb.replaceBrackets( name.name )
				.. ']' .. addNameExtra() .. '</bdi>'
		else
			-- article and web links
			s = s .. name.all .. addNameExtra()
				.. '</bdi> <span class="listing-url">['
				.. vp.ParMap.url .. ' ' .. mi.icons.internet .. ']</span>'
		end
	else
		s = s .. name.all .. addNameExtra() .. '</bdi>'
	end
	if vc.wdContent.name then
		r = r .. '<span class="wikidata-content">' .. s .. '</span>'
	else
		r = r .. s
	end

	t = ''
	if mi.options.showLocalData then
		if vp.ParMap.nameLocal ~= '' then
			t = '<span class="listing-name-local' .. vc.addWdClass( 'nameLocal' ) .. '">'
				.. vc.languageSpan( vp.ParMap.nameLocal, mi.texts.hintName, wikiLang, country )
				.. '</span>'
		end
		if vp.ParMap.nameLatin ~= '' then
			t = vc.addComma( t ) .. '<span class="listing-name-latin listing-emphasized" title="'
				.. mi.texts.hintLatin .. '">' .. vp.ParMap.nameLatin .. '</span>'
		end
	end
	if vp.ParMap.alt ~= '' then
		t = vc.addComma( t ) .. '<bdi>' .. vp.ParMap.alt .. '</bdi>'
	end
	if t ~= '' then
		t = '<span class="p-nickname nickname listing-alt">' .. t .. '</span>'
	end
	if vp.ParMap.comment ~= '' then
		t = vc.addComma( t ) .. '<span class="listing-comment listing-emphasized"><bdi>'
			.. vp.ParMap.comment .. '</bdi></span>'
	end
	if vp.ParMap.iata ~= '' then
		s = '<span class="listing-airport listing-iata' .. vc.addWdClass( 'iata' ) .. '">'
			.. vp.ParMap.iata .. '</span>'
		t = vc.addComma( t ) .. mw.ustring.format( mi.texts.iata, s )
	elseif vp.ParMap.iata == '' and vp.ParMap.icao ~= '' then
		s = '<span class="listing-airport listing-icao' .. vc.addWdClass( 'icao' ) .. '">'
			.. vp.ParMap.icao .. '</span>'
		t = vc.addComma( t ) .. mw.ustring.format( mi.texts.icao, s )
	end
	if t ~= '' then
		r = r .. ' (' .. t .. ')'
	end
	
	leading = r -- end of leading

	-- additional part for vCard mode
	
	-- assorting contact information
	r = ''
	if vp.ParMap.address ~= '' then
		r = r .. ', <bdi class="p-adr adr listing-address'
			.. vc.addWdClass( 'address' ) .. '"'
		if vp.ParMap.addressLang and vp.ParMap.addressLang ~= '' then
			t = lg.getProperty( vp.ParMap.addressLang, 'n' )
			if t == '' then
				vc.unknownLanguage = true
			end
			r = r .. ' lang="' .. vp.ParMap.addressLang
				.. '" xml:lang="' .. vp.ParMap.addressLang .. '"'
				.. ' title="' .. mw.ustring.format( mi.texts.hintAddress2, t ) .. '"'
		end
		r = r .. '><span class="p-street-address street-address">'
			.. vp.ParMap.address .. '</span></bdi>'
	end
	if mi.options.showLocalData and vp.ParMap.addressLocal ~= '' then
		vp.ParMap.addressLocal =
			vc.languageSpan( vp.ParMap.addressLocal, mi.texts.hintAddress, wikiLang, country )
		r = r .. '<span class="listing-add-info">, <span class="listing-address-local'
			.. vc.addWdClass( 'addressLocal' ) .. '">' .. vp.ParMap.addressLocal
			.. '</span></span>'
	end
	if vc.unknownLanguage then
		mb.addMaintenance( mi.maintenance.unknownLanguage )
	end	

	t = ''
	if vp.ParMap.directions ~= '' then
		t = '<span class="listing-directions listing-emphasized'
			.. vc.addWdClass( 'directions' ) .. '">' .. vp.ParMap.directions
			.. "</span>"
	end
	s = ''
	if mi.options.showLocalData and vp.ParMap.directionsLocal ~= '' then
		s = '<span class="listing-add-info">, <span class="listing-directions-local'
			.. vc.addWdClass( 'directionsLocal' ) .. '">'
			.. vc.languageSpan( vp.ParMap.directionsLocal, mi.texts.hintDirections, wikiLang, country )
			.. '</span></span>'
	end
	if t ~= '' then
		r = r .. ' (' .. t .. s .. ')'
	else
		r = r .. s
	end
	if r ~= '' then
		r = r .. '. '
	end

	t = vc.formatPhone( 'phone', country, '' )
	t = vc.formatPhone( 'tollfree', country, t )
	t = vc.formatPhone( 'mobile', country, t )
	t = vc.formatPhone( 'fax', country, t )
	if vp.ParMap.email ~= '' then
		s = '<span class="u-email email listing-email' .. vc.addWdClass( 'email' )
			.. '">' .. lm.linkMailSet( { email = vp.ParMap.email } ) .. '</span>'
		t = vc.addComma( t ) .. mw.ustring.format( mi.texts.email, s )
	end
	if vp.ParMap.skype ~= '' then
		s = '<span class="listing-skype' .. vc.addWdClass( 'skype' ) .. '">'
			.. ls.linkSkypeSet( { skype = vp.ParMap.skype } ) .. '</span>'
		t = vc.addComma( t ) .. mw.ustring.format( mi.texts.skype, s )
	end
	if t ~= '' then
		r = r .. t .. '.'
	end
	-- contacts starts with punctuation mark
	if not r:find( '^,' ) and not r:find( '^ %(' )then
		r = '. ' .. r
	end
	contacts = vc.removeFullStops( r ) -- end of contact information
	
	-- making body
	r = ''
	if vp.ParMap.description ~= '' and not descrDiv then
		r = r .. ' <span class="p-note note listing-content">' ..
			vp.ParMap.description .. '</span>'
	end

	r = r .. vc.formatText( 'hours', 'p-note note listing-hours' )
		.. vc.formatText( 'checkin', 'listing-checkin' )
		.. vc.formatText( 'checkout', 'listing-checkout' )
		.. vc.formatText( 'price', 'p-note note listing-price' )
	if vp.ParMap.payment ~= '' then
		u = 'p-note note listing-payment'
		if vc.wdContent.payment then -- vp.ParMap.payment is an array
			if #vp.ParMap.payment > 0 then
				u = u .. ' wikidata-content'
				for s = #vp.ParMap.payment, 1, -1 do -- remove unknown items
					t = vp.ParMap.payment[ s ]
					if vr[ t ] then
						vp.ParMap.payment[ s ] = vr[ t ]
					else
						table.remove( vp.ParMap.payment, s )
					end
				end
			end
			vp.ParMap.payment = table.concat( vp.ParMap.payment, ', ' )
		else
			mb.addMaintenance( mi.maintenance.paymentUsed )
		end			
		r = r .. vc.formatText( 'payment', u )
	end

	if arrShow.subtype then
		-- merging subtypeAdd to arrSubtype
		vc.wdContent.subtypeAdd =
			type( vp.ParMap.subtypeAdd ) == 'table' and #vp.ParMap.subtypeAdd > 0
		if vc.wdContent.subtypeAdd then
			for s = 1, #vp.ParMap.subtypeAdd, 1 do
				t = vp.ParMap.subtypeAdd[ s ] -- Wikidata id
				if vs.t[ t ] then
					arrSubtype[ vs.t[ t ] ] = ''
				end
			end
		end
		
		t = ''
		if next( arrSubtype ) then
			for u = 2, vs.n, 1 do -- number of subtype groups
				for key, value in pairs( arrSubtype ) do
					s = vs.f[ key ]
					if s and s.g == u then
						if s.f ~= '' then
							t = t .. ' ' .. s.f
						else
							t = t .. ' [' .. key .. ']'
						end
					end
				end
			end
		end
		if t ~= '' then
			r = r .. ' <span class="listing-subtype' .. vc.addWdClass( 'subtypeAdd' )
				.. '">' .. mw.ustring.format( mi.texts.subtype, t ) .. '.</span>'
		end
	end

	if vp.ParMap.unesco ~= '' then
		r = r .. ' <span class="listing-unesco wv-symbol-inline wv-symbol-unesco">'
			.. vc.getUnescoImage( country.country, country.cont ) .. '</span>'
	end

	body = r -- body contains only text parts

	-- adding DMS coordinates
	if arrShow.all or arrShow.coord then
		r = r .. ' '
			.. mb.dmsCoordinates( vp.ParMap.lat, vp.ParMap.long, name.name, vc.wdContent.lat, extra, true )
	end

	t = ''
	if vp.ParMap.description ~= '' and descrDiv then
		-- last edit will be inserted at the end of the div tag
		t = '<div class="p-note note listing-content">\n' .. vp.ParMap.description
		body = body .. t
	end

	if mi.options.showSisters == 'atEnd' then
		r = r .. vc.makeIcons( sisters, name.name, vp.ParMap.wikidata, body ~= '' )
	end
	r = r .. t

	t = ''
	if vp.ParMap.lastedit ~='' then
		local success;
		success, t = pcall( vc.formatDate, vp.ParMap.lastedit, 'M Y' )
		if success then
			t = mw.ustring.format( mi.texts.lastedit, t )
		else
			mb.addMaintenance( mi.maintenance.wrongDate )
			t = ''
		end
	end
	if t == '' then
		r = r .. '<span class="listing-metadata"><span class="listing-metadata-items">&nbsp;</span></span>'
	else
		r = r .. '<span class="listing-metadata"> (<span class="listing-metadata-items">'
			.. '<span class="listing-metadata-item listing-lastedit">' .. t .. '</span></span>)</span>'
	end

	if vp.ParMap.description ~= '' and descrDiv then
		r = r .. '</div>'
	end

	r = vc.removeFullStops( r )

	if contacts == '' and body == '' then
		r = leading
			.. vc.makeIcons( sisters, name.name, vp.ParMap.wikidata, false ) .. r
	else
		t = leading .. ( contacts == '' and '. ' or contacts )
		if mi.options.showSisters == true then
			-- could also be 'atEnd', then part of body
			t = t .. vc.makeIcons( sisters, name.name, vp.ParMap.wikidata, true )
		end
		r = t .. r
	end

	-- error handling and maintenance, not in template and module namespaces
	if ns ~= 10 and ns ~= 828 then
		r = r .. mb.getMaintenance()
			.. fw.getCategories( vc.catArray, mi.maintenance.properties )
	end

	-- wrapping tag
	return r .. ( arrShow.inline and '</span>' or '</div>' )
end

-- module administration
function vc.VCard()
	return vCard
end

function vc.failsafe( version )
	return fs._failsafe( version, vCard ) or ''
end

return vc