Modul:VCard

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

Anmerkungen

Anwendung

Der 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 | credit-cards = 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 = 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. }}
  • 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 0176 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 Kreditkarten: Visa, Master, AmEx, Maestro. Merkmale: [bar] [pool] [wlan]. (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.
Hinweise
-- module import
local mb = require( 'Module:MarkerBase' )
local ms = require( 'Module:MarkerBase/i18n' )
local fw = require( 'Module:FastWikidata' )

local vt = require( 'Module:VCard/Types' ) -- types to groups like drink, eat, go, see, sleep, ...
local vs = require( 'Module:VCard/Subtypes' )
local vr = require( 'Module:VCard/Cards' ) -- credit-card types, not yet used
local vd = require( 'Module:VCard/Defaults' ) -- country-specific show defaults
local vm = require( 'Module:VCard/Currencies' ) -- additional currency symbols
local mc = require( 'Module:Marker/Colors' )

local yn = require( 'Module:Yesno' )
local cm = require( 'Module:CountryData' )
local pt = require( 'Module:Wikidata2/POITypes' ) -- WD types to vCard/Poi types
local lg = require( 'Module:Languages' )
local lp = require( 'Module:LinkPhone' )
local lm = require( 'Module:LinkMail' )
local ls = require( 'Module:LinkSkype' )
local un = require( 'Module:Unesco' )

local vc = {}

-- table of parameters
-- true: get in from Wikidata in any case

local ParMap = {
	address           = '',
	['address-local'] = '',
	['address-lang']  = '',
	alt               = '',
	auto              = '',
	before            = '',
	booking           = true, -- booking.com
	checkin           = '',
	checkout          = '',
	comment           = '',
	content           = '',
	['credit-cards']  = '',
	wikidata          = '',
	description       = '',
	directions        = '',
	['directions-local'] = '',
	email             = '',
	facebook          = '',
	fax               = '',
	flickr            = '',
	google            = '',
	group             = '',
	hotels            = true, -- hotels.com
	hours             = '',
	iata              = true,
	icao              = true,
	image             = true,
	['intl-area-code'] = '',
	lastedit          = '',
	lat               = '',
	long              = '',
	['map-group']     = '',
	mobile            = '',
	name              = ms.texts.noName,
	['name-extra']    = '',
	['name-local']    = '',
	['name-latin']    = '',
	phone             = '',
	price             = '',
	recreation        = true, -- Recreation.gov
	show              = ms.texts.defaultShow,
	skype             = '',
	subtype           = '',
	tollfree          = '',
	tripadvisor       = true,
	twitter           = '',
	['type']          = '',
	unesco            = true,
	url               = '',
	youtube           = ''
}

-- p property or set of properties
-- f formatter url string
-- c maximum count of results, default = 1
-- m mode (if c > 1), default concat with ', '
-- v value type, default: value, id, au = amount + unit

local ParWD = {
	booking     = { p = 'P3607' },
	email       = { p =  'P968', c = 5 },
	facebook    = { p = { { p = 'P2013', f = 'https://www.facebook.com/$1' },
				     { p = 'P1997', f = 'https://www.facebook.com/pages/-/$1' } } },
	fax         = { p = 'P2900', c = 3 },
	flickr      = { p = 'P3267', f = 'https://www.flickr.com/photos/$1' },
	google      = { p = 'P2847', f = 'https://plus.google.com/$1' },
	hotels      = { p = 'P3898' },
	iata        = { p =  'P238' },
	icao        = { p =  'P239' },
	image       = { p =   'P18' },
	phone       = { p = 'P1329', c = 5 },
	price       = { p = 'P2284', c = 1, v = 'au' }, -- maybe useless
	recreation  = { p = 'P3714' },
	skype       = { p = 'P2893', f = 'skype:$1' },
	tripadvisor = { p = 'P3134' },
	twitter     = { p = 'P2002', f = 'https://twitter.com/$1' },
	['type']    = { p =   'P31', c = 3, v = 'id' },
	unesco      = { p =  'P757' },
	url         = { p =  'P856' },
	youtube     = { p = 'P2397', f = 'https://www.youtube.com/channel/$1' }
}

-- Data to be inserted in vCard wrapper tag
local vcardData = {
	['type']      = 'data-type',
	group         = 'data-group',
	['group-translated'] = 'data-group-translated',
	['map-group'] = 'data-map-group',
	booking       = 'data-booking-com',
	hotels        = 'data-hotels-com',
	recreation    = 'data-recreation-gov',
	tripadvisor   = 'data-tripadvisor-com'
}

local searchLimit = 4 -- for P31
local wdContent = {} -- args got from Wikidata

-- Splitting comma separated lists
local function split( s, convert )
	local t
	local arr = {}
	if (s == nil) or (s == '') then return arr end

	for t in string.gmatch( s .. ',', '([^,]+)' ) do
		t = mw.text.trim( t )
		if t ~= '' then
			if convert then t = string.gsub( t:lower(), ' ', '_') end
			arr[t] = ''
		end
	end

	return arr
end

-- p : property id
-- tp: data value type
-- mx: maximum count
-- f : format
function vc.getWDvalues( p, tp, mx, f, entity )
	local r = ''
	local a, i, t, u
	local ar = fw.getValues( entity, p, mx )
	if #ar == 0 then return ar end

	if p == 'P31' then
		return { fw.typeSearch( ar, pt, searchLimit ) }
	else
		for i = 1, #ar, 1 do
			if tp == '' then
				if (ar[i] ~= '') and (f ~= '') and f:find( '$1' ) then
					ar[i] = mw.ustring.gsub( f, '($1)', ar[i])
				end

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

			elseif tp == 'au' then
				a = ar[i].amount
				a = mw.ustring.gsub( a, '+', '')
				if ms.texts.decimalPoint ~= '.' then
					a = mw.ustring.gsub( a, '%.', ms.texts.decimalPoint)
				end
				u = ar[i].unit
				u = mw.ustring.gsub( u, 'http://www.wikidata.org/entity/', '' )
				if mw.ustring.match( u, '^Q[%d]+$') then
					t = fw.getValue( u, 'P558' ) -- unit
					if t == '' then
						t = fw.getValue( u, 'P498' ) -- currency code
					end
					if t ~= '' then u = t end
				end
				if (a ~= '') and (u ~= '') then
					if (f ~= '') and f:find( '$1' ) and f:find( '$2' ) 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 )
	local arr = {} -- contains results of multiple singleProperty() calls

	local function singleProperty( pr, f, c, v )
		if #arr == 0 then
			arr = vc.getWDvalues( pr, v or '', c or 1, f or '', entity )
		else
			local subArr = vc.getWDvalues( pr, v or '', c or 1, f or '', entity )

			if #subArr > 0 then -- move to arr
				for i = 1, #subArr, 1 do table.insert( arr, subArr[i] ) end
			end
		end
	
		return
	end

	local p = parWDitem, i, prop
	if p == nil then return '' end
	p.c = p.c or 1 -- count

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

	if #arr > p.c then
		for i = p.c + 1, #arr, 1 do arr[i] = nil end
	end
	if #arr > 0 then
		if prop == 'P2893' then -- skype
			return table.concat( arr, '; ' )
		else
			return table.concat( arr, ', ' )
		end
		-- analyse other concat modes
	else
		return ''
	end
end

function vc.formatText( key, class )
	if ParMap[key] == '' then return '' end
	
	local r = ' <span class="' .. class
	if wdContent[key] then r = r .. ' wikidata-content' end
	r = r .. '">'
	if ms.texts[key] ~= '' then r = r .. ms.texts[key] .. ' ' end
	r = r .. ParMap[key]
	if not ParMap[key]:find( '%.$' ) then r = r .. '.' end
	return r .. '</span>'
end

function vc.formatPhone( key, country, text )
	if ParMap[key] == '' then return text end
	if text ~= '' then text = text .. ', ' end
	
	local function concatCC( tel, cc )
		if cc ~= '' then
			local t = tel
			t = t:gsub( '^00', '+' )
			t = t:gsub( '^%+%+', '+' )
			if t:sub( 1, 1 ) == '+' then return t end
			if (cc ~= '+39') and (cc ~= '+378') then t = t:gsub( '^0', '(0)' ) end
			return cc .. ' ' .. t
		else
			return tel
		end
	end

	local pArgs = {}
	pArgs.cc = ParMap['intl-area-code']
	pArgs.phone = concatCC( ParMap[key], pArgs.cc )
	if pArgs.cc == '' then pArgs.cc = country.cc end
	pArgs.nocc = 'true'
	pArgs.isFax = ''
	pArgs.format = ''
	local t = ms.texts[key]
	if key == 'fax' then
		t = t .. ' <span class="p-tel-fax fax listing-fax'
		pArgs.isFax = 'true'
	else
		t = t .. ' <span class="p-tel tel listing-phone'
		if key == 'phone' then t = t .. ' listing-landline'
		elseif key == 'tollfree' then t = t .. ' listing-tollfree'
		elseif key == 'mobile' then t = t .. ' listing-mobile'
		end
	end
	if wdContent[key] then
		t = t .. ' wikidata-content'
		pArgs.format = 'true'
	end
	t = t .. '">' .. lp.linkPhoneNumberSet( pArgs ) .. '</span>'
	return text .. t
end

function vc.formatSocial( key, f, url )
	local t = ParMap[key], s
	if t == '' then return '' end
	if not t:find( f ) then t = url .. t end
	s = ' <span class="listing-social-media'
	if wdContent[key] then s = s .. ' wikidata-content' end
	return s .. '">[' .. t .. ms.icons[key] .. ']</span>'
end

function vc.languageSpan( s, titleHint, wikiLang, country )
	local c = country.lang
	if (s == nil) or (s == '') then return '' end
	if (c == '') or (c == wikiLang) then return s end

	local isR2L = lg.getProperty( c, 'd' ) == 'rtl'
	local t = '<span lang="' .. c .. '" xml:lang="' .. c .. '"' ..
		' title="' .. titleHint .. ' ' .. country.langName .. '"'
	if isR2L then
		t = t .. ' dir="rtl"'
	else
		if wikiLangR2L then t = t .. ' dir="ltr"' end
	end
	t = t .. '>' .. s .. '</span>'
	if isR2L and not wikiLangR2L then t = '&rlm;' .. t .. '&lrm;' end
	if 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

-- vCard main function

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

	local r, s, t, u, key, value
	local cntrl = false

	local args = frame:getParent().args
	args.name = args.name or ''
	args['name-local'] = args['name-local'] or ''
	ParMap['name-local'] = args['name-local']

	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
	}

	ParMap.wikidata, vcEntity, wrongQualifier = fw.getEntity( args.wikidata or '' )
	if args.auto == nil then args.auto = 'n'
	elseif args.auto == '' then args.auto = 'y' end
	ParMap.auto = yn( args.auto, false )

	t = yn( args.name, nil )
	if t ~= nil then args.name = '' end

	-- getting name from Wikidata
	if ParMap.wikidata == '' then
		ParMap.auto = false
	else
		if args.name == '' then
			if wikiLang == 'en' then
				args.name = vcEntity:getLabel() or ''
			else
				args.name = vcEntity:getLabel() or vcEntity:getLabel( 'en' ) or ''
			end
			ParMap.name = args.name
			wdContent.name = ''
		end
	end

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

	-- Country-specific technical parameters
	local country = {
		id = '',
		iso_3166 = '',
		cc = '',
		lang = '',
		langName = '',
		currency = '',
		country = ''
	}

	country = cm.getCountryData( vcEntity )
	if country.iso_3166 ~= '' then
		extra = extra .. '_region:' .. country.iso_3166
		t = vd[country.iso_3166]
		if t then ParMap.show = t end
	end
	if country.lang ~= '' then
		country.langName = lg.getProperty( country.lang, 'n' )
	end

	-- getting addresses from Wikidata
	local addresses = nil
	if ParMap.wikidata ~= '' then
		addresses = fw.getValuesWithQualifierIds( vcEntity, 'P969', 'P407',
			lg.getProperty( country.lang, 'q' ) )
		if next( addresses ) == nil then addresses = nil end
	end
	if ParMap.auto and ( args.address == nil or args.address == '' ) then
		args.address = true
	end
	if not ParMap.auto and ( args.address == nil ) then args.address = '' end
	t = yn( args.address, nil )
	if ( ( t ~= nil ) and ( ParMap.wikidata == '' ) ) or
		( ( t == false  or t == nil ) and ( ParMap.wikidata ~= '' ) ) then
		args.address = ''
		ParMap.address = ''
	elseif addresses and ( t == true ) and ( ParMap.wikidata ~= '' ) then
		args.address = addresses[ lg.getProperty( wikiLang, 'q' ) ]
		-- select address if the same writing system is used
		if ( args.address == nil ) then
			u = lg.getProperty( wikiLang, 'w' )
			for key, value in pairs( addresses ) do
				t = lg.id2code[ key ]
				if t and ( lg.getProperty( t, 'w' ) == u ) then
					args.address = value
					args['address-lang'] = t
					break
				end
			end
		end
		if ( args.address == nil ) then
			args.address = addresses[ lg.getProperty( 'en', 'q' ) ]
			args['address-lang'] = 'en'
		end
		if ( args.address == nil ) then
			args.address = addresses[ lg.getProperty( 'fr', 'q' ) ]
			args['address-lang'] = 'fr'
		end
		if ( args.address == nil ) then
			args.address = ''
			args['address-lang'] = ''
		end
		ParMap.address = args.address
		ParMap['address-lang'] = args['address-lang']
		if args.address ~= '' then wdContent.address = true end
	end
	if ParMap.auto and ( args['address-local'] == nil or args['address-local'] == '')
		then args['address-local'] = true end
	if not ParMap.auto and ( args['address-local'] == nil ) then args['address-local'] = '' end
	t = yn( args['address-local'], nil )
	if ( ( t ~= nil ) and ( ParMap.wikidata == '' ) ) or
		( ( t == false or t == nil ) and ( ParMap.wikidata ~= '' ) ) then
		args['address-local'] = ''
		ParMap['address-local'] = ''
	elseif addresses and ( t == true ) and ( ParMap.wikidata ~= '' ) and
		( country.lang ~= wikiLang ) and ( country.lang ~= 'en' ) and
		( country.lang ~= 'fr' ) then
		t = lg.getProperty( country.lang, 'q' )
		if t ~= '' then
			args['address-local'] = addresses[ t ] or addresses[ 'unknown' ] or ''
		else
			-- unknown language, maybe missing in Module:Languages
			args['address-local'] =	addresses[ 'unknown' ] or ''
		end
		ParMap['address-local'] = args['address-local']
		if args['address-local'] ~= '' then wdContent['address-local'] = true end
	end

	if (ParMap.wikidata ~= '') and vcEntity.sitelinks then
		if vcEntity.sitelinks[wikiLang .. 'wikivoyage'] then
			thisWiki = vcEntity.sitelinks[wikiLang .. 'wikivoyage'].title
			if thisWiki == mw.title.getCurrentTitle().text then
				thisWiki = '' end -- no link to the article itself
		end
		if wikiLang == 'en' then
			sisters.wikipedia = mb.getWikiLink( {wikiLang, country.lang}, 'wiki', vcEntity )
		else
			sisters.wikipedia = mb.getWikiLink( {wikiLang, 'en', country.lang}, 'wiki', vcEntity )
		end
		if thisWiki == '' then
			if wikiLang == 'en' then
				sisters.wikivoyage = mb.getWikiLink( {country.lang}, 'wikivoyage', vcEntity )
			else
				sisters.wikivoyage = mb.getWikiLink( {'en', country.lang}, 'wikivoyage', vcEntity )
			end
		end
	end

	-- handling args and ParMap show arrays
	local arrShow = split( ParMap.show, true )
	local addShow = split( args.show, true )
	if addShow.none or addShow.coord or addShow.all
		then arrShow.poi = nil -- overwriting default
	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

	-- force getting data from Wikidata if existent
	if ParMap.auto == true then
		if (args['name-local'] == nil) or (args['name-local'] == '') and
			(wikiLang ~= country.lang) then
			args['name-local'] = true
			ParMap['name-local'] = true
		end
		for key, value in pairs( ParWD ) do
			if (args[key] == nil) or (args[key] == '') then
				args[key] = true
				ParMap[key] = true
			end
		end
	end

	-- copying args parameters to ParMap parameters
	local errorMsgs = ''
	-- ParMap['intl-area-code'] is separately handled because country code = '+1'
	-- (USA, Canada) is wrongly detect as true
	ParMap['intl-area-code'] = args['intl-area-code']
	if ParMap['intl-area-code'] == nil then ParMap['intl-area-code'] = '' end
	for key, value in pairs( args ) do
		-- remove breaks and controls
		t = mw.ustring.gsub( value, '<br%s*/*>', ' ' )
		t = mw.ustring.gsub( t, '</br>', ' ' )
		t = mw.ustring.gsub( t, '<p>', ' ' )
		if not mw.ustring.find( t, '<span' ) then
			t = mw.ustring.gsub( t, '[%z\000-\031]', ' ' ) end
		-- not %c because \127 is used for Mediawiki tags (strip markers `UNIQ)
		if t ~= value then
			cntrl = true
			value = t
		end

		if (key ~= 'auto') and (key ~= 'show') and (key ~= 'wikidata')
			and (key ~= 'intl-area-code') then
			if ParMap[key] == nil then
				if errorMsgs == '' then errorMsgs = '' .. key
				else errorMsgs = errorMsgs .. ', ' .. key end
			else
				if value == '' then value = true
				elseif value == nil then value = false end
				t = yn( value, nil )
				if t ~= nil then
					if ParMap.wikidata ~= '' then ParMap[key] = t else ParMap[key] = '' end
				else ParMap[key] = value end
			end
		end
	end
	if errorMsgs ~= '' then
		if errorMsgs:find( ',' ) then t = ms.errorMsg.unknownParams
		else t = ms.errorMsg.unknownParam end
		errorMsgs = '<span class="error">' .. t .. errorMsgs .. ms.errorMsg.maintenance .. '</span>'
	end

	if country.fromWD then errorMsgs = errorMsgs .. ms.errorMsg.countryFromWD end
	if ParMap['intl-area-code'] ~= '' then errorMsgs = errorMsgs .. ms.errorMsg.intlAreaCode end

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

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

	-- getting data from Wikidata
	if ParMap.wikidata ~= '' then
		for key, value in pairs( ParMap ) do
			if (key ~= 'auto') and (key ~= 'show') and (key ~= 'wikidata')
				and (key ~= 'name') and (ParMap[key] == true) then
				if key == 'name-local' then
					ParMap['name-local'] = vcEntity:getLabel( country.lang ) or ''
					if ParMap['name-local'] == name.name then ParMap['name-local'] = '' end
					wdContent['name-local'] = ''
				elseif ParMap[key] and ParWD[key] then
					ParMap[key] = vc.getFromWD( ParWD[key], vcEntity )
					wdContent[key] = ''
				else ParMap[key] = '' end
			end
		end
		if ParMap['type'] == '' then
			ParMap['type'] = vc.getFromWD( ParWD['type'], vcEntity ) end
	end
	for key, value in pairs( ParMap ) do
		if type( ParMap[key] ) == 'boolean' then ParMap[key] = '' end		
	end

	-- names shall not contain tags or template calls
	if ParMap.name:find( '<' ) or ParMap.name:find( '{{' ) or 
		ParMap['name-local']:find( '<' ) or ParMap['name-local']:find( '{{' ) then
		errorMsgs = errorMsgs .. ms.errorMsg.malformedName
	end

	-- handling subtype array
	t = ''
	local arrSubtype = split( ParMap.subtype, true )
	for key, value in pairs( arrSubtype ) do
		if vs[key] == nil then
			if t ~= '' then t = t .. ', ' end
			t = t .. key
			value = nil
		end
	end
	if t ~= '' then
		errorMsgs = errorMsgs .. ms.errorMsg.unknownSubtype
			.. '<span class="error">' .. ms.errorMsg.unknown .. ' ' .. t .. '</span>'
	end
	
	-- checking and getting coordinates
	local dms = false
	ParMap.lat, ParMap.long, dms = mb.checkCoordinates( ParMap.lat, ParMap.long )
	if dms then errorMsgs = errorMsgs .. ms.errorMsg.dmsCoordinate end
	if (ParMap.lat == '') or (ParMap.long == '') then
		if ParMap.wikidata ~= '' then
			t = fw.getValue( vcEntity, 'P625' )
			if t ~= '' then
				ParMap.lat = t.latitude
				ParMap.long = t.longitude
				wdContent.lat = ''
			end
		end
	end
	if (ParMap.lat == '') or (ParMap.long == '') then
		arrShow.all = nil
		arrShow.coord = nil
		arrShow.poi = nil
	end

	-- getting Marker type and group
	ParMap['type'], ParMap.group, errorMsgs =
		mb.checkTypeAndGroup( ParMap['type'], ParMap.group, errorMsgs )
	ParMap['group-translated'] = mb.translateGroup( ParMap.group )

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

	ParMap.zoom = 17
	
	-- 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
	if country.iso_3166 ~= '' then
		r = r .. ' data-region="' .. country.iso_3166 .. '"'
	end
	if country.cc ~= '' then
		r = r .. ' data-country-calling-code="' .. country.cc .. '"'
	end
	if country.lang ~= '' then
		r = r .. ' data-lang="' .. country.lang .. '"'
	else
		errorMsgs = errorMsgs .. ms.errorMsg.unknownLanguage
	end
	r = r .. ' data-wikilang="' .. wikiLang .. '"'
		.. ' data-name="' .. mb.htmlReplace( name.name ) .. '"'
		.. ' data-symbol="-number-' .. ParMap.group .. '"'
	if country.country ~= '' then
		r = r .. ' data-country="' .. country.country .. '"'
	end
	if country.currency ~= '' then
		r = r .. ' data-currency="' .. country.currency
		if vm[country.currency]
			then r = r .. ', ' .. vm[country.currency] end
		r = r .. '"'
	end
	for key, value in pairs( vcardData ) do
		if ParMap[key] ~= '' then
			r = r .. ' ' .. value .. '="' .. ParMap[key] .. '"'
		end
	end
	local color = mc.getColor( ParMap.group )
	r = r .. ' data-color="#' .. color .. '"'
	if ParMap.wikidata ~= '' then
		r = r .. ' data-wikidata="' .. ParMap.wikidata .. '"'
		t = fw.getValue( vcEntity, 'P373' )
		if (t ~= '') then
			t = mw.ustring.gsub( t, ' ', '_' )
			r = r .. ' data-commonscat="' .. t .. '"'
			sisters.commons = tostring( mw.uri.fullUrl( 'c:Category:' .. mw.uri.encode( t, 'WIKI' ) ) )
		end
	end
	if ParMap.url ~= '' then
		r = r .. ' data-url="' .. mw.text.nowiki( ParMap.url ) .. '"' end
	if ParMap.image ~= '' then
		r = r .. ' data-image="' .. mw.ustring.gsub(  ParMap.image, ' ', '_' ) .. '"' end
	r = r .. '>' -- tag closing

	-- inserting content

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

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

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

	t = ''
	if ParMap['name-local'] ~= '' then
		t = vc.languageSpan( ParMap['name-local'], ms.texts.hintName, wikiLang, country )
		if wdContent['name-local'] then
			t = '<span class="listing-name-local wikidata-content">' .. t .. '</span>'
		else
			t = '<span class="listing-name-local">' .. t .. '</span>'
		end
	end
	if ParMap['name-latin'] ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. '<span class="listing-name-latin listing-emphasized" title="' .. ms.texts.hintLatin .. '">'
			.. ParMap['name-latin'] .. '</span>'
	end
	if ParMap.alt ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. '<bdi>' .. ParMap.alt .. '</bdi>'
	end
	if t ~= '' then
		t = '<span class="p-nickname nickname listing-alt">' .. t .. '</span>'
	end
	if ParMap.comment ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. '<span class="listing-comment listing-emphasized"><bdi>' .. ParMap.comment .. '</bdi></span>'
	end
	if ParMap.iata ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. ms.texts.iataLink .. ': ' .. ParMap.iata
	end
	if (ParMap.iata == '') and (ParMap.icao ~= '') then
		if t ~= '' then t = t .. ', ' end
		t = t .. ms.texts.icaoLink .. ': ' .. ParMap.icao
	end
	if t ~= '' then r = r .. ' (' .. t .. ')' end
	
	local leading = r
	r = ''

	-- additional part for vCard mode
	
	local period = ''

	-- adding address and direction
	if ( ParMap.address == ParMap['address-local'] ) or
		( ParMap['address-lang'] and ( ParMap['address-lang'] == country.lang ) )then
		ParMap['address-local'] = ''
	end
	if ParMap['address-local'] ~= '' then
		ParMap['address-local'] =
			vc.languageSpan( ParMap['address-local'], ms.texts.hintAddress, wikiLang, country )
		if ParMap.address == '' then
			ParMap.address = ParMap['address-local']
			ParMap['address-local'] = ''
			wdContent.address = wdContent['address-local']
		end
	end
	if ParMap.address ~= '' then
		r = r .. ', <bdi class="p-adr adr listing-address'
		if wdContent.address then r = r .. ' wikidata-content' end
		r = r .. '"'
		if ParMap['address-lang'] and ParMap['address-lang'] ~= '' then
			r = r .. ' lang="' .. ParMap['address-lang']
				.. '" xml:lang="' .. ParMap['address-lang'] .. '"'
				.. ' title="' .. ms.texts.hintAddress2 .. ' '
				.. lg.getProperty( ParMap['address-lang'], 'n' ) .. '"'
		end
		r = r .. '><span class="p-street-address street-address">'
			.. ParMap.address .. '</span></bdi>'
	end
	if ParMap['address-local'] ~= '' then
		r = r .. '<span class="listing-add-info">, <span class="listing-address-local'
		if wdContent['address-local'] then r = r .. ' wikidata-content' end
		r = r .. '">' .. ParMap['address-local'] .. '</span></span>'
	end
	
	t = ''
	if ParMap.directions ~= '' then
		t = '<span class="listing-directions listing-emphasized">'
			.. ParMap.directions .. "</span>"
	end
	s = ''
	if ParMap['directions-local'] ~= '' then
		s = '<span class="listing-add-info">, <span class="listing-directions-local">'
			.. vc.languageSpan( ParMap['directions-local'], ms.texts.hintDirections, wikiLang, country )
			.. '</span></span>'
	end
	if t ~='' then r = r .. ' (' .. t .. s .. ')'
		else r = r .. s end
	if r ~= '' then r = r .. '. '
		else period = '. ' end

	t = ''
	t = vc.formatPhone( 'phone', country, t )
	t = vc.formatPhone( 'tollfree', country, t )
	t = vc.formatPhone( 'mobile', country, t )
	t = vc.formatPhone( 'fax', country, t )
	if ParMap.email ~='' then
		if t ~= '' then t = t .. ', ' end
		t = t .. ms.texts.email .. ' <span class="u-email email listing-email'
		if wdContent.email then t = t .. ' wikidata-content' end
		t = t .. '">' .. lm.linkMailSet( { email = ParMap.email } ) .. '</span>'
	end
	if ParMap.skype ~= '' then
		if t ~= '' then t = t .. ', ' end
		t = t .. ms.texts.skype .. ' <span class="listing-skype'
		if wdContent.skype then t = t .. ' wikidata-content' end
		t = t .. '">' .. ls.linkSkypeSet( { skype = ParMap.skype } ) .. '</span>'
	end
	if t ~= '' then
		t = t .. '.'
		r = r .. t
	end
	
	t = ''
	for key, value in pairs( sisters ) do
		if value ~= '' then
			t = t .. ' <span class="listing-sister-icon">['
				.. value .. ' ' .. ms.icons[key] .. ']</span>'
		end
	end
	s = ''
	if ParMap.wikidata ~= '' then
		s = '<span class="listing-sister-icon listing-sister-wikidata">['
			.. tostring( mw.uri.fullUrl( 'd:' .. ParMap.wikidata ) )
			.. ' ' .. ms.icons.wikidata .. ']</span>'
		t = t .. s
	end

	u = vc.formatSocial( 'facebook', 'facebook.com', 'https://www.facebook.com/' )
		.. vc.formatSocial( 'flickr', 'flickr.com', 'https://www.flickr.com/photos/' )
		.. vc.formatSocial( 'google', 'google.com', 'https://plus.google.com/' )
		.. vc.formatSocial( 'twitter', 'twitter.com', 'https://twitter.com/' )
		.. vc.formatSocial( 'youtube', 'youtube.com', 'https://www.youtube.com/channel/' )
	t = t .. u

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

	if (ParMap.description ~= '') or (ParMap.content ~= '') then
		t = ParMap.description
		if ParMap.content ~= '' then
			if t ~= '' then t = t .. ' ' end
			t = t .. ParMap.content
		end
		if t ~= ParMap[ ms.errorMsg.defaultDescr ] then
			errorMsgs = errorMsgs .. ms.errorMsg.contentUsed
		end
		r = r .. ' <span class="p-note note listing-content">' .. t .. '</span>'
	end

	r = r .. vc.formatText( 'hours', 'p-note note listing-hours' )
	r = r .. vc.formatText( 'checkin', 'listing-checkin' )
	r = r .. vc.formatText( 'checkout', 'listing-checkout' )
	r = r .. vc.formatText( 'price', 'p-note note listing-price' )
	r = r .. vc.formatText( 'credit-cards', 'p-note note listing-credit' )
	if ParMap['credit-cards'] ~= '' then errorMsgs = errorMsgs .. ms.errorMsg.creditUsed end


	if arrShow.subtype then
		t = ''
		for key, value in pairs( arrSubtype ) do
			s = vs[key]
			if s and (type( s ) == 'string') then
				t = t .. ' [' .. key .. ']'
			end
		end
		if t ~= '' then r = r .. ' <span class="listing-subtype">'
			.. ms.texts.subtype .. ' ' .. t .. '.</span>' end
	end

	if ParMap.unesco ~= '' then
		r = r .. ' <span class="listing-unesco">' .. ms.icons.unesco .. un.getArticleFromWD()
			.. '|' .. ms.texts.unesco .. ']]</span>'
	end

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

	if ParMap.lastedit ~='' then
		local success;
		success, t = pcall( vc.formatDate, ParMap.lastedit, 'M Y' )
		if not success then
        	t = ms.errorMsg.wrongDate
        end
		r = r .. ' <span class="listing-metadata">(<span class="listing-metadata-items listing-lastedit">'
			.. ms.texts.lastedit .. ' ' .. t
			.. '</span>)</span>'
	else
		r = r .. '<span class="listing-metadata listing-metadata-items>&nbsp;</span>'
	end

	r = mw.ustring.gsub( r, '(%.%.)', '.' )
	r = mw.ustring.gsub( r, '(%.</span>%.)', '</span>.' )
	r = mw.ustring.gsub( r, '(%.</span></span>%.)', '</span></span>.' )
	
	if r == '' then r = leading else r = leading .. period .. r end

	-- wrapping tag

	if arrShow.inline then r = r .. '</span>'
		else r = r .. '</div>' end

	if ParMap.wikidata ~= '' then errorMsgs = errorMsgs .. ms.errorMsg.wikidata end
	if wrongQualifier then errorMsgs = errorMsgs .. '<span class="error">'
		.. ms.errorMsg.wrongQualifier .. '</span>' end
	if cntrl then errorMsgs = errorMsgs .. '<span class="listing-error">'
		.. ms.errorMsg.illegalCtrls .. '</span>' end

	local ns = mw.title.getCurrentTitle().namespace
	if (ns == 0) or (ns == 828) then
		return r .. errorMsgs
	else return r end
end

return vc