Vikivojaĝo
eowikivoyage
https://eo.wikivoyage.org/wiki/Vikivoja%C4%9Do:%C4%88efpa%C4%9Do
MediaWiki 1.47.0-wmf.21
first-letter
Aŭdvidaĵo
Specialaĵo
Diskuto
Uzanto
Uzanto-Diskuto
Vikivojaĝo
Vikivojaĝo-Diskuto
Dosiero
Dosiero-Diskuto
MediaWiki
MediaWiki-Diskuto
Ŝablono
Ŝablono-Diskuto
Helpo
Helpo-Diskuto
Kategorio
Kategorio-Diskuto
TimedText
TimedText talk
Modulo
Modulo-Diskuto
Event
Event talk
Modulo:VCard
828
4800
73250
72508
2026-09-24T10:48:20Z
RolandUnger
168
Update
73250
Scribunto
text/plain
-- module variable and administration
local vc = {
moduleInterface = {
suite = 'vCard',
serial = '2026-09-23',
item = 58187507
},
-- table containing parameters fetched from Wikidata
fromWD = {},
-- Wikidata to subtype table
subtypeIds = nil,
-- complete subtype table including Wikidata subtypes
subtypes = {}
}
-- module import
-- require( 'strict' )
local mi = require( 'Module:Marker utilities/i18n' )
local mu = require( 'Module:Marker utilities' )
local vp = require( 'Module:VCard/Params' ) -- parameter lists
local vi = require( 'Module:VCard/i18n' ) -- parameter translations
local vq = mw.loadData( 'Module:VCard/Qualifiers' ) -- comment tables
local cm = require( 'Module:CountryData' )
local er -- modules will be loaded later if needed
local hi
local hr
local lg
local lp = require( 'Module:LinkPhone' )
local vs
local wu = require( 'Module:Wikidata utilities' )
local function addWdClass( key )
return mu.addWdClass( vc.fromWD[ key ] )
end
local function forceFetchFromWikidata( tab )
for key, value in pairs( tab ) do
vp.ParMap[ key ] = true
end
end
-- copying frameArgs parameters to args = vp.ParMap parameters
local function copyParameters( args, show )
-- force getting data from Wikidata for missing parameters
show.inlineDescription = true -- description with div or span tag
if vp.ParMap.auto == true then
forceFetchFromWikidata( vp.ParWD )
forceFetchFromWikidata( vp.ParWDAdd )
end
-- copying args parameters to vp.ParMap parameters
local t, value
local exclude = { auto = 1, show = 1, wikidata = 1 }
for key, v in pairs( vi.p ) do
value = args[ key ]
if value then
value, t =
mu.removeCtrls( value, show.inline or key ~= 'description' )
if t then
show.inlineDescription = false
end
if vp.ParWD[ key ] then
if value == '' then
value = 'y'
end
t = mu.yesno( value )
if t then
if vp.ParMap.wikidata ~= '' then
vp.ParMap[ key ] = t == 'y'
else
vp.ParMap[ key ] = ''
end
else
vp.ParMap[ key ] = value
end
elseif not exclude[ key ] then
vp.ParMap[ key ] = value
end
end
end
return vp.ParMap
end
-- checking subtypes
local function checkSubtypes( args, subtypesTable )
if not mu.isSet( args.subtype ) then
return {}
end
local function aliasToSubtype( alias )
if not vc.subtypeAliases then -- alias to subtype table
vc.subtypeAliases = mu.getAliases( subtypesTable, 'alias' )
end
return vc.subtypeAliases[ alias ]
end
local function subtypeExists( subtype )
return subtypesTable[ subtype ] and subtype or aliasToSubtype( subtype )
end
local subtypes = {}
local invalidSubtypes = {}
for subtype, v in pairs( mu.split( args.subtype ) ) do
local count = ''
local invalidCount = false
local item = subtype
-- split item from count
local at = item:find( ':', 1, true )
if at then
count = tonumber( item:sub( at + 1, #item ) ) or ''
item = mw.text.trim( item:sub( 1, at - 1 ) )
if count == '' then
invalidCount = true -- ':' without count or not a number
else
count = math.floor( count )
if count < 2 then
count = ''
end
end
end
item = subtypeExists( item ) or mu.typeExists( item )
if item then
subtypes[ item ] = count
end
if invalidCount or not item then
table.insert( invalidSubtypes, subtype )
end
end
if #invalidSubtypes > 0 then
mu.addMaintenance( 'unknownSubtype', table.concat( invalidSubtypes, mu.commaSeparator ) )
end
return subtypes
end
local function initialParametersCheck( frame, page )
local country, email, entity, show, t, v, web, wrongQualifier
local frameArgs = mu.checkArguments( frame:getParent().args, vi.p )
-- Using wu.getEntity instead of wu.getEntityId brings a better overall performance
vp.ParMap.wikidata, entity, wrongQualifier = wu.getEntity( frameArgs.wikidata or '' )
if wrongQualifier then
mu.addMaintenance( 'wrongQualifier' )
end
vp.ParMap.auto = false
if mu.isSet( vp.ParMap.wikidata ) then
vp.ParMap.auto = vi.options.defaultAuto
v = mu.yesno( frameArgs.auto or '' )
if v then
vp.ParMap.auto = v == 'y'
end
mu.addMaintenance( 'wikidata' )
end
-- making phone number table
t = {}
for i, key in ipairs( vp.phones ) do
mu.tableInsert( t, frameArgs[ key ] )
end
-- making web addresses table
web = {}
mu.tableInsert( web, frameArgs.url )
email = ( frameArgs.email or '' ):gsub( ',.*$', '' ) -- first email
mu.tableInsert( web, email )
-- getting country-specific technical parameters
country = cm.getCountryData( entity, t, frameArgs.country, vp.ParMap.wikidata, web )
if country.fromWD then
mu.addMaintenance( 'countryFromWD' )
end
if country.unknownCountry then
mu.addMaintenance( 'unknownCountry' )
end
if country.cc ~= '' then
country.trunkPrefix = lp.getTrunkPrefix( country.cc )
end
-- for map support
country.extra = mi.map.defaultSiteType
if mu.isSet( country.iso_3166 ) then
country.extra = country.extra .. '_region:' .. country.iso_3166
end
-- country-specific default show
if mu.isSet( country.show ) then
vp.ParMap.show = vp.ParMap.show .. ',' .. country.show
end
show = mu.getShow( vp.ParMap.show, frameArgs, vp.show )
-- copying frameArgs parameters to args = vp.ParMap parameters
local args = copyParameters( frameArgs, show )
-- alternate local language
if mu.isSet( args.localLang ) then
args.localLang = args.localLang:lower()
if args.localLang ~= country.lang then
lg = lg or require( 'Module:Languages' )
if lg.lngProps[ args.localLang ] then
cm.setLanguageParams( args.localLang, page.lang, country )
else
args.localLang = ''
mu.addMaintenance( 'unknownLanguage' )
end
end
end
mu.checkStatus( args )
mu.checkStyles( args )
-- checking coordinates and converting DMS to decimal coordinates if necessary
mu.checkCoordinates( args )
mu.checkZoom( args )
-- remove namespace from category
mu.checkCommonsCategory( args )
mu.checkId( args )
for i, param in ipairs( mi.options.parameters ) do
if mu.isSet( args[ param ] ) then
mu.addMaintenance( 'parameterUsed', param )
end
end
args.subtypeAdd = mu.isSet( args.wikidata ) and args.auto
-- getting features manually entered
if mu.isSet( args.subtype ) then
vs = require( 'Module:VCard/Subtypes' )
vc.subtypes = checkSubtypes( args, vs.f )
if mu.isSet( args.wikidata ) then
-- y = fetch additional features from Wikidata
if vc.subtypes.y then
args.subtypeAdd = true
-- n = do not show subtypes fetched from Wikidata
elseif vc.subtypes.n then
args.subtypeAdd = false
end
end
end
if type( args.lastedit ) == 'string' and args.lastedit ~= ''
and not args.lastedit:match( mi.dates.yyyymmdd.p ) then
mu.addMaintenance( 'wrongDate' )
args.lastedit = ''
end
-- check Google Maps customer id
if type( args.googlemaps ) == 'string' and mu.isSet( args.googlemaps ) and
not ( mu.checkLength( args.googlemaps, 14, 20 ) and args.googlemaps:match( '^[1-9]%d+$' ) ) then
mu.addMaintenance( 'wrongGoogleCid' )
args.googlemaps = ''
end
if type( args.googlemaps ) == 'string' and mu.isSet( args.googlemaps ) then
mu.addMaintenance( 'parameterUsed', 'google-maps' )
if mu.isSet( args.wikidata ) then
mu.addMaintenance( 'wdWithGoogleCid' )
end
end
return args, entity, show, country
end
local function getQuantity( value, page )
if type( value ) == 'number' then
return tostring( value )
elseif value.amount == '0' then
return '0'
else
local a = mu.formatNumber( value.amount )
local u = ''
local unitId = value.unit
local unit = cm.getCurrency( unitId )
if mu.isSet( unit ) then
if unit.mul then
a = mu.formatNumber( string.format( '%.2f', -- 2 decimal places
tonumber( value.amount ) * unit.mul ) )
end
if mi.noCurrencyConversion.all or mi.noCurrencyConversion[ unit.iso ] then
unit = mu.makeSpan( cm.getCurrencyFormatter( unitId ),
'voy-currency voy-currency-' .. unit.iso:lower() )
else
er = er or require( 'Module:Exchange rate' )
unit = er.getWrapper( a, unit.iso, '', 2, cm.getCurrencyFormatter )
mu.addMaintenance( 'currencyTooltip' )
end
else
unit = vq.labels[ unitId ]
end
if unit and unit:find( '%s', 1, true ) then
a = mw.ustring.format( unit, a )
elseif unit then
u = unit
elseif mw.wikibase.isValidEntityId( unitId ) then
-- currency code
u = wu.getValue( unitId, mi.properties.iso4217 )
if u == '' then
-- unit symbol
u = wu.getValuesByLang( unitId, mi.properties.unitSymbol, 1,
page.lang )
u = u[ 1 ] or ''
end
if u ~= '' then
mu.addMaintenance( 'unitFromWD' )
else
u = unitId
mu.addMaintenance( 'unknownUnit' )
end
end
return ( u ~= '' ) and a .. ' ' .. u or a
end
end
local function getHourModules()
if not hr then
hi = require( 'Module:Hours/i18n' )
hr = require( 'Module:Hours' )
end
end
local function getLabel( id )
local label = id
local tables = { vq.labels }
if hi then
table.insert( tables, hi.dateIds )
end
if type( id ) == 'string' and id:match( '^Q%d+$' ) then
for i, tab in ipairs( tables ) do
if type( tab[ id ] ) == 'string' then
label = tab[ id ]
break
end
end
if label == '' then
return label
elseif label == id then
label = mu.getTypeLabel( id )
end
if label == '' or label == id then
label = wu.getLabel( id ) or ''
if label == '' then
mu.addMaintenance( 'unknownLabel' )
else
mu.addMaintenance( 'labelFromWD' )
end
end
end
return label
end
local function removeStringDuplicates( ar )
local hash = {}
local result = {}
local val
for i = 1, #ar do
val = ar[ i ]
if not hash[ val ] then
table.insert( result, val )
hash[ val ] = 1
end
end
return result
end
-- getting comments for contacts and prizes from Wikidata using tables
local function getComments( statement, properties, args, page )
local comments = {}
local isMobilephone = false
local minAge, maxAge
for i, property in ipairs( properties ) do
local pType = property .. '-type'
if statement[ property ] then
if property == mi.properties.minimumAge then
minAge = getQuantity( statement[ property ][ 1 ], page )
elseif property == mi.properties.maximumAge then
maxAge = getQuantity( statement[ property ][ 1 ], page )
end
for j, id in ipairs( statement[ property ] ) do
if statement[ pType ] == 'monolingualtext' then
id = id.text
elseif statement[ pType ] == 'time' then
-- getting last date in case of price/fees
id = wu.getDateFromTime( id )
if not mu.isSet( args.asOf ) or args.asOf < id then
args.asOf = id
end
id = ''
elseif type( id ) == 'table' then
id = ''
end
if id == mi.qualifiers.mobilePhone then
isMobilephone = true
else
mu.tableInsert( comments, getLabel( id ) )
end
end
end
end
comments = removeStringDuplicates( comments )
if minAge and maxAge then
mu.tableInsert( comments, mw.ustring.format( mi.texts.fromTo,
minAge:gsub( '(%d+).*', '%1' ), maxAge ) )
elseif minAge then
mu.tableInsert( comments, mw.ustring.format( mi.texts.from, minAge ) )
elseif maxAge then
mu.tableInsert( comments, mw.ustring.format( mi.texts.to, maxAge ) )
end
return table.concat( comments, mu.commaSeparator ), isMobilephone
end
local function getLngProperty( lng, p )
if not mu.isSet( lng ) then
return ''
end
lg = lg or require( 'Module:Languages' )
local item = lg.lngProps[ lng ]
if not item then
local hyphen = lng:find( '-', 1, true )
if hyphen and hyphen > 1 then
item = lg.lngProps[ lng:sub( 1, hyphen - 1 ) ]
end
end
if item then
item = item[ p ]
end
return item or ( p == 'c' and 0 or '' )
end
local function removeTableDuplicates( ar )
local hash = {}
local result = {}
local hashVal
for i, tab in ipairs( ar ) do
hashVal = tab.value .. '#' .. tab.comment
if not hash[ hashVal ] then
table.insert( result, tab )
hash[ hashVal ] = 1
end
end
return result
end
local function mergeComments( ar )
if #ar > 1 then
for i = #ar, 2, -1 do
for j = 1, i - 1, 1 do
if ar[ i ].value == ar[ j ].value and ar[ i ].comment ~= ''
and ar[ j ].comment ~= '' then
ar[ j ].comment = ar[ j ].comment .. '; ' .. ar[ i ].comment
table.remove( ar, i )
break
end
end
end
end
end
local function convertTableWithComment( ar )
for i = 1, #ar, 1 do
if ar[ i ].comment == '' then
ar[ i ] = ar[ i ].value
else
ar[ i ] = ar[ i ].value .. mu.parentheses( ar[ i ].comment )
end
end
end
--[[
properties are defined in Module:vCard/Params
p property or set of properties
f formatter string
c maximum count of results, default = 1
m concat mode (if c > 1), default concat with ', '
v value type,
empty: string value (i.e. default type),
id: string value of an id like Q1234567
idl: string value of the label of an id like Q1234567
il: language-dependent string value
iq: string value with qualifier ids
au: quantity consisting of amount and unit
pau: quantity consisting of amount (for P8733)
vq: string or table value with qualifiers ids and references
l = lang: language dependent
wiki / local: monolingual text by wiki or local language
le = true: use date for lastedit parameter
--]]
-- function returns an array in any case
local function getWikidataValues( args, propDef, entity, page, country )
local ar = {}
local a, isMobilephone, item, id, langs, q, u
-- setting defaults
propDef.v = propDef.v or ''
propDef.f = propDef.f or ''
propDef.c = propDef.c or 1
-- getting value arrays
if propDef.l == 'wiki' then
ar = wu.getValuesByLang( entity, propDef.p, propDef.c, page.lang )
elseif propDef.l == 'local' then
ar = wu.getValuesByLang( entity, propDef.p, propDef.c, country.lang )
elseif propDef.l == 'lang' and propDef.c == 1 then
id = getLngProperty( country.lang, 'q' )
if id == '' then
country.unknownLanguage = true
else
-- using language of work or name ( page.lang, mi.langs, country.lang )
a = wu.getValuesByQualifier( entity, propDef.p, mi.properties.languageOfName, id )
if next( a ) then
langs = mu.getLangTable( page.lang, country.lang )
for i, lang in ipairs( langs ) do
item = a[ getLngProperty( lang, 'q' ) ]
if item then
break
end
end
ar = { item or a[ next( a, nil ) ] } -- fallback: first item
end
end
elseif propDef.v == 'iq' or propDef.v == 'iqa' or propDef.v == 'iqp'
or propDef.v == 'iqu' then
q = mi.propTable.quantity
if propDef.v == 'iqa' then
q = mi.propTable.accessQuantity
elseif propDef.v == 'iqp' then
q = mi.propTable.policyComments
elseif propDef.v == 'iqu' then
q = mi.propTable.unescoPartOf
end
ar = wu.getValuesWithQualifiers( entity, propDef.p, propDef.q, q,
{ mi.properties.retrieved }, propDef.c )
if propDef.le then
args.lastedit = wu.getLastedit( args.lastedit, ar )
end
elseif propDef.v == 'au' or propDef.v == 'vq' then
q = propDef.v == 'au' and mi.propTable.feeComments or
mi.propTable.contactComments
ar = wu.getValuesWithQualifiers( entity, propDef.p, nil, q,
{ mi.properties.retrieved }, propDef.c )
-- maybe a change of nil to a properties table is useful
if propDef.le then
args.lastedit = wu.getLastedit( args.lastedit, ar )
end
else
ar = wu.getValues( entity, propDef.p, propDef.c )
end
if #ar == 0 and propDef.p ~= mi.properties.instanceOf then
return ar
end
for i = #ar, 1, -1 do
-- amount with unit (for fees)
if propDef.v == 'au' then
a = getQuantity( ar[ i ].value, page )
if a == '0' then
a = vq.labels.gratis
end
u = getComments( ar[ i ], mi.propTable.feeComments, args, page )
ar[ i ] = { value = a, comment = u }
-- for number of rooms P8733
elseif propDef.v == 'pau' then
if ar[ i ].unit == '1' then
a = tonumber( ar[ i ].amount ) or 0
else
a = 0
end
ar[ i ] = {}
ar[ i ][ mi.properties.quantity ] = { a }
ar[ i ][ mi.properties.quantity .. '-type' ] = 'quantity'
ar[ i ].value = mi.qualifiers.roomNumber
ar[ i ]['value-type'] = 'wikibase-entityid'
-- qualifier ids (for subtypes)
elseif propDef.v == 'iq' or propDef.v == 'iqa' or propDef.v == 'iqp'
or propDef.v == 'iqu' then
if ar[ i ][ 'value-type' ] ~= 'wikibase-entityid' then
table.remove( ar, i )
end
if propDef.v == 'iqu' then
if ar[ i ][ mi.properties.partOf ] then
ar[ i ] = ar[ i ][ mi.properties.partOf ][ 1 ]
else
ar[ i ] = mi.qualifiers.unescoHeritage
end
end
if propDef.v == 'iqa' then
ar[ i ].policyComment =
getComments( ar[ i ], mi.propTable.accessibility, args, page )
end
if propDef.v == 'iqp' then
ar[ i ].policyComment =
getComments( ar[ i ], mi.propTable.policyComments, args, page )
end
-- strings with qualifiers (for contacts)
elseif propDef.v == 'vq' then
if ar[ i ][ 'value-type' ] ~= 'string' then
table.remove( ar, i )
else
u, isMobilephone =
getComments( ar[ i ], mi.propTable.contactComments, args, page )
if vi.options.useMobile and propDef.t then
if ( isMobilephone and propDef.t == 'mobile' ) or
( not isMobilephone and propDef.t == 'landline' ) then
ar[ i ] = { value = ar[ i ].value, comment = u }
else
table.remove( ar, i )
end
else
ar[ i ] = { value = ar[ i ].value, comment = u }
end
end
-- value, monolingual text, identifier
else
if propDef.v == 'id' then
ar[ i ] = ar[ i ].id
elseif propDef.v == 'idl' then
getHourModules()
ar[ i ] = hr.formatTime( getLabel( ar[ i ].id ) )
end
if ar[ i ] ~= '' and propDef.f ~= '' then
ar[ i ] = mw.ustring.format( propDef.f, ar[ i ] )
end
end
if propDef.v == 'au' or propDef.v == 'vq' then
if ar[ i ] and ar[ i ].value == '' then
table.remove( ar, i )
end
else
if ar[ i ] == '' then
table.remove( ar, i )
end
end
end
-- cleanup
if propDef.v == 'au' or propDef.v == 'vq' then
ar = removeTableDuplicates( ar )
mergeComments( ar )
convertTableWithComment( ar )
else
ar = removeStringDuplicates( ar )
end
return ar
end
local function getWikidataItem( args, parWDitem, entity, page, country )
local arr = {}
local function singleProperty( propDef )
if #arr == 0 then
arr = getWikidataValues( args, propDef, entity, page, country )
else
for i, value in ipairs( getWikidataValues( args, propDef, entity, page, country ) ) do
table.insert( arr, value ) -- copy to arr
end
end
end
local p = parWDitem
if not p or not p.p then
return ''
end
p.c = p.c or 1 -- count
local tp = type( p.p )
if tp == 'string' then
singleProperty( p )
elseif tp == 'table' then
for i, sngl in ipairs( p.p ) do
if type( sngl ) == 'table' then
singleProperty( sngl )
if p.c == 1 and #arr > 0 then
break
end
end
end
end
if #arr > p.c then
for i = #arr, p.c + 1, -1 do -- delete supernumerary values
table.remove( arr, i )
end
end
if p.m == 'no' then
return arr
else
return table.concat( arr, p.m or mu.commaSeparator )
end
end
local function getAddressesFromWikidata( args, page, country, entity )
local addresses
-- getting addresses from Wikidata but only if necessary
if args.address == true or type( args.addressLocal ) == 'boolean' then
-- P6375: address
addresses = wu.getMonolingualValues( entity, mi.properties.streetAddress )
if next( addresses ) then -- sometimes addresses contain <br> tag(s)
for key, value in pairs( addresses ) do
addresses[ key ] = value:gsub( '</*br%s*/*>', mi.texts.space )
end
else
return
end
else
return
end
local t, w
if args.address == true then
args.address = addresses[ page.lang ]
-- select address if the same writing system is used
if not args.address then
local weight = -1
local u = getLngProperty( page.lang, 'w' ) -- writing entity id
for key, value in pairs( addresses ) do
-- same writing entity id as page.lang
w = getLngProperty( key, 'w' )
if w == '' then
country.unknownPropertyLanguage = true
else
if key and w == u then -- same writing entity id
w = getLngProperty( key, 'c' ) -- getting language weight
if w > weight then -- compare language weight
args.address = value
args.addressLang = key
weight = w
end
end
end
end
end
if not args.address then
for i, lng in ipairs( mi.langs ) do
if addresses[ lng ] then
args.address = addresses[ lng ]
args.addressLang = lng
break
end
end
end
if not args.address then
args.address = ''
args.addressLang = ''
end
vc.fromWD.address = args.address ~= ''
end
-- removing county name from the end of address
-- same with county name in county language and English
if type( args.address ) == 'string' then
args.address = mw.ustring.gsub( args.address,
'[.,;]*%s*' .. country.country .. '$', '' )
end
t = true
for i, lng in ipairs( mi.langs ) do
if country.lang == lng then
t = false
end
end
-- keeping local address in any case for html data
args.addAddressLocal = addresses[ country.lang ] or ''
if t and args.addressLocal == true
and country.lang ~= page.lang then
if country.lang ~= '' then
args.addressLocal = addresses[ country.lang ] or ''
else
-- unknown language, maybe missing in Module:Languages
args.addressLocal = addresses.unknown or ''
end
vc.fromWD.addressLocal = args.addressLocal ~= ''
end
end
local function getDataFromWikidata( args, page, country, entity )
if args.wikidata == '' then
return
end
mu.getTypeFromWikidata( args, entity )
-- prevent local data if wiki language == country language
if country.lang == page.lang then
for i, value in ipairs( vp.localData ) do
if type( args[ value ] ) == 'boolean' then
args[ value ] = ''
end
end
end
mu.getNamesFromWikidata( args, vc.fromWD, page, country, entity )
getAddressesFromWikidata( args, page, country, entity )
if args.hours == true then
local lastEdit
getHourModules()
if not mu.typeIds then
mu.idToType( 'Q1' ) -- dummy call to create mu.typeIds
end
args.hours, lastEdit = hr.getHoursFromWikidata( entity, page.lang,
mi.langs[ 1 ] or '', mi.formats.wikidata, nil, args.lastedit,
vq.labels, { typeTable = mu.types, idTable = mu.typeIds } )
vc.fromWD.hours = args.hours ~= ''
if vi.options.lasteditHours then
args.lastedit = lastEdit
end
end
for key, value in pairs( vp.ParWD ) do
if args[ key ] == true then
args[ key ] =
getWikidataItem( args, vp.ParWD[ key ], entity, page, country )
vc.fromWD[ key ] = args[ key ] ~= ''
end
end
mu.getArticleLink( args, entity, page )
mu.getCommonsCategory( args, entity )
mu.getCoordinatesFromWikidata( args, vc.fromWD, entity )
end
local function checkAddresses( args )
local s
for i, key in ipairs( { 'address', 'addressLocal', 'directions', 'directionsLocal' } ) do
if mu.isSet( args[ key ] ) then
s = args[ key ]
args[ key ] = args[ key ]:gsub( "'''?", '' )
-- addresses shall not contain tags
if key == 'address' or key == 'addressLocal' then
args[ key ] = args[ key ]:gsub( '<[^<>]*>', '' )
:gsub( '[<>]+', '' )
end
if s ~= args[ key ] then
args[ key ] = mw.text.trim( args[ key ] )
mu.addMaintenance( 'malformedAddress' )
end
end
end
end
local function finalParametersCheck( args, show, page, country, defaultType, entity )
-- remove boolean values from parameters to have only strings
for key, value in pairs( args ) do
if type( args[ key ] ) == 'boolean' then
args[ key ] = ''
end
end
-- create givenName, displayName tables
args.langIsWikiLang = country.lang == page.lang
mu.prepareNames( args )
if args.langIsWikiLang and ( mu.isSet( args.addressLocal ) or
mu.isSet( args.directionsLocal ) ) then
args.addressLocal = ''
args.directionsLocal = ''
mu.addMaintenance( 'noLocalParams' )
end
checkAddresses( args )
-- analysing addressLocal vs address
if args.addressLang and args.addressLang == country.lang then
args.addressLocal = ''
args.addAddressLocal = ''
end
if args.addressLocal ~= '' and args.address == '' then
args.address =
mu.languageSpan( args.addressLocal, mi.texts.hintAddress, page, country )
args.addressLocal = ''
args.addAddressLocal = ''
vc.fromWD.address = vc.fromWD.addressLocal
end
show.noCoord = args.lat == '' or args.long == ''
if show.noCoord then
show.coord = nil
show.poi = nil
mu.addMaintenance( 'missingCoordVc' )
else
mu.prepareCoordinates( args )
end
-- getting Marker type, group, and color
if not mu.isSet( args.type ) and mu.isSet( defaultType ) then
args.type = defaultType
end
mu.checkTypeAndGroup( args )
-- image check
if not vc.fromWD.image or mi.options.WDmediaCheck then
mu.checkImage( args, entity )
end
mu.checkUrl( args )
args.commonscat = args.commonscat:gsub( ' ', '_' )
-- add final period if not yet exists
if mu.isSet( args.description ) then
if mw.ustring.match( args.description, '[%w_€$]$' ) then
args.description = args.description .. mi.texts.period
end
if mw.ustring.len( args.description ) > mi.options.contentLimit and
mi.options.groupsWithLimit[ args.group ] then
args.description = mw.ustring.sub( args.description, 1, mi.options.contentLimit ) .. '…'
mu.addMaintenance( 'contentTooLong' )
end
end
end
local function formatText( args, results, key, class )
if not mu.isSet( args[ key ] ) then
return
end
local r
local textKey = key
local period = mi.texts.period
if key == 'hours' then
args[ key ], r = mw.ustring.gsub( args[ key ],
mi.texts.closedPattern, '' )
textKey = ( r > 0 ) and 'closed' or key
end
r = mw.ustring.format( mi.texts[ textKey ], args[ key ] )
r = mw.ustring.gsub( r, '^%a', mw.ustring.upper )
-- add period if not yet exists
r = r .. ( mw.ustring.sub( r, -1 ) == period and '' or period )
table.insert( results, mu.makeSpan( r, class .. addWdClass( key ) ) )
end
local function formatPhone( args, key, country )
if not mu.isSet( args[ key ] ) then
return ''
end
local class
local pArgs = {
phone = args[ key ],
cc = country.cc,
isFax = false,
isTollfree = false,
format = false
}
if vc.fromWD[ key ] then
pArgs.format = true
pArgs.size = country.phoneDigits or 2
end
if key == 'fax' then
class = 'voy-listing-fax p-tel-fax fax' .. addWdClass( key )
pArgs.isFax = true
else
class = 'p-tel tel' .. addWdClass( key )
if key == 'tollfree' then
class = 'voy-listing-tollfree ' .. class
pArgs.isTollfree = true
elseif key == 'mobile' then
class = 'voy-listing-mobile ' .. class
else
class = 'voy-listing-phone ' .. class
end
end
return mw.ustring.format( mi.texts[ key ],
mu.makeSpan( lp.linkPhoneNumbers( pArgs ), class ) )
end
local function formatDate( aDate, aFormat )
return mw.getContentLanguage():formatDate( aFormat, aDate, true )
end
local function removePeriods( s )
local period = mi.texts.period
local _period = '%' .. period
-- closing (span) tags between full stops
return s:gsub( _period .. '+(</[%l<>/]+>)' .. _period .. '+', '%1' .. period )
:gsub( _period .. _period .. '+', period )
end
local function makeMarkerAndName( args, show, page, country, frame )
local result = {}
-- adding status icons
mu.tableInsert( result, mu.makeStatusIcons( args ) )
-- adding POI marker
if show.poi or mu.isSet( args.copyMarker ) then
table.insert( result, mu.makeMarkerSymbol( args, show, frame ) )
end
mu.makeName( result, args, show, page, country, addWdClass( 'name' ),
addWdClass( 'nameLocal' ) )
if #result > 0 then
result = { table.concat( result, mi.texts.space ) }
end
if args.before ~= '' then
table.insert( result, 1, mu.makeSpan( args.before, 'voy-listing-before' ) )
end
return table.concat( result, mi.texts.space )
end
local function makeEvent( args, page )
local isEvent = false
local s = {}
local count = 0 -- counts from-to statements
local startMonth -- month of start date
local today = page.langObj:formatDate( 'Y-m-d', 'now', true )
local todayYear = today:sub( 1, 4 ) -- yyyy
local todayMonth = today:sub( 6, 7 ) -- mm
local lastDate = ''
local lastYear = ''
local useYMD -- both dates are yyyy-mm-dd
local function makePeriod( beginP, endP )
if beginP == endP then
endP = ''
end
if mu.isSet( beginP ) and mu.isSet( endP ) then
count = count + 1
return mw.ustring.format( mi.texts.fromTo2, beginP, endP )
elseif mu.isSet( beginP ) then
return beginP
else
return endP
end
end
local function analyseDate( d, m, y )
local success, c, t
if useYMD then
success, t = pcall( formatDate, d, mi.dates.yyyymmdd.f )
if success then
success, c = pcall( formatDate, d, 'Y-m-d' )
end
if success then
lastDate = c > lastDate and c or lastDate
d = t
end
return d, nil
end
if d:match( mi.dates.yyyymmdd.p ) then
y = d:sub( 1, 4 )
d = d:sub( 6 )
end
if mu.isSet( y ) then
if y:match( mi.dates.yy.p ) then
y = ( '2000' ):sub( -#y ) .. y
elseif not y:match( mi.dates.yyyy.p ) then
y = nil
end
lastYear = y > lastYear and y or lastYear
end
if mu.isSet( d ) and mu.isSet( m ) and d:match( mi.dates.dd.p ) and
not m:match( mi.dates.mm.p ) then
-- try to convert month to number string
success, t = pcall( formatDate, m, 'm' )
if success then
m = t
else
for i = 1, 12, 1 do
if m == mi.months[ i ] or mw.ustring.match( m, mi.monthAbbr[ i ] ) then
m = '' .. i
break
end
end
end
end
if mu.isSet( d ) and mu.isSet( m ) and d:match( mi.dates.dd.p ) and
m:match( mi.dates.mm.p ) then
d = m:gsub( '%.+$', '' ) .. '-' .. d:gsub( '%.+$', '' )
m = nil
elseif mu.isSet( d ) and not mu.isSet( m ) and d:match( mi.dates.dd.p ) then
d = ( startMonth or todayMonth ) .. '-' .. d:gsub( '%.+$', '' )
end
if mu.isSet( d ) then
if d:match( mi.dates.mmdd.p ) then
startMonth = d:gsub( '%-%d+', '' )
m = nil
c = ( y or todayYear ) .. '-' .. d
success, t = pcall( formatDate, c, mi.dates.mmdd.f )
if success then
d = t
end
elseif d:match( mi.dates.dd.p ) and not mu.isSet( m ) and startMonth then
c = ( y or todayYear ) .. '-' .. startMonth .. '-' .. d
success, t = pcall( formatDate, c, mi.dates.mmdd.f )
if success then
d = t
end
end
end
if mu.isSet( m ) then
d = ( mu.isSet( d ) and ( d .. mi.texts.space ) or '' ) .. m
end
return d, y
end
if not mu.groupWithEvents( args.group ) then
return ''
end
-- check if vCard is an event
for i, param in ipairs( vp.checkEvent ) do
if mu.isSet( args[ param ] ) then
isEvent = true
break
end
end
if not isEvent then
return ''
end
if mu.isSet( args.frequency ) then
table.insert( s, mu.makeSpan( args.frequency, 'voy-listing-frequency' ) )
else
if args.date:match( mi.dates.yyyymmdd.p ) and
args.endDate:match( mi.dates.yyyymmdd.p ) then
useYMD = true
if args.date > args.endDate then
args.date, args.endDate = args.endDate, args.date
end
end
args.date, args.year
= analyseDate( args.date, args.month, args.year )
args.endDate, args.endYear
= analyseDate( args.endDate, args.endMonth, args.endYear )
local d = {}
mu.tableInsert( d, makePeriod( args.date, args.endDate ) )
mu.tableInsert( d, makePeriod( args.year, args.endYear ) )
mu.tableInsert( s, mu.makeSpan( table.concat( d, count > 1 and
mu.commaSeparator or mi.texts.space ), 'voy-listing-date' ) )
if ( lastYear ~= '' and lastYear < todayYear ) or
( lastDate ~= '' and lastDate < today ) then
mu.addMaintenance( 'outdated' )
end
end
if mu.isSet( args.location ) then
local locations = mu.textSplit( args.location, ',' )
for i, location in ipairs( locations ) do
if location ~= page.subpageText and location ~= page.text
and mw.title.new( location, '' ).exists then
location = mu.makeSpan( '[[' .. location .. ']]', 'voy-listing-location' )
end
table.insert( s, location )
end
end
s = table.concat( s, mu.commaSeparator )
return ( s ~= '' and ': ' or '' ) .. s
end
local function makeAddressAndDirections( args, page, country )
local r = ''
local p, t
if mu.isSet( args.address ) then
p = {}
if mu.isSet( args.addressLang ) then
p.lang = args.addressLang
t = mw.language.fetchLanguageName( args.addressLang, page.lang )
if mu.isSet( t ) then
p.title = mw.ustring.format( mi.texts.hintAddress, t )
else
country.unknownPropertyLanguage = true
end
end
r = mu.commaSeparator .. mu.makeSpan( args.address,
'voy-listing-address p-adr adr' .. addWdClass( 'address' ), true, p )
end
if mi.options.showLocalData and mu.isSet( args.addressLocal ) then
r = r .. mu.comma .. mu.languageSpan( args.addressLocal, mi.texts.hintAddress,
page, country, 'voy-listing-address-local' .. addWdClass( 'addressLocal' ) )
end
t = {}
if mu.isSet( args.directions ) then
table.insert( t, mu.makeSpan( args.directions,
'voy-listing-directions' .. addWdClass( 'directions' ) ) )
end
if mi.options.showLocalData and mu.isSet( args.directionsLocal ) then
table.insert( t, mu.languageSpan( args.directionsLocal,
mi.texts.hintDirections, page, country,
'voy-listing-directions-local' .. addWdClass( 'directionsLocal' ) ) )
end
if #t == 0 then
return r
end
return r .. mi.texts.space .. mu.makeSpan( mu.parentheses( table.concat( t, mu.comma ), true ),
'voy-listing-add-address' )
end
local function makeContacts( args, country )
local t = {}
local s
mu.tableInsert( t, formatPhone( args, 'phone', country ) )
mu.tableInsert( t, formatPhone( args, 'tollfree', country ) )
mu.tableInsert( t, formatPhone( args, 'mobile', country ) )
mu.tableInsert( t, formatPhone( args, 'fax', country ) )
if args.email ~= '' then
local lm = require( 'Module:LinkMail' )
s = mu.makeSpan( lm.linkMailSet( { email = args.email, ignoreUnicode = 1 } ),
'voy-listing-email u-email email' .. addWdClass( 'email' ) )
mu.tableInsert( t, mw.ustring.format( mi.texts.email, s ) )
end
s = table.concat( t, mu.commaSeparator )
if s ~= '' then
-- mi.texts.periodSeparator = '. '
s = mi.texts.periodSeparator .. mw.ustring.gsub( s, '^%a', mw.ustring.upper )
end
return s
end
-- making subtypes string
local function makeFeatures( args, tab )
vs = vs or require( 'Module:VCard/Subtypes' )
local function getSubtypeParams( subtype )
local r = vs.f[ subtype ] or mu.getTypeParams( subtype )
if not r.n then
r.n = r.label or subtype
end
r.g = r.g or vs.fromTypesGroupNumber
return r
end
vc.fromWD.subtypeAdd = type( args.subtypeAdd ) == 'table' and #args.subtypeAdd > 0
-- merging subtypeAdd (from Wikidata) to manually entered subtypes
local unknowWDfeatures = false
local label, p, t
if vc.fromWD.subtypeAdd then
-- making translation table from Wikidata ids to feature types
if not vc.subtypeIds then
vc.subtypeIds = mu.getAliases( vs.f, 'wd' )
end
-- adding type if Wikidata id (wd.value) is known
-- indexed array prevents multiple identical types
for i, wd in ipairs( args.subtypeAdd ) do
t = vc.subtypeIds[ wd.value ] or mu.idToType( wd.value )
if not t then
-- maybe instance or subclass of wd.value are known
local p31ids = wu.getIds( wd.value, mi.properties.instanceOf )
local p279ids = wu.getIds( wd.value, mi.properties.subclassOf )
-- merging both arrays
for j = 1, #p279ids, 1 do
table.insert( p31ids, p279ids[ j ] )
end
for j = 1, #p31ids, 1 do
t = vc.subtypeIds[ p31ids[ j ] ] or mu.idToType( p31ids[ j ] )
if t then
break
end
end
end
-- subtype from WD is not known
if not t and not vs.exclude[ wd.value ] then
unknowWDfeatures = true
-- try to add a new subtype Q... to vs.f subtypes table
label = wu.getLabel( wd.value )
if label then
vs.f[ wd.value ] = {
n = label,
wd = wd.value,
g = vs.fromWDGroupNumber
}
t = wd.value
end
end
-- add known subtype
if t then
vc.subtypes[ t ] = {
c = ( wd[ mi.properties.quantity ]
and wd[ mi.properties.quantity ][ 1 ] )
or ( wd[ mi.properties.capacity ] and
wd[ mi.properties.capacity ][ 1 ] ) or '',
p = wd.policyComment
}
end
end
end
if unknowWDfeatures then
mu.addMaintenance( 'unknowWDfeatures' )
end
if next( vc.subtypes ) == nil and #args.subtypeTable == 0 then
return
end
-- replace selected subtypes
for subtype, count in pairs( vc.subtypes ) do
if vs.convert[ subtype ] then
if type( count ) == 'table' then
p = count.p
count = count.c
end
t = vs.convert[ subtype ][ count ] or vs.convert[ subtype ][ 1 ]
vc.subtypes[ t ] = { p = p }
vc.subtypes[ subtype ] = nil
end
end
-- make subtypes table sortable
local s = {};
for subtype, count in pairs( vc.subtypes ) do
if type( count ) == 'table' then
table.insert( s, { t = subtype, c = count.c, p = count.p } )
else
table.insert( s, { t = subtype, c = count } )
end
end
-- add subtypes from types table
if args.subtypeTable then
for i, subtype in ipairs( args.subtypeTable ) do
table.insert( s, { t = subtype, c = 1 } )
end
end
-- sorting subtypes
-- by subtype group and then alphabetically by name
table.sort( s,
function( a, b )
local at = getSubtypeParams( a.t )
local bt = getSubtypeParams( b.t )
local na = mu.convertForSort( at.n )
local nb = mu.convertForSort( bt.n )
return ( at.g < bt.g ) or ( at.g == bt.g and na < nb )
end
)
-- make text and data output
local data = {} -- for data-subtype attribute in wrapper tag
if #s > 0 then
local r = {};
local subtype, f, u, u_n, v
for i = 1, #s do
subtype = s[ i ]
-- for data-subtype="..." in wrapper tag
u = subtype.t .. ',' .. tostring( i )
if type( subtype.c ) == 'number' and subtype.c > 1 then
u = u .. ',' .. subtype.c
end
table.insert( data, u )
u = getSubtypeParams( subtype.t )
if u.g >= vs.firstGroup then
u_n = u.n
if not mu.isSet( u_n ) then
u_n = subtype.t
end
u_n = u_n:gsub( '[,;/].*$', '' )
local count = ( type( subtype.c ) == 'number' ) and subtype.c or 1
if count > 1 and u_n:find( '%[[^%[%]]*%]' ) then
v = mw.ustring.format( mi.texts.subtypeWithCount, subtype.c,
u_n:gsub( '%[([^%[%]]*)|([^%[%]]*)%]', '%1' )
:gsub( '%[([^%[%]]*)%]', '%1' ) )
else
v = u_n:gsub( '%[([^%[%]]*)|([^%[%]]*)%]', '%2' )
:gsub( '%[([^%[%]]*)%]', '' )
end
if mu.isSet( u.t ) then -- string tooltip
v = mw.ustring.format( mi.texts.subtypeSpan, u.t, v )
elseif mu.isSet( u.f ) then -- icons
f = mw.ustring.format( mi.texts.subtypeFile, u.f, v )
if u.c then
f = mw.ustring.rep( f, u.c )
end
v = mw.ustring.format( mi.texts.subtypeAbbr, v, f )
end
-- adding policy comment
if subtype.p and subtype.p ~= '' then
v = v .. mu.parentheses( subtype.p )
end
end
table.insert( r, v )
end
if #r > 0 then
r = #r == 1 and mw.ustring.format( mi.texts.subtype, r[ 1 ] )
or mw.ustring.format( mi.texts.subtypes, table.concat( r, mu.commaSeparator ) )
if r ~= '' then
table.insert( tab, mu.makeSpan( r,
'voy-listing-subtype' .. addWdClass( 'subtypeAdd' ) ) )
end
end
end
-- subtype contains now the value for wrapper tag
args.subtype = table.concat( data, ';' )
end
local function makePayment( args, results )
if not mu.isSet( args.payment ) then
return
end
local t
local class = 'voy-listing-payment p-note note'
if type( args.payment ) == 'table' then
local vr = mw.loadData( 'Module:VCard/Cards')
for i = #args.payment, 1, -1 do -- remove unknown items
t = args.payment[ i ]
if vr.cards[ t ] then
args.payment[ i ] = vr.cards[ t ]
else
table.remove( args.payment, i )
end
end
class = class .. mu.addWdClass( #args.payment > 0 )
args.payment = table.concat( args.payment, mu.commaSeparator )
else
mu.addMaintenance( 'paymentUsed' )
end
formatText( args, results, 'payment', class )
end
local function wrapDescription( args, tab, isInline, addText )
if args.description ~= '' then
table.insert( tab, tostring( mw.html.create( isInline and 'span' or 'div' )
:addClass( 'voy-listing-content p-note note' )
:wikitext( args.description .. ( addText or '' ) ) )
)
end
end
local function makeMetadata( args, page )
local outdated = false
local t = args.lastedit
if t ~= '' then
local s, success, u
success, t = pcall( formatDate, t, mi.dates.lastedit.f )
if not success then
mu.addMaintenance( 'wrongDate' )
t = ''
else
success, s = pcall( formatDate, args.lastedit, 'U' ) -- UNIX seconds
if success then
success, u = pcall( formatDate, mi.texts.expirationPeriod, 'U' )
end
if success and s < u then
t = t .. mi.texts.space .. mi.texts.maybeOutdated
outdated = true
end
end
end
local tag = mw.html.create( 'span' )
:attr( 'class', 'voy-listing-metadata' )
-- add node to save the parent tag
:node( mw.html.create( 'span' )
:addClass( 'voy-listing-metadata-item voy-listing-lastedit' )
:addClass( outdated and 'voy-listing-outdated' or nil )
:addClass( t == '' and 'voy-listing-item-dummy' or nil )
:wikitext( mw.ustring.format( mi.texts.lastedit,
t == '' and mi.texts.lasteditNone or t ) )
)
if mu.isSet( args.sectionFrom ) then
local from = args.sectionFrom:gsub( '_', ' ' )
if from ~= page.subpageText and from ~= page.text then
if mu.isSet( args.wikidata ) then
from = mw.ustring.format( '%s#' .. mi.texts.anchor, from, args.wikidata )
end
tag:node( mw.html.create( 'span' )
:addClass( 'voy-listing-metadata-item voy-listing-toSourcePage' )
:wikitext( mw.ustring.format( '[[%s|%s]]', from, mi.texts.editInSource ) )
)
end
end
return tostring( tag )
end
-- making description, coordinates, and meta data
local function makeDescription( args, show, page, country, entity )
local results = {}
-- inline description
if show.inlineDescription then
wrapDescription( args, results, true )
end
-- adding features
makeFeatures( args, results )
-- practicalities
formatText( args, results, 'hours', 'voy-listing-hours p-note note' )
formatText( args, results, 'checkin', 'voy-listing-checkin' )
formatText( args, results, 'checkout', 'voy-listing-checkout' )
if mu.isSet( args.asOf ) and mu.isSet( args.price ) then
local success
success, args.asOf = pcall( formatDate, args.asOf, mi.dates.asOf.f )
if success then
args.price = args.price .. mw.ustring.format( mi.texts.asOf, args.asOf )
end
end
formatText( args, results, 'price', 'voy-listing-price p-note note' )
makePayment( args, results )
-- adding Unesco symbol
if args.unesco ~= '' and vi.options.showUnesco then
local uLink, uTitle = require( 'Module:VCard/Unesco' ).getUnescoInfo( country )
table.insert( results, mu.addLinkIcon( 'voy-listing-unesco', uLink,
uTitle, 'unesco' ) )
end
local noContent = #results == 0
-- adding DMS coordinates
if show.coord then
table.insert( results, mu.dmsCoordinates( args, page, country, vc.fromWD.lat ) )
end
if mi.options.showSisters == 'atEnd' then
table.insert( results, mu.makeIcons( args, page, country, entity, show, vc.fromWD ) )
end
local description
local space = mi.texts.space
-- adding description in block mode
if args.description ~= '' and not show.inlineDescription then
-- last edit will be inserted at the end of the div tag
wrapDescription( args, results, false, makeMetadata( args, page ) )
noContent = false
description = table.concat( results, space )
if description ~= '' then
description = space .. description
end
-- adding description in inline mode
else
description = table.concat( results, space )
if description ~= '' then
description = space .. description
end
end
return removePeriods( description ), noContent
end
-- vCard main function
function vc.vCard( frame )
mu.initMaintenance()
local page = mu.getPageData()
-- getting location (vCard/listing) entity, show options and country data
local args, vcEntity, show, country = initialParametersCheck( frame, page )
-- associated Wikivoyage page of the location in current Wikivoyage branch
-- possibly modified by mu.getArticleLink()
args.wikiPage = ''
args.officialName = ''
-- getting data from Wikidata
getDataFromWikidata( args, page, country, vcEntity )
-- final check
local defaultType = frame.args.type
finalParametersCheck( args, show, page, country, defaultType, vcEntity )
-- making output
-- leading part for marker mode: only location names and comment
-- saving address
args.addressOrig = args.address
-- creating text parts
-- leading part (marker and names)
local leading = makeMarkerAndName( args, show, page, country, frame )
.. makeEvent( args, page )
-- additional parts for vCard mode
-- get address and directions
local address = makeAddressAndDirections( args, page, country )
-- get all contact information
local contacts = makeContacts( args, country ) -- all contacts
contacts = removePeriods( address .. contacts )
-- making description, coordinates, and meta data
local description, noContent =
makeDescription( args, show, page, country, vcEntity )
local r = leading
local icons = ''
if contacts == '' and noContent then
show.inline = true
r = r .. mu.makeIcons( args, page, country, vcEntity, show, vc.fromWD ) .. description
else
if type( mi.options.showSisters ) == 'boolean' then
-- could also be 'atEnd', then part of body
icons = mu.makeIcons( args, page, country, vcEntity, show, vc.fromWD )
end
-- mi.texts.periodSeparator = '. '
r = removePeriods( r .. contacts .. icons ..
( show.noperiod and '' or mi.texts.periodSeparator ) .. description )
:gsub( '%)(</span>)%s*(<span [^>]*>)%s*%(', '%1; %2' )
end
-- prevents line break before punctuation mark
r = r:gsub( '</span>([,;.:!?])', '%1</span>' )
-- remove space(s) before punctuation marks
:gsub( '%s+(<span [^>]*>[,;.:!?])', '%1' )
if show.inlineDescription then
r = r:gsub( '%s+$', '' ) .. makeMetadata( args, page )
end
-- error handling and maintenance, not in template and module namespaces
if country.unknownLanguage then
mu.addMaintenance( 'unknownLanguage' )
end
if country.unknownPropertyLanguage then
mu.addMaintenance( 'unknownPropertyLanguage' )
end
r = r .. mu.makeMaintenance( page, { wu, mu, cm, hr } )
-- wrapping tag
args.address = args.addressOrig
args.template = 'vCard'
return mu.makeWrapper( r, args, page, country, show, vp.vcardData, frame )
end
return vc
capbzxso4856qlp2fujjwky0am17f0k
Modulo:VCard/Params
828
4802
73247
72148
2026-09-24T10:44:40Z
RolandUnger
168
Update
73247
Scribunto
text/plain
--[[
This module contains the parameter tables and definitions. Do not modify this
module. The translated values are stored in Module:vCard/i18n.
Not all parameters given in the ParMap table can be used by authors. They are
only for internal usage and will not be shown in the output (for instance
booking). Parameters for internal usage will be generated by the program or
fetched from Wikidata.
--]]
-- module import
local vi = require( 'Module:VCard/i18n' ) -- additional vCard options
return {
-- administration
moduleInterface = {
suite = 'vCard',
sub = 'Params',
serial = '2026-09-17',
item = 65455743
},
-- complete table of parameters
-- true: get it from Wikidata in any case
-- for parameter translations see Module:VCard/i18n
ParMap = {
address = '',
addressLang = '',
addressLocal = '',
agoda = true, -- Agoda.com
alt = '',
applemaps = true, -- Maps.Apple.com
auto = '',
before = '',
booking = true, -- Booking.com
checkin = '',
checkout = '',
color = '', -- internal use
comment = '',
commonscat = '',
content = '',
copyMarker = '',
country = '',
dav = true, -- Alpenverein.de
description = '',
directions = '',
directionsLocal = '',
email = '',
expedia = true, -- Expedia.com
facebook = '',
fax = '',
flickr = '',
foursquare = true, -- Foursquare.com
geonames = true, -- Geonames.org
googlemaps = '', -- Maps.Google.com
group = '',
histhotelsAm = true, -- HistoricHotels.org
histhotelsEu = true, -- HistoricHotelsOfEurope.com
histhotelsWw = true, -- HistoricHotelsWorldwide.com
hostelworld = true, -- Hostelworld.com
hotels = true, -- Hotels.com
hours = '',
iata = vi.options.showIata,
icao = vi.options.showIcao,
id = '', -- used if wikidata is missing
image = true,
instagram = '',
kayak = true, -- Kayak.com
lastedit = '',
lat = '',
leadingHotels = true, -- LHW.com
localLang = '',
long = '',
mapGroup = '',
mobile = '',
name = true,
nameExtra = '',
nameLatin = '',
nameLocal = '',
nameMap = '',
oeav = true, -- Alpenverein.at
osmNodeId = true,
osmRelationId = true,
osmWayId = true,
payment = '',
phone = '',
preferredHotels = true, -- PreferredHotels.com
price = '',
pzs = true, -- PZS.si (Slovenia)
recreation = true, -- Recreation.gov
relaisChateaux = true, -- RelaisChateaux.com
rss = true, -- web feed
sac = true, -- SAC-CAS.ch
sectionFrom = '',
show = vi.options.defaultShow,
skyscanner = true, -- Skyscanner.com
stationNumber = true, -- Intl. station number
status = '',
styles = '',
subtype = '',
subtypeAdd = true, -- internal use
symbol = '', -- internal use
text = '', -- internal use
tiktok = '',
tollfree = '',
trip = true, -- Trip.com
tripadvisor = true, -- Tripadvisor.com
type = '',
unesco = vi.options.showUnesco,
url = '',
urlMap = true, -- official map URL
urlTimetable = true, -- timetable/schedule URL
useIcon = '', -- internal use
wikidata = '',
wikipedia = '', -- deprecated
x = '',
youtube = '',
zoom = '',
date = '', -- for events
month = '',
year = '',
endDate = '',
endMonth = '',
endYear = '',
frequency = '',
location = ''
},
--[[
Wikidata properties and definitions for vCard parameters
p property or set of properties
f formatter string
c maximum count of results, default = 1
m concat mode (if c > 1), default concat with ', '
v value type,
empty: string value (i.e. default type),
id: string value of an id like Q1234567
idl: string value of the label of an id like Q1234567
il: language-dependent string value
iq: string value with qualifier ids
iqa: string value with qualifier ids, for comments in accessibility
iqp: string value with qualifier ids, for comments in policies
iqu: string value with qualifier ids, for UNESCO parts
au: quantity consisting of amount and unit
pau: quantity consisting of amount (for P8733)
vq: string or table value with qualifiers ids and references
q table of qualifiers allowed, for value type id
l = lang: language dependent
wiki / local: monolingual text by wiki or local language
le = true: use date for lastedit parameter
t = phone type (landline, mobile)
--]]
ParWD = {
address = {},
addressLocal = {},
agoda = { p = 'P6008' },
applemaps = { p = 'P10046' },
booking = { p = 'P3607' },
checkin = { p = 'P8745', v = 'idl' },
checkout = { p = 'P8746', v = 'idl' },
dav = { p = 'P5757' },
directions = { p = 'P2795', v = 'il', l = 'wiki' },
directionsLocal = { p = 'P2795', v = 'il', l = 'local' },
email = { p = 'P968', v = 'vq', c = 5 },
expedia = { p = 'P5651' },
facebook = { p = { { p = 'P2013', f = 'https://www.facebook.com/%s' }, -- Facebook username
{ p = 'P1997', f = 'https://www.facebook.com/%s' }, -- Facebook places ID
{ p = 'P11705', f = 'https://www.facebook.com/pages/%s' } } }, -- Facebook numeric ID
fax = { p = 'P2900', v = 'vq', c = 3 },
flickr = { p = 'P3267', f = 'https://www.flickr.com/photos/%s' },
foursquare = { p = 'P1968' },
geonames = { p = 'P1566' },
googlemaps = { p = 'P3749' },
histhotelsAm = { p = 'P5734' },
histhotelsEu = { p = 'P5774' },
histhotelsWw = { p = 'P5735' },
hostelworld = { p = 'P10442' },
hotels = { p = 'P3898' },
iata = { p = 'P238', c = 3 },
icao = { p = 'P239' },
image = { p = { { p = 'P18' },
{ p = 'P3451' }, -- nighttime view
{ p = 'P8592' }, -- aerial view
{ p = 'P5775' } } }, -- interior image
instagram = { p = { { p = 'P2003', f = 'https://www.instagram.com/%s/' },
{ p = 'P4173', f = 'https://www.instagram.com/explore/locations/%s/' } } },
kayak = { p = 'P10547' },
leadingHotels = { p = 'P5834' },
mobile = { p = 'P1329', v = 'vq', c = 5, t = 'mobile' },
nameLocal = {},
oeav = { p = 'P5759' },
osmNodeId = { p = 'P11693' },
osmRelationId = { p = 'P402' },
osmWayId = { p = 'P10689' },
payment = { p = 'P2851', v = 'id', c = 50, m = 'no' },
phone = { p = 'P1329', v = 'vq', c = 5, t = 'landline' },
preferredHotels = { p = 'P5890' },
price = { p = 'P2555', v = 'au', c = 10, le = true }, -- fee
pzs = { p = 'P5758' },
recreation = { p = 'P3714' },
relaisChateaux = { p = 'P5836' },
rss = { p = 'P1019' },
sac = { p = 'P5761' },
skyscanner = { p = 'P10487' },
stationNumber = { p = 'P954' }, -- intl station number
subtypeAdd = { p = { { p = 'P912', v = 'iqa', c = 50 }, -- has facility
{ p = 'P166', v = 'iq', c = 5, q = { 'Q2976556', 'Q20824563', 'Q104135230' } },
-- awards received (hotel rating, Michelin etc.)
{ p = 'P10290', v = 'iq', c = 3 }, -- hotel rating
{ p = 'P8733', v = 'pau' }, -- number of rooms
{ p = 'P2012', v = 'iq', c = 50 }, -- cuisine
{ p = 'P2846', v = 'iq' }, -- wheelchair
{ p = 'P2848', v = 'iq' }, -- WLAN
{ p = 'P5023', v = 'iqp', c = 10 } }, c = 100, m = 'no' }, -- activity policies
tiktok = { p = { { p = 'P7085', f = 'https://www.tiktok.com/@%s' }, -- TikTok username
{ p = 'P11559', f = 'https://www.tiktok.com/place/_-%s' } } }, -- TikTok place ID
trip = { p = 'P10425' },
tripadvisor = { p = 'P3134' },
x = { p = 'P2002', f = 'https://x.com/%s' },
unesco = { p = { { p = 'P757' },
{ p = 'P1435', v = 'iqu', q = { 'Q43113623', 'Q9259' } } } },
url = { p = { { p = 'P856', l = 'lang' }, -- URL
{ p = 'P973', l = 'lang' } } }, -- described at URL
urlMap = { p = 'P9601' },
urlTimetable = { p = 'P12677' },
youtube = { p = { { p = 'P11245', f = 'https://www.youtube.com/@%s' }, -- Youtube channel @ alias
{ p = 'P2397', f = 'https://www.youtube.com/channel/%s' } } } -- Youtube channel
},
-- additional parameters for auto = y
ParWDAdd = {
address = 1,
addressLocal = 1,
directions = 1,
directionsLocal = 1,
hours = 1,
nameLocal = 1
},
-- parameters to save in vCard wrapper tag
vcardData = {
addressLang = 'data-address-lang', -- language of address
addressLocal = 'data-address-local',
color = 'data-color',
commonscat = 'data-commonscat',
directionsLocal = 'data-directions-local',
group = 'data-group',
image = 'data-image',
mapGroup = 'data-map-group',
nameLocal = 'data-name-local',
rss = 'data-rss',
subtype = 'data-subtype',
symbol = 'data-symbol',
type = 'data-type',
url = 'data-url',
wikidata = 'data-wikidata',
agoda = 'data-agoda-com',
applemaps = 'data-apple-maps-id',
booking = 'data-booking-com',
dav = 'data-alpenverein-de',
expedia = 'data-expedia-com',
foursquare = 'data-foursquare-id',
geonames = 'data-geonames-id',
googlemaps = 'data-google-maps-cid',
histhotelsAm = 'data-historic-hotels-america',
histhotelsEu = 'data-historic-hotels-europe',
histhotelsWw = 'data-historic-hotels-worldwide',
hostelworld = 'data-hostelworld-com',
hotels = 'data-hotels-com',
kayak = 'data-kayak-com',
leadingHotels = 'data-leading-hotels',
oeav = 'data-alpenverein-at',
osmNodeId = 'data-osm-node-id',
osmRelationId = 'data-osm-relation-id',
osmWayId = 'data-osm-way-id',
preferredHotels = 'data-preferred-hotels',
pzs = 'data-pzs-si',
recreation = 'data-recreation-gov',
relaisChateaux = 'data-relais-chateaux',
sac = 'data-sac-cas-ch',
sectionFrom = 'data-section-from',
skyscanner = 'data-skyscanner-com',
stationNumber = 'data-station-number',
trip = 'data-trip-com',
tripadvisor = 'data-tripadvisor-com',
urlMap = 'data-map-url',
urlTimetable = 'data-timetable-url'
},
-- check if event
checkEvent = { 'date', 'month', 'year', 'endDate', 'endMonth', 'endYear',
'frequency', 'location' },
-- prevent local data if wiki language == country language
localData = { 'nameLocal', 'addressLocal', 'directionsLocal' },
-- phone numbers for fetching country data
phones = { 'phone', 'fax', 'mobile', 'tollfree' },
-- possible values for show parameter
show = {
all = 1,
coord = 1,
copy = 1,
inline = 1,
noairport = 1,
none = 1,
noperiod = 1,
nositelinks = 1,
nosocialmedia = 1,
outdent = 1,
poi = 1,
symbol = 1,
wikilink = 1
}
}
8w7v8nbgxdv54xpuzx7f9mgjq8ymb1p
Modulo:VCard/Qualifiers
828
4803
73241
72146
2026-09-24T10:44:16Z
RolandUnger
168
Update
73241
Scribunto
text/plain
-- Qualifier to label table
-- please use only quotation marks instead of apostrophs for JSON export
return {
-- documentation
moduleInterface = {
suite = "VCard",
sub = "VCard/Qualifiers",
serial = "2026-09-23",
item = 99929816
},
labels = {
-- unuoj / units
gratis = "senkosta",
Q1543615 = "senkosta",
Q1092296 = "Aĝojaro",
Q24564698 = "Aĝojaro",
-- uzado / use (P366)
-- parto rilatanta / applies to part (P518) etc.
Q5070802 = "Krizostato",
Q11028 = "Informo",
Q58897583 = "Informo",
Q1482145 = "Telefonhelpo",
Q256132 = "Telefoncentralo",
Q1261521 = "Telefoncentralo",
Q589666 = "Telefoncentralo",
Q2794937 = "Akceptejo",
Q31948 = "Vestiblo",
Q862212 = "Fojero",
Q4096995 = "Rezervo",
Q1029698 = "Gvidata rondiro",
Q7673285 = "Seĝa rezervo",
Q1162163 = "Direktisto",
Q267936 = "Direktisto",
Q25713832 = "Estro",
Q11964531 = "Manaĝero",
Q22132694 = "Muzedirektoro",
Q80687 = "Sekretariato",
Q859482 = "Sekretariato",
Q182060 = "Oficejo",
Q5283295 = "Administracio",
Q50412353 = "Administracio",
Q39809 = "Merkatiko",
Q133080 = "Publikrilatoj",
Q111148864 = "Kultura oficejo",
Q674426 = "Kuratoro",
Q2108946 = "Gazetara oficejo",
Q1193236 = "Novaĵa amaskomunikilo",
Q5196479 = "Klienta subteno",
Q1060653 = "Klienta servo",
Q955464 = "Pastro",
Q7406919 = "Servo",
Q918324 = "Flughavena turo",
Q51073356 = "Havenestro",
Q11735065 = "Havenestro",
Q12407563 = "Devigo de parkumejoj",
Q1049511 = "WhatsApp",
Q15616276 = "Telegram",
Q17517 = "Poŝtelefono",
Q738621 = "Fiksa telefono",
Q2664461 = "Pordisto",
Q1735282 = "Kassisto",
Q1463565 = "Kassisto",
Q551800 = "Biletoj",
Q187456 = "Trinkejo",
Q777754 = "Manĝlivera servo",
Q41958 = "Manĝlivera servo",
Q171141 = "Gastronomio",
Q43164 = "Kuirejo",
Q213441 = "Vendejo",
Q11707 = "Restoracio",
Q547762 = "Amuzumado",
Q133215 = "Kazino",
Q1065656 = "Gimnastikejo",
Q55187 = "Tondisto",
Q31374404 = "Butikcentro",
Q179415 = "Masaĝo",
Q33506 = "Muzeo",
Q2772772 = "Milita muzeo",
Q1824143 = "Liverado",
Q2048970 = "Ĉambra servo",
Q15983979 = "Oficejo pri perditaj posedaĵoj",
Q60616546 = "Urba turismo",
Q112726458 = "Vizoficejo",
Q862761 = "Interne",
Q1322786 = "Eksteraĵo",
Q121298623 = "Subĉiela areo",
Q115156410 = "Montra kolekto",
Q464980 = "Ekspozicio",
Q5402268 = "Daŭra ekspozicio",
Q10426913 = "Daŭra ekspozicio",
Q29023906 = "Portempa ekspozicio",
-- por homoj / applies to people (P6001)
Q5 = "Persono",
Q1340307 = "Malgranda infano",
Q11370581 = "Beboj kaj infanetoj",
Q7569 = "Infano",
Q29514218 = "Filo",
Q1076052 = "Infanĝardenano",
Q11519472 = "Infanĝardenano",
Q1902344 = "Infanĝardenano",
Q190007 = "Junaĝulo",
Q131774 = "Junaĝulo",
Q170079 = "Neplenaĝulo",
Q1492760 = "Dekkelkjarulo",
Q17156455 = "Juna plenkreskulo",
Q80994 = "Plenkreskulo",
Q18000 = "Plenkreskulo",
Q16003605 = "Bazlernejaj studentoj",
Q98021727 = "Bazlernejaj studentoj",
Q16003532 = "Gimnaziano",
Q15360275 = "Mezlernejaj studentoj",
Q48942 = "Lernanto",
Q68131879 = "Lernanto",
Q73229462 = "Lernanto",
Q98033936 = "Mezlernejaj studentoj",
Q37226 = "Instruisto",
Q48282 = "Studento",
Q315247 = "Universitata studento",
Q110207241 = "Eksterlanda studento",
Q253567 = "Metilernanto",
Q59263364 = "Metilernanto",
Q28790169 = "Senlaborulo",
Q59308743 = "Ricevulo de registara asistado",
Q109710549 = "Volontulo",
Q136806547 = "Volontulo",
Q136806565 = "Volontulo",
Q24716636 = "Volontulo",
Q1454927 = "Soldatservanto",
Q47228496 = "Soldatservanto",
Q1930187 = "Ĵurnalisto",
Q1749879 = "Emerito",
Q1358789 = "Maljunuloj",
Q191089 = "Maljunuloj",
Q2191986 = "Maljunuloj",
Q111524907 = "Maljunuloj ekde 60",
Q117131136 = "Maljunuloj ekde 65",
Q108427775 = "Maljunuloj super 65",
Q12131 = "Malkapablo",
Q10857933 = "Malkapablo",
Q1250414 = "Grave handikapita",
Q136806121 = "Grave handikapita (50% aŭ pli)",
Q8436 = "Familio",
Q1422286 = "Kompaniulo",
Q874405 = "Grupo",
Q16334295 = "Grupo",
Q1605672 = "Junulara gvidanto",
Q113191894 = "Egipta studento",
Q113191817 = "Araba studento",
Q221488 = "Piediranto",
Q11442 = "Biciklo",
Q42889 = "Rimedo de transporto",
Q1420 = "Aŭtomobilo",
Q1144312 = "Persona aŭto",
Q190578 = "Persona aŭto",
Q43193 = "Kamiono",
Q5638 = "Buso",
Q1373492 = "Buso",
Q193234 = "Skotero",
Q34493 = "Motorciklo",
Q23901795 = "plena kotizo",
Q100157294 = "malpliigita kotizo",
Q23901802 = "malpliigita kotizo",
Q10328277 = "malpliigita enirkotizo",
Q10585806 = "Minimumo",
Q10578722 = "Maksimumo",
Q30079877 = "Monata bileto",
Q2024421 = "Enreta bileto",
Q59582212 = "Semajna bileto",
Q819073 = "Labortago",
Q211391 = "Semajnfino",
Q22947 = "Loĝanto",
Q1020994 = "Civitano",
Q70237645 = "Hejmlando",
Q473741 = "Eksterlandano",
Q1072012 = "Eksterlandano",
Q56508363 = "Civitano de Eŭropa Unio aŭ Eŭropa Ekonomia Areo",
Q56508358 = "Ne-EU-civitanoj",
Q1061510 = "Egipta",
Q35323 = "Araba",
Q31 = "Belgio",
Q4200853 = "Indonezianoj",
Q15731961 = "Indonezianoj",
Q19840821 = "Singapuranoj",
Q126003079 = "Singapuranoj",
Q2408569 = "Tajlandanoj",
Q7901501 = "Urugvajanoj",
Q39201 = "dorlotbesto",
Q144 = "hundo",
Q62966720 = "parkumeja kotizo",
Q1039099 = "ĉiĉerono",
Q758877 = "aŭdogvidilo",
Q15328 = "kamerao",
Q313600 = "fotilo",
Q313614 = "filmilo",
Q335234 = "filmilo",
Q335095 = "filmilo",
Q683906 = "stativo",
Q24192067 = "atingebla per rulseĝo",
Q24192068 = "rulseĝo alirebla kun helpo",
Q63731120 = "rulseĝo parte alirebla",
Q63731151 = "rulseĝo parte alirebla kun helpo"
-- es fehlen Übernachtung, ÜF, EZ, DZ u. ä. (in Wikidata anlegen)
}
}
1tyx3fxeskdkm12oboq3900z68jvm7u
Modulo:VCard/Subtypes
828
4804
73242
72958
2026-09-24T10:44:19Z
RolandUnger
168
Update
73242
Scribunto
text/plain
-- empty strings should be filled with icons
-- please use only quotation marks instead of apostrophs for JSON export
return {
-- administration
moduleInterface = {
suite = 'vCard',
sub = 'Subtypes',
serial = '2026-08-20',
item = 65455756
},
firstGroup = 2, -- first group to display
fromWDGroupNumber = 98, -- group number for Q... types from Wikidata
fromTypesGroupNumber = 99, -- group number for types from types table
-- subtype conversion
convert = {
hotelstars = { "1", "2", "3", "4", "5" }, -- hotel stars codes
michelin = { "michelin1", "michelin2", "michelin3" }
},
-- type list
f = {
-- classification, rating, y & n. Group 1 is usually not displayed
budget = { g = 1, wd = "", n = "günstig" },
midrange = { g = 1, wd = "", n = "mittel" },
upmarket = { g = 1, wd = "", n = "gehoben" },
-- fetching features from Wikidata
n = { g = 1, wd = "", alias = { "no", "none", "nein" }, n = "ohne Wikidata-Merkmale" },
y = { g = 1, wd = "", alias = { "yes", "j", "ja" }, n = "mit Wikidata-Merkmalen" },
-- hotel rating
hotelstars = { g = 2, wd = "Q2976556", n = "Hotel-Stern[e]" }, -- see: convert
-- Upto now it seems that there is no font containing the left black half star
-- (u+2BE8): ⯨. That's why now the ½ workaround.
["1"] = { g = 2, wd ="Q110772650", sortkey = "01*", n = "★", t = "1-Stern-Bewertung" }, -- tourist
["1h"] = { g = 2, wd ="Q110932985", sortkey = "01*5", n = "★½", t = "1,5-Sterne-Bewertung" }, -- superior tourist (tourist plus)
["1s"] = { g = 2, wd ="Q109726413", sortkey = "01*S", n = "★S", t = "1-Stern-Superior-Bewertung" }, -- superior tourist (tourist plus)
["2"] = { g = 2, wd ="Q110772651", sortkey = "02*", n = "★★", t = "2-Sterne-Bewertung" }, -- standard
["2h"] = { g = 2, wd ="Q110932986", sortkey = "02*5", n = "★★½", t = "2,5-Sterne-Bewertung" }, -- superior standard
["2s"] = { g = 2, wd ="Q109726348", sortkey = "02*S", n = "★★S", t = "2-Sterne-Superior-Bewertung" }, -- superior standard
["3"] = { g = 2, wd ="Q110772652", sortkey = "03*", n = "★★★", t = "3-Sterne-Bewertung" }, -- comfort
["3h"] = { g = 2, wd ="Q110932987", sortkey = "03*5", n = "★★★½", t = "3,5-Sterne-Bewertung" }, -- superior comfort
["3s"] = { g = 2, wd ="Q109726284", sortkey = "03*S", n = "★★★S", t = "3-Sterne-Superior-Bewertung" }, -- superior comfort
["4"] = { g = 2, wd ={ "Q110772653", "Q99309708" }, sortkey = "04*", n = "★★★★", t = "4-Sterne-Bewertung" }, -- first class
["4h"] = { g = 2, wd ="Q110932988", sortkey = "04*5", n = "★★★★½", t = "4,5-Sterne-Bewertung" }, -- superior first class
["4s"] = { g = 2, wd ="Q109726210", sortkey = "04*S", n = "★★★★S", t = "4-Sterne-Superior-Bewertung" }, -- superior first class
["5"] = { g = 2, wd ={ "Q109248725", "Q109248724" }, sortkey = "05*", n = "★★★★★", t = "5-Sterne-Bewertung" }, -- luxury
["5s"] = { g = 2, wd ="Q109726138", sortkey = "05*S", n = "★★★★★S", t = "5-Sterne-Superior-Bewertung" }, -- superior luxury
-- Michelin awards to restaurant chefs
bib_gourmand = { g = 2, wd ="Q104135230", n = "Bib Gourmand" },
michelin = { g = 2, wd = "Q20824563", n = "Michelin-Stern[e]" },
michelin1 = { g = 2, wd = "", n = "Michelin 1*", f = "Etoile Michelin-1.svg", c = 1 },
michelin2 = { g = 2, wd = "", n = "Michelin 2*", f = "Etoile Michelin-1.svg", c = 2 },
michelin3 = { g = 2, wd = "", n = "Michelin 3*", f = "Etoile Michelin-1.svg", c = 3 },
-- subtypes from subtype parameter in types table
bnb = { g = 3, wd = "Q367914", n = "Bed & Breakfast" },
boarding_house = { g = 3, wd = { "Q1558858", "Q1065252" }, n = "Pension" },
hotel_garni= { g = 3, wd = "Q1631103", n = "Garni" },
-- general facilities
accessible = { g = 4, wd = "Q808926", n = "barrierefrei" }, -- barrier-free, for handicapped people
ai = { g = 4, wd = "Q1281666", n = "All inclusive" },
basement_garage = { g = 4, wd = "Q2431970", n = "Tiefgarage[]" },
car_park = { g = 4, wd = "Q13218805", n = "Parkhaus" },
free_wlan = { g = 4, wd = "Q1543615", n = "freies WLAN" },
garage = { g = 4, wd = "Q22733", n = "Garage[n]" },
induction_loop = { g = 4, wd = "Q2163913", n = "Induktionsschleife[n]" },
internet_access = { g = 4, wd = "Q1472399", n = "Internetzugang" }, -- unknown type or both lan and wlan
lan = { g = 4, wd = "Q11381", n = "LAN" },
lgbt = { g = 4, wd = "Q17884", n = "LGBT", f = "Gay flag.svg" }, -- including gay
nobreakfast= { g = 4, wd ="Q106041208", n = "kein Frühstück" },
nowheelchair = { g = 4, wd = "Q24192069", n = "nicht rollstuhlzugänglich", f = "Wheelchair-red3.png" },
nowlan = { g = 4, wd = "Q1814990", n = "kein WLAN" }, -- no
paid_wlan = { g = 4, wd = "Q24202480", n = "kostenpflichtiges WLAN" },
parking = { g = 4, wd = "Q6501349", n = "Parkpl[ä|a]tz[e]" },
tactile_graphic = { g = 4, wd = "Q7674130", n = "Blindengrafik[en]" },
valet_parking = { g = 4, wd = "Q1423019", n = "Valet-Parken" },
withbreakfast = { g = 4, wd ="Q106041297", n = "mit Frühstück" },
wheelchair = { g = 4, wd = "Q24192067", n = "rollstuhlzugänglich", f = "Wheelchair-green3.png" },
wheelchair_available = { g = 4, wd = "Q191931", n = "Rollstuhl verfügbar" },
wheelchair_with_help = { g = 4, wd = "Q24192068", n = "rollstuhlzugänglich mit Hilfe", f = "Wheelchair-yellow3.png" },
wheelchair_partially = { g = 4, wd = "Q63731120", n = "teilweise rollstuhlzugänglich" },
wheelchair_partially_with_help = { g = 4, wd = "Q63731151", n = "teilweise rollstuhlzugänglich mit Hilfe" },
wlan = { g = 4, wd = { "Q6452715", "Q29643" }, n = "WLAN" }, -- yes
-- hotel facilities
adult_pool = { g = 5, wd = "", n = "Pool[s] für Erwachsene" },
airport_transfer_service = { g = 5, wd ="Q110012299", n = "Flughafentransfer-Service" },
atm = { g = 5, wd = { "Q81235", "Q6554231"}, n = "Geldautomat[en], Bankomat[en]" },
ballroom = { g = 5, wd = "Q805353", n = "Balls[ä|aa]l[e]" },
babysitter = { g = 5, wd = "Q45181247", n = "Babysitter[]" },
bank = { g = 5, wd = "Q22687", n = "Bank[en]" },
banquet_room = { g = 5, wd = "Q85833489", n = "Banketts[ä|aa]l[e]" },
bar = { g = 5, wd = "Q187456", n = "Bar[s]" },
beach = { g = 5, wd = "Q40080", n = "Str[ä|a]nd[e]" },
bed = { g = 5, wd = "Q42177", n = "Bett[en]" },
bicycle_stand = { g = 5, wd = "Q1392526", n = "Fahrradstellpl[ä|a]tz[e]" },
bike_rental= { g = 5, wd = "Q10611118", n = "Fahrradverleih[e]" },
business = { g = 5, wd = "Q203180", n = "Geschäftsbereich[e]" },
buy = { g = 5, wd = "Q1369832", n = "Einkaufen" },
cabana = { g = 5, wd = "Q3649129", n = "Cabana[s], Hütte[n], Umkleidehäuschen" },
cafe = { g = 5, wd = "Q30022", n = "Café[s]" },
cafeteria = { g = 5, wd = "Q8463304", n = "Cafeteria[s]" },
casino = { g = 5, wd = "Q133215", n = "Casino[s]" },
cell = { g = 5, wd = "Q2555640", n = "Zelle[n]" },
change_machine = { g = 5, wd = "Q5071849", n = "Geldwechselautomat[en]" },
cinema = { g = 5, wd = "Q41253", n = "Kino[s]" },
cloakroom = { g = 5, wd = "Q965173", n = "Garderobe[n]" },
conference = { g = 5, wd = { "Q625994", "Q1207465" }, n = "Konferenzr[ä|a]um[e]" },
currency_exchange = { g = 5, wd = "Q2002539", n = "Geldwechsel" },
dance_hall = { g = 5, wd ="Q121085156", n = "Tanzs[ä|aa]l[e]" },
dining_room= { g = 5, wd = "Q661199", n = "Esszimmer" },
diving = { g = 5, wd = "Q179643", n = "Tauchbas[en|is]" },
dormitory = { g = 5, wd = "Q3037266", n = "Schlafs[ä|aa]l[e]" },
family_room= { g = 5, wd = "Q5433389", n = "Familienzimmer[]" },
fitness_center = { g = 5, wd = { "Q1065656", "Q30750411", "Q56298769" }, n = "Fitnessstudio[s]" }, -- including gym, healthclub
games_room = { g = 5, wd = "", n = "Spielzimmer[]" },
garden = { g = 5, wd = "Q1107656", n = "G[ä|a]rten" },
golf = { g = 5, wd = { "Q5377", "Q1048525", "Q3177122", "Q3177122" }, n = "Golf, Golfpl[ä|a]tz[e]" },
gym = { g = 5, wd = { "Q14092", "Q203609", "Q121085159" }, n = "Turnhalle[n]" },
indoorpool = { g = 5, wd = "Q357380", n = "Hallenschwimmb[ä|a]d[er]" },
kidsclub = { g = 5, wd = "Q16255832", n = "Kinderclub[s]" },
kiting = { g = 5, wd = "Q219554", n = "Kiten" },
library = { g = 5, wd = "Q7075", n = "Bibliothek[en]" },
lift = { g = 5, wd = "Q132911", n = "Fahrst[ü|u]hl[e], Lift[e]" },
lobby = { g = 5, wd = "Q31948", n = "Lobby[s]" },
luggage_storage = { g = 5, wd = { "Q1195470", "Q21996814" }, n = "Gepäckaufbewahrung[en]" },
money_exchange_machine = { g = 5, wd = "Q25632829", n = "Geldwechselautomat[en]" },
meeting = { g = 5, wd = "Q3469909", n = "Besprechungszimmer[]" }, -- meeting rooms
minigolf = { g = 5, wd = "Q754796", n = "Minigolf" },
nightclub = { g = 5, wd = "Q622425", n = "Nachtclub[s]" },
playground = { g = 5, wd = "Q11875349", n = "Spielpl[ä|a]tz[e]" },
playground_tunnel = { g = 5, wd = "Q130308900", n = "Spielplatz-Tunnel[], Kriechtunnel[]" },
pool = { g = 5, wd = { "Q1501", "Q118559330" }, n = "Schwimmbecken[]" },
reception = { g = 5, wd = "Q2794937", alias = "service_counter", n = "Rezeption[en], Empfangsschalter" },
restaurant = { g = 5, wd = "Q11707", n = "Restaurant[s]" },
roof_garden= { g = 5, wd = "Q1156696", n = "Dachg[ä|a]rten" },
roof_terrace= { g = 5, wd = "Q1081213", n = "Dachterrasse[n]" },
room = { g = 5, wd = { "Q180516", "Q105582722" }, n = "Zimmer[]" },
sauna = { g = 5, wd = "Q57036", n = "Sauna[s]" },
slide = { g = 5, wd = "Q334747", n = "Rutsche[n]" },
socket_near_bed = { g = 5, wd ="Q110073378", n = "Steckdose[n] in Bettnähe" },
shop = { g = 5, wd = "Q213441", n = "Geschäft[e]" },
souvenir_shop = { g = 5, wd = "Q865693", n = "Souvenirgeschäft[e]" },
spa = { g = 5, wd = "Q1341387", alias = "wellness_center", n = "Wellness-Center[], Spa[s]" },
sports = { g = 5, wd = "Q349", n = "Sport" },
suite = { g = 5, wd = "Q1367530", n = "Suite[n]" },
surfing = { g = 5, wd = "Q1324499", n = "Surfen" },
tennis = { g = 5, wd = "Q847", n = "Tennis" },
tennis_court = { g = 5, wd = "Q741118", n = "Tennispl[ä|a]tz[e]" },
theater = { g = 5, wd = "Q24354", n = "Theater[]" },
wading_pool= { g = 5, wd = "Q2098314", n = "Planschbecken[]" },
warm_water = { g = 5, wd = "Q1419245", n = "Warmwasser" },
water_slide= { g = 5, wd = "Q1163166", n = "Wasserrutsche[n]" },
wave_pool = { g = 5, wd = "Q827349", n = "Wellenb[ä|a]d[er]" },
-- non-hotel facilities
audioguide = { g = 5, wd = "Q758877", n = "Audioguide[s]" },
cctv = { g = 5, wd = { "Q242256", "Q334415" }, n = "Videoüberwachungsanlage[n]" },
communal_bunks = { g = 5, wd = "Q1628935", n = "Pl[ä|a]tz[e] im Matratzenlager" },
educational_workshop = { g = 5, wd ="Q113484895", n = "pädagogische[n] Werkst[ä|a]tt[en]" },
guidebook = { g = 5, wd = "Q223638", n = "gedruckte Reiseführer[]" },
lecture_hall = { g = 5, wd = "Q253275", n = "Hörs[ä|aa]l[e]" },
lighting = { g = 5, wd = "Q210064", n = "Beleuchtung" },
museum_shop= { g = 5, wd = "Q2922607", n = "Museumsgeschäft[e]" },
organ = { g = 5, wd = "Q1444", n = "Orgel[n]" },
public_clock = { g = 5, wd ="Q129165885", n = "öffentliche Uhr[en]" },
rest_area = { g = 5, wd = { "Q47520603", "Q785979" }, alias = "picnic_site", n = "Rastpl[ä|a]tz[e], Picknickplatz" },
reading_room = { g = 5, wd = "Q1753764", n = "Leses[ä|aa]l[e]" },
shakedown = { g = 5, wd = "Q40415224", n = "Pl[ä|a]tz[e] im Notlager" },
school_meal= { g = 5, wd = "Q1195832", n = "Schulspeisung" },
winter_room= { g = 5, wd = "Q382899", n = "Pl[ä|a]tz[e] im Winterraum" },
-- services in hotels etc.
["24-hour_reception"] = { g = 6, wd = "", n = "24-Stunden-Rezeption" },
accessible_toilet = { g = 6, wd = "Q2775009", n = "Behinderten-WC[s]" },
airport_shuttle = { g = 6, wd = "", n = "Flughafenshuttle" },
airport_terminal = { g = 6, wd = "Q849706", n = "Flughafenterminal[s]" },
airport_transportation = { g = 6, wd = "", n = "Flughafentransport" },
animation = { g = 6, wd = "Q547762", n = "Animation" },
baby_change = { g = 6, wd = "Q2567605", n = "Wickelr[ä|a]um[e]" },
babysitting = { g = 6, wd = "Q797990", n = "Babysitten" },
bahnhofsmission = { g = 6, wd = "Q801713", n = "Bahnhofsmission" },
beauty_service = { g = 6, wd = "Q30303305", n = "Schönheitsservice" },
bicycle = { g = 6, wd = "Q11442", n = "Fahrrad" },
breakfast = { g = 6, wd = "Q80973", n = "Frühstück" },
breakfast_buffet = { g = 6, wd = "", n = "Frühstücksbuffet" },
breakfast_included= { g = 6, wd = "", n = "inklusive Frühstück" },
bus_stop = { g = 6, wd = "Q953806", n = "Bushaltestelle[n]" },
car_hire = { g = 6, wd = "Q291240", n = "Autovermietung[en]" },
changing_table = { g = 6, wd = "Q1780834", n = "Wickeltisch[e]" },
concierge = { g = 6, wd = "Q2664461", n = "Concierge" },
discotheque = { g = 6, wd = "Q1228895", n = "Discothek[en]" },
dry_cleaning = { g = 6, wd = "Q878156", n = "chemische Reinigung[en]" },
entertainment = { g = 6, wd = "Q173799", n = "Unterhaltung" },
federal_police = { g = 6, wd = "Q56026", n = "Bundespolizei" },
free_parking = { g = 6, wd ="Q108759647", n = "kostenlose[|r] Parkpl[ä|a]tz[e]" },
gate = { g = 6, wd = "Q247739", n = "Flugsteig[e]" },
hairdresser = { g = 6, wd = { "Q55187", "Q95856773", "Q3062512" }, n = "Friseur[e]" },
laundry = { g = 6, wd = { "Q267734", "Q7223085", "Q12893467", "Q57261433" }, n = "Wäscherei[en]" },
live_music = { g = 6, wd ="Q100348587", n = "Livemusik" },
massage = { g = 6, wd = "Q179415", n = "Massage[n]" },
multilingual_staff= { g = 6, wd = "Q30081", n = "mehrsprachiges Personal" },
newspaper = { g = 6, wd = "Q11032", n = "Tageszeitung" },
paid_parking = { g = 6, wd ="Q128800991", n = "kostenpflichtige[|r] Parkpl[ä|a]tz[e]" },
post_office = { g = 6, wd = "Q35054", n = "Postfiliale[n]" },
public_toilet = { g = 6, wd = { "Q813966", "Q3472280" }, n = "öffentliche Toilette[n]" },
railroad_police = { g = 6, wd = "Q1930355", n = "Bahnpolizei" },
room_service = { g = 6, wd = "Q2048970", n = "Zimmerservice" },
selflaundry = { g = 6, wd = "Q1143034", n = "Waschsalon[s]" },
shuttle_bus = { g = 6, wd = "Q1368498", n = "Shuttlebus" },
taxicab_stand = { g = 6, wd = { "Q82650", "Q1395196" }, n = "Taxist[ä|a]nd[e]" },
ticket_machine = { g = 6, wd = "Q657345", n = "Fahrkartenautomat[en]" },
ticket_office = { g = 6, wd = { "Q56845288", "Q15842100" }, n = "Fahrkartenschalter[]" },
toilet = { g = 6, wd = { "Q7857", "Q97657740" }, n = "Toilette[n]" },
urinal = { g = 6, wd = { "Q152285", "Q97657738" }, n = "Urinal[e]" },
wc = { g = 6, wd = "Q7813355", n = "WC[s]" },
workshop = { g = 6, wd = "Q656720", n = "Werkst[ä|a]tt[en]" },
-- room facilities
ac = { g = 7, wd = "Q173725", n = "Klimaanlage[n]" },
air_condition = { g = 5, wd = "Q1265533", n = "Klimaanlage[n]" },
balcony = { g = 7, wd = "Q170552", n = "Balkon[e]" },
bathroom = { g = 7, wd = "Q190771", n = "Badezimmer[]" },
bathtub = { g = 7, wd = "Q152095", n = "Badewanne[n]" },
bottle_warmer = { g = 7, wd = "Q56711128", n = "Flaschenwärmer[]" },
coffeemaker= { g = 7, wd = "Q211841", n = "Kaffeemaschine[n]" },
commonbath = { g = 7, wd = "", n = "Gemeinschaftsb[ä|a]d[er]" }, -- Gemeinschaftsbad
fan = { g = 7, wd = "Q6498398", n = "Ventilator[en]" },
fridge = { g = 7, wd = "Q37828", n = "Kühlschr[ä|a]nk[e]" },
grab_rail = { g = 7, wd = "", n = "Haltegriff[e]" },
hairdryer = { g = 7, wd = "Q15004", n = "Fön[e]" },
jacuzzi = { g = 7, wd = "Q1936429", n = "Whirlpool[s]" }, -- incl. hot tub
kitchen = { g = 7, wd = "Q43164", n = "Küche[n]" }, -- usable for guest, usually in the room
minibar = { g = 7, wd = "Q1191522", n = "Minibar[s]" },
phone = { g = 7, wd = "Q11035", n = "Telefon[e]" },
safe = { g = 7, wd = "Q471898", n = "Safe[s]" },
shower = { g = 7, wd = "Q7863", n = "Dusche[n]" },
terrace = { g = 7, wd = "Q641406", n = "Terrasse[n]" },
tv = { g = 7, wd = "Q8075", n = "Fernseher[], TV" },
-- cuisine by ethnicity
african = { g = 8, wd = "Q386284", n = "afrikanische Küche" },
alsatian = { g = 8, wd = "Q3006870", n = "elsässische Küche" },
american = { g = 8, wd = "Q40578", n = "amerikanische Küche" },
arab = { g = 8, wd = "Q623970", n = "arabische Küche" },
argentinian= { g = 8, wd = "Q579500", n = "argentische Küche" },
asian = { g = 8, wd = "Q728206", n = "asiatische Küche" },
australian = { g = 8, wd = "Q783010", n = "australische Küche" },
austrian = { g = 8, wd = "Q42029", n = "österreichische Küche" },
baden = { g = 8, wd = "Q799087", n = "badische Küche" },
balkan = { g = 8, wd = "Q805060", n = "Balkan-Küche" },
basque = { g = 8, wd = "Q521179", n = "baskische Küche" },
bavarian = { g = 8, wd = "Q458851", n = "bayerische Küche" },
bolivian = { g = 8, wd = "Q3006895", n = "bolivianische Küche" },
brazilian = { g = 8, wd = "Q614394", n = "brasilianische Küche" },
burmese = { g = 8, wd = "Q1187275", n = "burmesische Küche" },
californian= { g = 8, wd = "Q1026802", n = "kalifornische Küche" },
cambodian = { g = 8, wd = "Q139430", n = "kambodschanische Küche" },
cantonese = { g = 8, wd = "Q1154790", n = "kantonesische Küche" },
caribbean = { g = 8, wd = "Q1729345", n = "karibische Küche" },
chinese = { g = 8, wd = "Q10876842", n = "chinesische Küche" },
creole = { g = 8, wd = { "Q85430164", "Q1645076" }, n = "kreolische Küche" },
croatian = { g = 8, wd = "Q1789628", n = "kroatische Küche" },
cypriot = { g = 8, wd = "Q245932", n = "zyprische Küche" },
czech = { g = 8, wd = "Q871595", n = "tschechische Küche" },
danish = { g = 8, wd = "Q1196267", n = "dänische Küche" },
egyptian = { g = 8, wd = "Q1346230", n = "ägyptische Küche" },
english = { g = 8, wd = "Q1261477", n = "englische Küche" },
ethiopian = { g = 8, wd = "Q257508", n = "äthiopische Küche" },
european = { g = 8, wd = "Q579316", n = "europäische Küche" },
franconian = { g = 8, wd = "Q1471192", n = "fränkische Küche" },
french = { g = 8, wd = "Q6661", n = "französische Küche" },
fucha_ryori= { g = 8, wd = "Q10286142", n = "Fucha Ryōri" },
georgian = { g = 8, wd = "Q1199026", n = "georgische Küche" },
german = { g = 8, wd = "Q47629", n = "deutsche Küche" },
greek = { g = 8, wd = "Q744027", n = "griechische Küche" },
home_style = { g = 8, wd = "Q881929", n = "gutbürgerliche Küche" },
hunan = { g = 8, wd = "Q1156889", n = "Hunan-Küche" },
hungarian = { g = 8, wd = "Q264327", n = "ungarische Küche" },
indian = { g = 8, wd = "Q192087", n = "indische Küche" },
indonesian = { g = 8, wd = "Q787497", n = "indonesische Küche" },
international = { g = 8, wd = "Q99522230", n = "internationale Küche" },
iranian = { g = 8, wd = "Q1342397", n = "iranische Küche" },
irish = { g = 8, wd = "Q1068545", n = "irische Küche" },
italian = { g = 8, wd = "Q192786", n = "italienische Küche" },
japanese = { g = 8, wd = "Q234138", n = "japanische Küche" },
jewish = { g = 8, wd = "Q284288", n = "jüdische Küche" },
korean = { g = 8, wd = "Q647500", n = "koreanische Küche" },
latin_american = { g = 8, wd = "Q2707196", n = "lateinamerikanische Küche" },
lebanese = { g = 8, wd = "Q929239", n = "libanesische Küche" },
levantine = { g = 8, wd = "Q765174", n = "levantinische Küche" },
malaysian = { g = 8, wd = "Q772247", n = "malaysische Küche" },
medieval = { g = 8, wd = "Q10886", n = "Mittelalterküche" },
mediterranean = { g = 8, wd = "Q934309", n = "Mittelmeerküche" },
mexican = { g = 8, wd = "Q207965", n = "mexikanische Küche" },
modern = { g = 8, wd = "", n = "moderne Küche" },
national = { g = 8, wd = "Q1968435", n = "Nationalküche" },
nepalese = { g = 8, wd = "Q1194855", n = "nepalesische Küche" },
new_nordic = { g = 8, wd = "Q3345199", n = "New Nordic Cuisine" },
nubian = { g = 8, wd ="Q113827054", n = "nubische Küche" },
oriental = { g = 8, wd = "Q1547037", n = "orientalische Küche" },
pakistani = { g = 8, wd = "Q1089120", n = "pakistanische Küche" },
palestinian= { g = 8, wd = "Q1154594", n = "palästinensische Küche" },
peruvian = { g = 8, wd = "Q749847", n = "peruanische Küche" },
polish = { g = 8, wd = "Q756020", n = "polnische Küche" },
portuguese = { g = 8, wd = "Q180817", n = "portugiesische Küche" },
regional = { g = 8, wd = "Q94951", n = "Regionalküche" },
rhenish = { g = 8, wd = "Q2147761", n = "rheinische Küche" },
russian = { g = 8, wd = "Q12505", n = "russische Küche" },
savoy = { g = 8, wd = "Q3006988", n = "Savoyer Küche" },
shandong = { g = 8, wd = "Q1038209", n = "Shandong-Küche" },
sichuan = { g = 8, wd = "Q691365", n = "Sichuan-Küche" },
south_indian= { g = 8, wd = "Q3595152", n = "südindische Küche" },
spanish = { g = 8, wd = "Q622512", n = "spanische Küche" },
swedish = { g = 8, wd = "Q35623", n = "schwedische Küche" },
swiss = { g = 8, wd = "Q13497", n = "schweizerische Küche" },
swabian = { g = 8, wd = "Q880365", n = "schwäbische Küche" },
syrian = { g = 8, wd = "Q4119264", n = "syrische Küche" },
thai = { g = 8, wd = "Q841984", n = "thailändische Küche" },
thuringian = { g = 8, wd = "Q187477", n = "Thüringer Küche" },
turkish = { g = 8, wd = "Q654493", n = "türkische Küche" },
ukranian = { g = 8, wd = "Q1503789", n = "ukrainische Küche" },
vietnamese = { g = 8, wd = "Q826059", n = "vietnamesische Küche" },
western = { g = 8, wd = "Q16143746", n = "westliche Küche" },
westphalian= { g = 8, wd = "Q2565249", n = "westfälische Küche" },
-- cuisine by type of food
bagel = { g = 9, wd = "Q272502", n = "Bagel" },
barbecue = { g = 9, wd = "Q461696", n = "Barbecue, BBQ" },
bougatsa = { g = 9, wd = "Q895009", n = "Bougatsa" },
buffet = { g = 9, wd = "Q847462", n = "Büffet" },
burger = { g = 9, wd = "Q6663", n = "Burger" },
cake = { g = 9, wd = "Q13276", n = "Kuchen" },
casserole = { g = 9, wd = "Q7724780", n = "Kasserolle" },
chicken = { g = 9, wd = "Q864693", n = "Hühnchen" },
crepe = { g = 9, wd = "Q12200", n = "Crêpe" },
couscous = { g = 9, wd = "Q76605", n = "Couscous" },
curry = { g = 9, wd = "Q164606", n = "Curry" },
dessert = { g = 9, wd = "Q182940", n = "Dessert, Nachspeise" },
donut = { g = 9, wd = "Q192783", n = "Donut" },
empanada = { g = 9, wd = "Q747457", n = "Empanada" },
fish = { g = 9, wd = "Q152", n = "Fisch" },
fish_and_chips = { g = 9, wd = "Q203925", n = "Fish and Chips" },
fried_food = { g = 9, wd = "Q300472", n = "Braten" },
friture = { g = 9, wd = "Q854618", n = "Frittieren" },
grill = { g = 9, wd = "Q853185", n = "Grill" },
gyros = { g = 9, wd = "Q681596", n = "Gyros" },
halal = { g = 9, wd = "Q85536643", n = "halal" },
ice_cream = { g = 9, wd = "Q13233", n = "Eis, Speiseeis" },
kebab = { g = 9, wd = "Q179010", n = "Kebab" },
noodle = { g = 9, wd = "Q192874", n = "Nudeln" },
pancake = { g = 9, wd = "Q44541", n = "Pfannkuchen, Eierkuchen" },
pasta = { g = 9, wd = "Q178", n = "Pasta" },
pie = { g = 9, wd = "Q13360264", n = "Pie" },
pizza = { g = 9, wd = "Q177", n = "Pizza" },
salad = { g = 9, wd = "Q9266", n = "Salat" },
sandwich = { g = 9, wd = "Q28803", n = "Sandwich" },
sausage = { g = 9, wd = "Q131419", n = "Wurst, Würstchen" },
seafood = { g = 9, wd = "Q192935", n = "Meeresfrüchte" },
soba = { g = 9, wd = "Q753910", n = "Soba" },
soup = { g = 9, wd = "Q41415", n = "Suppe" },
steakhouse = { g = 9, wd = "Q3109696", n = "Steakhaus" },
sushi = { g = 9, wd = "Q46383", n = "Sushi" },
tapas = { g = 9, wd = "Q220964", n = "Tapa, Tapas" },
vegan = { g = 9, wd = { "Q181138", "Q20669090" }, n = "vegan" },
vegetarian = { g = 9, wd = { "Q83364", "Q638022" }, n = "vegetarisch" },
wild_game = { g = 9, wd = "Q223930", n = "Wild" },
yakitori = { g = 9, wd = "Q483163", n = "Yakitori" },
-- drinks
alcoholic = { g = 10, wd = "Q154", n = "alkoholische Getränke" },
beer = { g = 10, wd = "Q44", n = "Bier" },
cocktails = { g = 10, wd = "Q134768", n = "Cocktails" },
["non-alcoholic"] = { g = 10, wd = "Q2647467", n = "alkoholfreie Getränke" },
noalcoholic= { g = 10, wd = "Q67426650", n = "keine alkoholischen Getränke" },
wine = { g = 10, wd = "Q282", n = "Wein" },
-- services in restaurants
beer_garden = { g = 11, wd = "Q857909", n = "Biergarten" },
bowling_alley = { g = 11, wd = "Q27106471", n = "Bowlingbahn[en]" },
delivery = { g = 11, wd = { "Q2334804", "Q1824143" }, n = "Lieferung, Freihauslieferung" },
drive_in = { g = 11, wd = "Q14253958", n = "Drive-in" },
drive_through = { g = 11, wd = "Q14253958", n = "Drive-through" }, -- including drive-thru
outdoor_seating = { g = 11, wd = "Q98642678", n = "Sitzplätze im Freien" },
reservation = { g = 11, wd = { "Q2145615", "Q7673285" }, n = "Reservierung" },
self_service = { g = 11, wd = "Q1369310", n = "Selbstbedienung" },
table_service = { g = 11, wd ="Q100805023", n = "mit Bedienung" },
takeaway = { g = 11, wd = "Q154383", n = "zum Mitnehmen" }, -- including "take-out", "to-go", and "carry-out"
-- activity policies (P5023)
-- photography
noflash = { g = 12, wd = "Q51728726", n = "ohne Blitz" },
nophotos = { g = 12, wd = "Q51728721", n = "Fotografieren verboten" },
nosticks = { g = 12, wd = "Q53540617", n = "Selfie-Sticks verboten" },
notripod = { g = 12, wd ="Q108583523", n = "ohne Stativ" },
novideo = { g = 12, wd = "Q66361451", n = "Videografieren verboten" },
permit_for_commercial_photography = { g = 12, wd ="Q113756144", n = "Erlaubnis für gewerbsmäßige Fotografie erforderlich" },
photos_allowed= { g = 12, wd = "Q51728733", n = "Fotografieren erlaubt" },
-- general policies
adults_only = { g = 13, wd ="Q132174927", n = "Adults Only, Erwachsenenhotel" },
animals = { g = 13, wd ="Q105100898", n = "Tiere erlaubt" },
bags_prohibited = { g = 13, wd ="Q113773766", n = "große Taschen verboten" },
cats = { g = 13, wd ="Q105100905", n = "Katzen erlaubt" },
companion_dogs= { g = 13, wd ="Q116343464", n = "Begleithunde erlaubt" },
couples_and_families = { g = 13, wd ="Q136175147", n = "Couples and Families Only" },
couples_only = { g = 13, wd ="Q136175105", n = "Couples Only" },
dogs = { g = 13, wd ="Q105100922", n = "Hunde erlaubt" },
drinking_ban = { g = 13, wd ="Q111986775", n = "Trinkverbot" },
eating_ban = { g = 13, wd ="Q116343890", n = "Essensverbot" },
face_mask_mandatory = { g = 13, wd = "Q97933005", n = "Gesichtsmaske vorgeschrieben" },
families_only = { g = 13, wd ="Q136175123", n = "Families Only, Familienhotel" },
leashed_dogs = { g = 13, wd = "Q66361287", n = "Hunde an der Leine" },
noanimals = { g = 13, wd ="Q105094093", n = "Tiere verboten" },
nobarefoot = { g = 13, wd ="Q135522352", n = "keine Barfüßigkeit" },
nobikes = { g = 13, wd = "Q66361472", n = "Fahrräder verboten" },
nocamping = { g = 13, wd = "Q66361437", n = "Campingverbot" },
nocats = { g = 13, wd ="Q105094244", n = "Katzen verboten" },
nodogs = { g = 13, wd ="Q105094236", n = "Hunde verboten" },
nodrones = { g = 13, wd = "Q66361435", n = "Drohnen verboten" },
nofeeding = { g = 13, wd = "Q5286412", n = "Tiere füttern verboten" },
nohighheels = { g = 13, wd ="Q123013492", n = "Stöckelschuhe verboten" },
nokids = { g = 13, wd = "Q24861437", n = "keine Kinder" },
nolittering = { g = 13, wd = "Q66361444", n = "Müllabladen verboten" },
noloudly = { g = 13, wd ="Q111986810", n = "lautes Sprechen verboten" },
nonsmoking = { g = 13, wd = "", n = "Nichtraucher" },
nopets = { g = 13, wd = "Q66361297", n = "Haustiere verboten" },
notouch = { g = 13, wd = "Q66361307", n = "Berühren verboten" },
pets = { g = 13, wd = "Q66361299", n = "Haustiere erlaubt" },
smoking = { g = 13, wd = "Q18809854", n = "Raucher" },
smoking_ban = { g = 13, wd = "Q751734", n = "Rauchverbot" },
smoking_separated= { g = 13, wd ="Q110090224", n = "Rauchen an abgetrennten Plätzen" },
water_mandatory= { g = 13, wd = "Q66361375", n = "eigenes Wasser zwingend erforderlich" },
-- dress codes:
dress_code = { g = 13, wd = "Q286300", n = "Kleiderordnung" },
smart_casual = { g = 13, wd = "Q7544032", n = "Smart casual" },
decent_clothing = { g = 13, wd = "Q66361332", n = "Angemessene Kleidung erforderlich" },
-- difficulties (routes etc.)
novice = { g = 14, wd = "", n = "Anfänger" },
easy = { g = 14, wd = "", n = "geringe Schwierigkeit" },
intermediate = { g = 14, wd = "", n = "mittlere Schwierigkeit" },
advanced = { g = 14, wd = "", n = "Fortgeschrittene" },
expert = { g = 14, wd = "", n = "Erfahrener" },
freeride = { g = 14, wd = "", n = "Freeride" },
extreme = { g = 14, wd = "", n = "extreme Schwierigkeit" },
},
-- group meanings
g = {
["1"] = "Preisklasse",
["2"] = "Klassifikation",
["3"] = "Hoteltyp",
["4"] = "allgemeine Ausstattung",
["5"] = "Hotelausstattung",
["6"] = "Hoteldienstleistungen",
["7"] = "Raumausstattung",
["8"] = "Speisen nach Herkunft",
["9"] = "Speisen nach Art",
["10"] = "Getränke",
["11"] = "Restaurantdienstleistungen",
["12"] = "Verhaltensanweisungen Fotografie",
["13"] = "Verhaltensanweisungen",
["14"] = "Schwierigkeitsgrade"
},
exclude = { -- do not translate
Q116168276 = "10. Superior Deluxe",
Q1031873 = "aircraft catapult",
Q573970 = "apron",
Q104123038 = "bilingual street name sign",
Q918324 = "control tower",
Q192375 = "hangar",
Q464020 = "instrument landing system",
Q1061299 = "jet bridge",
Q184590 = "runway",
Q774583 = "solar panel",
Q5191724 = "steeple",
Q35473 = "window"
}
}
8rcv59xqb41zhk04l7i6fkmiqko3zy6
Modulo:Marker utilities
828
4807
73249
72507
2026-09-24T10:48:18Z
RolandUnger
168
Update
73249
Scribunto
text/plain
--[[
Functions library for Marker and vCard modules
In non-Wikivoyage projects, sister-project links functions have to be adapted.
]]--
-- require( 'strict' )
local cd = require( 'Module:Coordinates' )
local mg = require( 'Module:Marker utilities/Groups' )
local mi = require( 'Module:Marker utilities/i18n' )
local mm -- MAKI icons
local mt = require( 'Module:Marker utilities/Types' ) -- types to groups like drink, eat, go, see, sleep, ...
local uc -- URL check
local wu = require( 'Module:Wikidata utilities' )
-- module variable and administration
local mu = {
moduleInterface = {
serial = '2026-09-23',
item = 58187612
},
comma = mi.texts.comma,
commaSeparator = mi.texts.commaSeparator
}
-- to keep background color in print
local colorAdjust = { ['-webkit-print-color-adjust'] = 'exact', ['color-adjust'] = 'exact',
['print-color-adjust'] = 'exact' }
-- maintenance tools
function mu.initMaintenance()
mu.invalidParams = {} -- table of unknown parameters
mu.duplicateAliases = {} -- table of duplicate parameter aliases
mu.maintenance = {} -- table of error strings
mu.hints = {} -- table of hint strings
mu.types = mt.types
mu.groups = mg.groups
mu.typeAliases = nil -- table for type aliases. Create on demand
mu.groupAliases = nil -- table for group aliases
end
local function contains( new, ar )
for i = 1, #ar do
if ar[ i ] == new then
return true
end
end
return false
end
function mu.addMaintenance( key, value )
local s = key -- fallback
local tab = mi.maintenance[ key ]
if tab then
s = mi.formats.category:format( tab.category ) ..
( tab.err and mi.formats.error:format( tab.err ) or '' )
if not mi.options.noRecommendations then
s = s .. ( tab.hint and mi.formats.hint:format( tab.hint ) or '' )
end
end
s = value and mw.ustring.format( s, value ) or s
if not contains( s, mu.maintenance ) then
table.insert( mu.maintenance, s )
end
if mi.options.noRecommendations and tab and tab.hint then
s = value and mw.ustring.format( tab.hint, value ) or tab.hint
if not contains( s, mu.hints ) then
table.insert( mu.hints, s )
end
end
end
function mu.getCategories( formatStr )
return wu.getCategories( formatStr )
end
local function getMaintenance()
if #mu.invalidParams == 1 then
mu.addMaintenance( 'unknownParam', mu.invalidParams[ 1 ] )
elseif #mu.invalidParams > 1 then
mu.addMaintenance( 'unknownParams',
table.concat( mu.invalidParams, mu.commaSeparator ) )
end
if #mu.duplicateAliases > 0 then
mu.addMaintenance( 'duplicateAliases',
table.concat( mu.duplicateAliases, mu.commaSeparator ) )
end
return table.concat( mu.maintenance, '' )
end
function mu.makeMaintenance( page, modules )
local r = getMaintenance()
if mi.options.usePropertyCateg then
local m = mi.formats.wikidata -- format string
for i, aModule in ipairs( modules ) do
if aModule then
r = r .. aModule.getCategories( m, mu.hints )
end
end
end
if page.namespace ~= 0 then
-- remove maintenance categories
r = r:gsub( '%[%[[^%]]+%]%]', '' )
end
return r
end
-- general-use functions
function mu.isSet( arg )
return arg and arg ~= ''
end
function mu.convertForSort( s )
s = s:ulower()
for i, obj in ipairs( mi.substitutes ) do
s = mw.ustring.gsub( s, obj.l, obj.as )
end
return s
end
-- replacing decimal separator and inserting group separators
function mu.formatNumber( num )
if mu.isSet( mi.texts.decimalPoint ) and mi.texts.decimalPoint ~= '.' then
num = num:gsub( '%.', mi.texts.decimalPoint )
end
if mu.isSet( mi.texts.groupSeparator ) then
local count
repeat
num, count = num:gsub( '^([-+]?%d+)(%d%d%d)',
'%1%' .. mi.texts.groupSeparator .. '%2' )
until count == 0
end
return num
end
function mu.tableInsert( tab, value )
if mu.isSet( value ) then
table.insert( tab, value )
end
end
-- splitting string s at sep, removing empty substrings
-- sep is a single character separator but no magic pattern character
function mu.textSplit( s, sep )
local result = {}
if type( s ) ~= 'string' then
return result
end
for str in s:gmatch( '([^' .. sep .. ']+)' ) do
mu.tableInsert( result, mw.text.trim( str ) )
end
return result
end
local function encodeSpaces( s )
s = s:gsub( '[_%s]+', '_' )
return s
end
local function removeChars( s, pattern )
s = s:find( pattern ) and s:gsub( pattern, '' ) or s
return s
end
local function replaceWithSpace( s, pattern )
s = s:find( pattern ) and s:gsub( pattern, ' ' ) or s
return s
end
-- Splitting comma separated lists to a table and converting items
function mu.split( s )
local arr = {}
if not mu.isSet( s ) then
return arr
end
for i, str in ipairs( mu.textSplit( s, ',' ) ) do
arr[ encodeSpaces( str ) ] = 1
end
return arr
end
function mu.makeSpan( s, class, isBdi, attr, css )
return tostring( mw.html.create( isBdi and 'bdi' or 'span' )
:addClass( class )
:attr( attr or {} )
:css( css or {} )
:wikitext( s )
)
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 mu.languageSpan( s, titleHint, page, country, addClass )
if not mu.isSet( s ) then
return ''
end
local bdi = mw.html.create( 'bdi' )
:addClass( addClass )
:wikitext( s )
local c = country.lang
if c == '' or c == page.lang then
return tostring( bdi )
end
local dir
local fStr = '%s'
if country.isRTL and not page.isRTL then
dir = 'rtl'
fStr = '‏%s‎'
elseif not country.isRTL and page.isRTL then
dir = 'ltr'
fStr = '‎%s‏'
end
return fStr:format( tostring( bdi
:addClass( 'voy-lang voy-lang-' .. c )
:attr( { title = mw.ustring.format( titleHint , country.langName ),
lang = c, dir = dir } )
) )
end
function mu.addWdClass( isFromWikidata )
return isFromWikidata and ' voy-wikidata-content' or ''
end
function mu.getAliases( tab, key )
local result = {}
if not tab then
return result
end
local v
for k, tb in pairs( tab ) do
v = tb[ key ]
if v then
if type( v ) == 'table' then
for i = 1, #v do
result[ v[ i ] ] = k
end
else
result[ v ] = k
end
end
end
return result
end
function mu.yesno( val )
return mi.yesno[ val:ulower() ]
end
-- check functions
local function emphasize( s )
return mw.ustring.format( mi.texts.emph, s )
end
-- args: template arguments consisting of argument name as key and a value
-- validKeys: table with argument name as key used by the script and
-- a string or a table of strings for argument names used by the local wiki
function mu.checkArguments( templateArgs, validKeys )
local args = {}
if not templateArgs or not validKeys or not next( validKeys ) then
return args
end
local keys = {} -- list of wiki-dependent parameter names
for key, params in pairs( validKeys ) do
if type( params ) == 'string' then
keys[ params ] = key
else
for i = 1, #params do
keys[ params[ i ] ] = key
end
end
end
local targetKey
for key, arg in pairs( templateArgs ) do
targetKey = keys[ key ]
if targetKey then
if args[ targetKey ] then -- prevents duplicates
table.insert( mu.duplicateAliases, emphasize( key ) )
else
args[ targetKey ] = arg
end
else
table.insert( mu.invalidParams, emphasize( key ) )
end
end
-- normalize values
for i, param in ipairs( mi.options.normalizeValues ) do
if mu.isSet( args[ param ] ) then
args[ param ] = replaceWithSpace( args[ param ]:ulower(), '[_%s]+' )
end
end
return args
end
local function removeNS( s, nsTable )
if not s:find( ':', 1, true ) then
return s
end
local t = s
for i = 1, #nsTable do
t = mw.ustring.gsub( t, '^' .. nsTable[ i ] .. ':', '' )
if s ~= t then
return t
end
end
return t
end
function mu.checkCommonsCategory( args )
-- remove namespace from category
if mu.isSet( args.commonscat ) then
args.commonscat = removeNS( args.commonscat, mi.texts.CategoryNS )
end
end
-- checking coordinates
function mu.checkCoordinates( args )
local function clearCoordinates()
args.lat, args.long = '', ''
end
local t
if type( args.lat ) == 'boolean' or type( args.long ) == 'boolean' then
clearCoordinates()
end
if args.lat == '' and args.long == '' then
return
elseif args.lat ~= '' and args.long == '' then
t = args.lat:find( ',', 1, true )
if t then
args.long = mw.text.trim( args.lat:sub( t + 1, #args.lat ) )
args.lat = mw.text.trim( args.lat:sub( 1, t - 1 ) )
end
end
if args.lat == '' or args.long == '' then
clearCoordinates()
mu.addMaintenance( 'wrongCoord' )
return
end
local dms = false
t = tonumber( args.lat )
if t then
args.lat = math.abs( t ) <= 90 and t or ''
else
t = cd.toDec( args.lat, 'lat', 6 )
args.lat = t.error == 0 and t.dec or ''
dms = args.lat ~= ''
end
if args.lat ~= '' then
t = tonumber( args.long )
if t then
args.long = ( t > -180 and t <= 180 ) and t or ''
else
t = cd.toDec( args.long, 'long', 6 )
args.long = t.error == 0 and t.dec or ''
dms = dms or args.long ~= ''
end
end
if args.lat == '' or args.long == '' then
clearCoordinates()
mu.addMaintenance( 'wrongCoord' )
elseif dms then
mu.addMaintenance( 'dmsCoordinate' )
end
end
-- check zoom level
function mu.checkZoom( args )
args.zoom = math.floor( tonumber( args.zoom ) or mi.map.defaultZoomLevel )
if args.zoom < 0 or args.zoom > mi.map.maxZoomLevel then
args.zoom = mi.map.defaultZoomLevel
end
end
-- image check
function mu.checkImage( args, entity )
if type( args.image ) == 'boolean' or args.image == '' then
return
end
-- formal checks
if args.image:find( '^https?:' ) then
args.image = ''
else
-- remove namespace
args.image = removeNS( args.image, mi.texts.FileNS )
local extensionExists = false
local im = args.image:lower()
for i = 1, #mi.fileExtensions do
if im:find( '%.' .. mi.fileExtensions[ i ] .. '$' ) then
extensionExists = true
break
end
end
if not extensionExists then
args.image = ''
end
end
if args.image == '' then
mu.addMaintenance( 'wrongImgName' )
return
end
local alreadyChecked = false
if mi.options.mediaCheck and args.image ~= '' then
if not mi.options.WDmediaCheck and entity then
-- check if image is stored in Wikidata
local imgs = wu.getValues( entity, mi.properties.image, nil )
for i = 1, #imgs do
if imgs[ i ] == args.image then
alreadyChecked = true
break
end
end
end
if not alreadyChecked then
-- expensive function call
local title = mw.title.new( 'Media:' .. args.image )
if not title or not title.exists then
mu.addMaintenance( 'missingImg', args.image )
args.image = ''
end
end
end
end
function mu.checkStatus( args )
args.statusTable = {}
local hash = {}
if mu.isSet( args.status ) then
local statusAliases = mu.getAliases( mi.statuses, 'alias' )
for i, t in ipairs( mu.textSplit( args.status, ',' ) ) do
t = encodeSpaces( t )
t = statusAliases[ t ] or t
if mi.statuses[ t ] then
if not hash[ t ] then
table.insert( args.statusTable, t )
hash[ t ] = 'x'
end
else
mu.addMaintenance( 'unknownStatus' )
end
end
if #args.statusTable > 1 then
table.sort( args.statusTable,
function( a, b )
local at = mi.statuses[ a ]
local bt = mi.statuses[ b ]
return ( at.g < bt.g ) or ( at.g == bt.g and a < b )
end
)
end
end
end
function mu.checkStyles( args )
if mu.isSet( args.styles ) then
if mi.nameStyles[ args.styles:lower() ] then
args.styles = args.styles:lower()
args.styleClass = ' voy-listing-name-style-' .. args.styles
args.styles = mi.nameStyles[ args.styles ]
end
else
args.styles = nil
end
end
function mu.checkId( args )
if mu.isSet( args.id ) and mu.isSet( args.wikidata ) then
mu.addMaintenance( 'wikidataWithId' )
args.id = ''
end
if mu.isSet( args.id ) and args.id:find( '[!-,.-/:-?[-^{-\127%z\1-\31]' ) then
mu.addMaintenance( 'wrongId' )
args.id = ''
end
end
function mu.checkLength( s, min, max )
return #s >= ( min or 0 ) and #s <= ( max or 1000 )
end
-- groups translation for map legend into Wiki language
local function translateGroup( group )
if not mu.isSet( group ) then
group = mt.types.error.group
end
local t = mg.groups[ group ]
if t then
t = t.map or t.label or t.alias or group
if type( t ) == 'table' then
t = t[ 1 ]
end
return t
end
return group
end
local function getTypeFromTypeAliases( aType )
if not mu.typeAliases then
mu.typeAliases = mu.getAliases( mt.types, 'alias' )
end
return mu.typeAliases[ aType ]
end
local function getGroupFromGroupAliases( group )
if not mu.groupAliases then
mu.groupAliases = mu.getAliases( mg.groups, 'alias' )
end
return mu.groupAliases[ group ]
end
-- getting marker type and group
function mu.checkTypeAndGroup( args )
local s
args.typeTable = {}
args.subtypeTable = {}
-- check group
if mu.isSet( args.group ) then
mu.addMaintenance( 'parameterUsed', 'group' )
s = mg.groups[ args.group ]
if not s then
s = getGroupFromGroupAliases( args.group )
if s then
args.group = s
s = mg.groups[ args.group ]
end
end
if not s then
mu.addMaintenance( 'unknownGroup' )
args.group = ''
elseif s.is and s.is == 'color' and mi.options.useTypeCateg then
mu.addMaintenance( 'group', args.group )
end
end
-- check type
if not mu.isSet( args.type ) then
args.type = mt.types.error.group
mu.addMaintenance( 'missingType' )
elseif args.type == mt.types.error.group then
mu.addMaintenance( 'unknownType', args.type )
end
if args.type == mt.types.error.group then
args.group = mt.types.error.group
else
-- split seperate types and analyse them
for i, t in ipairs( mu.textSplit( args.type, ',' ) ) do
-- try to find the type t in types or groups
t = encodeSpaces( t )
if not mt.types[ t ] then
t = getTypeFromTypeAliases( t ) or getGroupFromGroupAliases( t ) or t
end
s = mg.groups[ t ]
if s then -- type is a group itself
if s.is and s.is == 'color' then
if mi.options.excludeColorTypes then
args.group = mt.types.error.group
mu.addMaintenance( 'unknownType', t )
else
mu.addMaintenance( 'typeIsColor' )
end
elseif not mi.options.noTypeMsgs then
mu.addMaintenance( 'typeIsGroup' )
end
if args.group == '' then
args.group = t
end
else
s = mt.types[ t ]
if s then
if args.group == '' then
args.group = s.group
end
if mu.isSet( s.subtype ) then
table.insert( args.subtypeTable, t )
end
else
args.group = mt.types.error.group
mu.addMaintenance( 'unknownType', t )
end
end
table.insert( args.typeTable, t )
if mi.options.useTypeCateg then
mu.addMaintenance( 'type', t )
end
end
args.type = table.concat( args.typeTable, ',' )
end
args.groupTranslated = translateGroup( args.group )
mu.getColor( args )
end
local function isUrl( url )
uc = uc or require( 'Module:UrlCheck' )
return uc.isUrl( url, mi.options.skipPathCheck )
end
-- url check in args
function mu.checkUrl( args )
if not mu.isSet( args.url ) then
return
end
local c = isUrl( args.url ) -- getting result code
if c > 2 then
mu.addMaintenance( 'wrongUrl' )
args.url = ''
elseif c == 2 then -- URL contains IP address
mu.addMaintenance( 'urlWithIP' )
else
if args.url:find( 'twitter.com', 1, true ) then -- old X url
mu.addMaintenance( 'urlIsSocialMedia' )
args.url = ''
else
for i = 1, #mi.services do
if args.url:find( '[./]' .. mi.services[ i ].key .. '.com' ) then
mu.addMaintenance( 'urlIsSocialMedia' )
args.url = ''
break
end
end
end
end
end
-- type and group functions
-- getting a set of parameters for a given type
function mu.getTypeParams( aType )
return mt.types[ aType ]
end
function mu.idToType( id )
if not mu.typeIds then
mu.typeIds = mu.getAliases( mt.types, 'wd' ) -- Q id to type table
end
return mu.typeIds[ id ]
end
function mu.getTypeLabel( id )
if not mu.isSet( id ) then
return ''
end
if id:match( '^Q%d+$' ) then
id = mu.idToType( id )
if not id then
return ''
end
else
id = encodeSpaces( id )
end
local at, t
t = mt.types[ id ]
if not t then
t = getTypeFromTypeAliases( id )
t = t and mt.types[ t ]
end
if t then
t = t.label or id
at = t:find( ',', 1, true )
if at then
t = t:sub( 1, at - 1 )
end
else
t = replaceWithSpace( id, '_' )
end
return t
end
function mu.typeExists( aType )
return mt.types[ aType ] and aType or getTypeFromTypeAliases( aType )
end
-- check if the specified group can have events
function mu.groupWithEvents( group )
return mg.groups[ group ] and mg.groups[ group ].withEvents
end
-- see: https://www.w3.org/TR/WCAG20/#relativeluminancedef
local function hexToLinear( hex )
hex = tonumber( hex, 16 ) / 255.0
if hex <= 0.03928 then
return hex / 12.92
else
return ( ( hex + 0.055 ) / 1.055 ) ^ 2.4
end
end
-- relative luminance of a color
-- 6 digit hex color
local function hexToLuminance( color )
local r = hexToLinear( color:sub( 1, 2 ) )
local g = hexToLinear( color:sub( 3, 4 ) )
local b = hexToLinear( color:sub( 5, 6 ) )
return 0.2126 * r + 0.7152 * g + 0.0722 * b
end
local function isInverse( backgroundColor )
-- the luminance threshold should be greater than 0.2848 (i.e. magenta,
-- error, #FF00FF) and smaller than 0.4
-- the value chosen of 0.386 corresponds to a light magenta (#FF69FF) which
-- seems to be used for Wikimedia's map server
-- see: https://github.com/wikimedia/makizushi/blob/master/lib/color.js
local luminanceThreshold = 0.386
backgroundColor = backgroundColor:sub( 2 ) -- remove #
:gsub( '^(%x)(%x)(%x)$', '%1%1%2%2%3%3' )
return hexToLuminance( backgroundColor ) > luminanceThreshold
end
-- getting color from group in args
function mu.getColor( args )
local c = mg.groups[ args.group ] or mg.groups[ 'error' ]
args.color = c.color
args.inverse = isInverse( c.color )
end
-- Splitting comma separated lists to a table of key items
-- checking items with allowed key values of validValues table
local function splitAndCheck( s, validValues )
local values = {}
if not validValues then
return values, ''
end
local errors = {}
for item, v in pairs( mu.split( s ) ) do
-- value check
if validValues[ item ] then
values[ item ] = 1
else
table.insert( errors, item )
end
end
return values, table.concat( errors, mu.commaSeparator )
end
local function setCopyMarker( args, show )
if show.copy and ( mu.isSet( args.copyMarker ) or not mu.isSet( args.wikidata ) ) then
show.copy = nil
mu.addMaintenance( 'deleteShowCopy' )
end
if show.copy then
args.copyMarker = args.wikidata
end
if mu.isSet( args.copyMarker ) then
show.symbol = nil
end
end
-- treatment of social media services if Wikidata is available
local function setSocialMedia( args, value )
for i, service in ipairs( mi.services ) do
args[ service.key ] = value
end
end
function mu.getShow( default, args, validValues )
local show = mu.split( default )
local add, err = splitAndCheck( args.show, validValues )
if err ~= '' then
mu.addMaintenance( 'unknownShow', err )
end
-- maintenance
if add.inline then
show.inlineSelected = true
mu.addMaintenance( 'showInlineUsed' )
end
if add.poi then
mu.addMaintenance( 'showPoiUsed' ) -- is default
end
-- overwriting defaults
if add.none or add.coord or add.poi or add.all then
show.all, show.coord, show.poi = nil, nil, nil
end
-- merge show with add values
for key, value in pairs( add ) do
show[ key ] = value
end
if show.none then
show.none, show.all, show.coord, show.poi = nil, nil, nil, nil
end
if show.all then
show.all = nil
show.coord, show.poi = 1, 1
end
if show.noname then
show.noname, show.name = nil, nil
else
show.name = 1
end
setCopyMarker( args, show )
if args.wikidata ~= '' then
if show.socialmedia then
setSocialMedia( args, 'y' )
elseif show.nosocialmedia then
setSocialMedia( args, 'n' )
end
end
if not show.nosocialmedia then
show.socialmedia = 1
end
return show
end
-- removing line breaks and controls from parameter strings
function mu.removeCtrls( s, onlyInline )
local descrDiv = false -- div tag instead of span tag for description needed?
-- remove controls from tags
s = s:gsub( '(<[^>]+>)', function( t )
return replaceWithSpace( t, '[%z\1-\31]' )
end )
local t = removeChars( s, '[%z\1-\8\11\12\14-\31]' ) -- ctrl chars
t = replaceWithSpace( t, '[\9]' ) -- horizontal tab
t = replaceWithSpace( t, '</br%s*>' )
if onlyInline then
t = replaceWithSpace( t, '<br[^/>]*/*>' ) -- no line breaks
t = replaceWithSpace( t, '</*p[^/>]*/*>' ) -- no paragraphs
t = replaceWithSpace( t, '</*div[^/>]*/*>' ) -- no divs
t = mw.text.trim( replaceWithSpace( t, '[\10\13]' ) ) -- no line breaks
-- not %c because \127 is used for Mediawiki tags (strip markers `UNIQ)
else
descrDiv = t:find( '[\10\13]' ) or t:find( '<br[^/>]*/*>' ) or
t:find( '<p[^/>]*>' ) or t:find( '<div[^/>]*>' )
end
-- remove LTR and RTL marks
t = mw.ustring.gsub( t, '[]+', '' )
if descrDiv then
-- unify line breaks to Linux mode
t = t:gsub( '\13\10', '\10' ):gsub( '\13', '\10' )
-- replace line breaks by <br> in block mode
t = t:gsub( '([^>%]\10])\10+([^<%[\10])', '%1<br class="voy-listing-next-paragraph" />%2' )
end
return replaceWithSpace( t, '%s%s+' ), descrDiv
end
-- fetch data from Wikidata
function mu.getCoordinatesFromWikidata( args, fromWikidata, entity )
if not entity or ( args.lat ~= '' and args.long ~= '' ) then
return
end
-- center coordinates from Wikidata
local c = wu.getValue( entity, mi.properties.centerCoordinates )
if c == '' then
-- coordinates from Wikidata
c = wu.getValue( entity, mi.properties.coordinates )
end
-- search for headquarters location
if c == '' then
local tab = wu.getValuesWithQualifiers( entity, mi.properties.headquartersLoc,
nil, mi.properties.coordinates )
if #tab > 0 then
tab = tab[ 1 ][ mi.properties.coordinates ]
if tab and #tab > 0 then
c = tab[ 1 ]
mu.addMaintenance( 'headquarters' )
args.coordFrom = 'headquarters'
end
end
end
if c ~= '' then
args.lat, args.long = c.latitude, c.longitude
fromWikidata.lat = true
end
end
local function typeSearch( p31 )
-- p31: array of Wikidata values
if not p31 or #p31 == 0 then
return ''
end
local firstStep = true
local function compareLabels( ar )
if not ar then
return nil
elseif type( ar ) == 'string' then
ar = { ar }
end
for i, value in ipairs( ar ) do
if mu.isSet( value ) then
value = ( encodeSpaces( value ) )
if mt.types[ value ] then
return value
end
end
end
return nil
end
local function compareIds( ar )
local id, t
for i = 1, #ar do
id = ar[ i ].id
-- md: indexed array of q id - types relations
t = mu.idToType( id )
if t then
return t
end
-- checking English label and aliases
t = compareLabels( mw.wikibase.getLabelByLang( id, 'en' ) )
or compareLabels( wu.getAliases( id, 'en' ) )
if t then
if firstStep and not mi.options.noTypeMsgs then
firstStep = false
mu.addMaintenance( 'typeFromWDchain' )
end
return t
end
end
return nil
end
local aType = compareIds( p31 ) -- check p31 ids first, maybe step 2 is not nessary
if aType then
return aType
end
-- now functions becomes expensive because of multiple wu.getValues calls
local id, ids
firstStep = false
for i = 1, #p31 do -- step 2: analyse P279 chains of first ids
id = p31[ i ].id -- start id
local j = 0
repeat
ids = wu.getValues( id, mi.properties.subclassOf, nil )
if #ids > 0 then
aType = compareIds( ids )
if aType then
if not mi.options.noTypeMsgs then
mu.addMaintenance( 'typeFromWDchain' )
end
return aType
end
id = ids[ 1 ].id
end
j = j + 1
-- limit: maximum levels to analyse
until j >= mi.options.searchLimit or #ids == 0
end
return ''
end
function mu.getTypeFromWikidata( args, entity )
if mu.isSet( args.type ) then
return
end
local p31 = wu.getValues( entity, mi.properties.instanceOf )
if #p31 == 0 then
p31 = wu.getValues( entity, mi.properties.subclassOf )
end
args.type = typeSearch( p31 )
end
function mu.getCommonsCategory( args, entity )
-- getting commonscat from commonswiki sitelink before P373
-- because sitelink is checked by Wikidata
if type( args.commonscat ) == 'boolean' then
args.commonscat = ''
end
local t = wu.getSitelink( entity, 'commonswiki' ) or ''
if t:match( '^Category:.+$' ) then
t = t:gsub( '^[Cc]ategory:', '' )
else
t = wu.getValue( entity, mi.properties.commonsCategory )
if t == '' then
local id = wu.getId( entity, mi.properties.mainCategory )
if id ~= '' then
t = wu.getSitelink( id, 'commonswiki' ) or ''
t = t:gsub( '^[Cc]ategory:', '' )
end
end
end
if t ~= '' and args.commonscat ~= '' then
mu.addMaintenance( 'commonscatWD' )
end
if args.commonscat == '' then
args.commonscat = t
end
end
function mu.getLangTable( wikiLang, localLang )
local langs = { wikiLang }
for i, lang in ipairs( mi.langs ) do
table.insert( langs, lang )
end
if mu.isSet( localLang ) and localLang ~= wikiLang then
table.insert( langs, localLang )
end
return langs
end
-- getting names from Wikidata
function mu.getNamesFromWikidata( args, fromWikidata, page, country, entity )
-- getting official names
local officialNames =
wu.getMonolingualValues( entity, mi.properties.officialName )
args.officialName = officialNames[ country.lang ] or
wu.getLabel( entity, country.lang, true ) or ''
if type( args.name ) == 'boolean' or args.name == '' then
args.name = ''
local langs = mu.getLangTable( page.lang )
for i, lang in ipairs( langs ) do
args.name = officialNames[ lang ]
if args.name then
break
end
end
-- if failed then get labels
if not mu.isSet( args.name ) then
for i, lang in ipairs( langs ) do
args.name = wu.getLabel( entity, lang, true ) -- no fallback
if args.name then
break
end
end
args.name = args.name or ''
end
if args.name ~= '' then
-- remove brackets at the end
args.name = args.name:gsub( '%s*%([^%(%)]*%)$', '' )
mu.addMaintenance( 'nameFromWD' )
fromWikidata.name = true
end
end
-- get local name if no name is available
if args.name == '' and
not ( type( args.nameLocal ) == 'string' and args.nameLocal ~= '' ) then
args.nameLocal = true
-- no local name if country and wiki language are identical
elseif args.nameLocal == true and page.lang == country.lang then
args.nameLocal = ''
end
if type( args.nameLocal ) == 'string' and args.nameLocal ~= '' then
-- keeping local name in any case for html data
args.addNameLocal = args.nameLocal
return
end
local nameLocal = officialNames[ country.lang ] or ''
if nameLocal == '' then
nameLocal = wu.getLabel( entity, country.lang, true ) or ''
end
nameLocal = nameLocal:gsub( '%s*%([^%(%)]*%)$', '' )
if args.nameLocal == true then
args.nameLocal = ''
if args.name == '' and nameLocal ~= '' then
args.name = nameLocal
nameLocal = ''
mu.addMaintenance( 'nameFromWD' )
fromWikidata.name = true
end
-- prevent local data if wiki language == country language
if page.lang ~= country.lang and nameLocal ~= '' then
args.nameLocal = nameLocal
if args.name:ulower() == args.nameLocal:ulower() then
args.nameLocal = ''
else
fromWikidata.nameLocal = true
end
end
elseif page.lang ~= country.lang and args.name ~= nameLocal then
args.addNameLocal = nameLocal
end
end
-- getting link to Wikivoyage
function mu.getArticleLink( args, entity, page )
local title, isRedirect =
wu.getCheckedSitelink( entity, page.lang .. page.globalProject )
if title and title ~= page.text then
args.wikiPage = title
if isRedirect == true then
args.linkIsRedirect = true
end
end
end
-- marker functions
-- returns a single data set from Module:Marker utilities/Maki icons
local function getMaki( key )
mm = mm or require( 'Module:Marker utilities/Maki icons' )
key = key:lower():gsub( '[_%s]+', '-' )
return mm.icons[ key ]
end
local function getMakiIconId( key )
if not mu.isSet( key ) then
return nil
end
key = key:lower():gsub( '[_%s]+', '-' )
if getMaki( key ) then
return key
end
key = mt.types[ key ] and mt.types[ key ].icon
if key and getMaki( key ) then
return key
end
return nil
end
local function addIconToMarker( args )
args.text = ( '[[File:Maki7-%s.svg|x14px|link=|class=noviewer]]' ):format( args.symbol )
args.isIcon = true
end
-- distinguishing marker symbols, default: number
local function makeMarkerProperties( args, show )
args.symbol = args.symbol or ''
local noSymbol = args.symbol == ''
if args.symbol == '' and show.poi and show.symbol then
args.symbol = getMakiIconId( args.typeTable[ 1 ] ) or ''
end
local isIcon = getMaki( args.symbol )
if args.symbol == '' or args.symbol == 'number' then
args.symbol = '-number-' .. args.group
elseif args.symbol == 'letter' then
args.symbol = '-letter-' .. args.group
elseif args.symbol:len() == 1 and args.symbol:match( '%w' ) then
args.text = args.symbol:upper()
mu.addMaintenance( 'numberUsed' )
elseif args.symbol ~= '' and args.text == '' and isIcon then
addIconToMarker( args )
elseif args.symbol ~= '' and not isIcon then
args.text = mi.texts.closeX
args.isIcon = true
args.group = 'error'
mu.getColor( args )
mu.addMaintenance( noSymbol and 'unknownMAKI' or 'unknownIcon' )
end
end
-- making marker symbol
function mu.makeMarkerSymbol( args, show, frame )
local title = args.givenName.all
local extraClasses = args.group == 'error' and ' voy-listing-map-is-error' or ''
if mu.isSet( args.copyMarker ) then
local copyClass = 'voy-listing-map voy-copy-marker plainlinks printNoLink' ..
extraClasses
return tostring( mw.html.create( 'span' )
:addClass( copyClass )
:css( colorAdjust )
-- display will be replaced by [[MediaWiki:Gadget-GeneralChanges.js]] script
:css( { display = 'none' } )
:attr( { ['data-copy-marker-attribute'] = args.copyMarker:match( 'Q%d+' )
and 'data-wikidata' or 'data-name', title = mi.texts.tooltip,
['data-copy-marker-content'] = args.copyMarker } )
)
end
makeMarkerProperties( args, show )
if args.isIcon then
extraClasses = extraClasses .. ' voy-listing-map-is-symbol' ..
-- set image color to white
( args.inverse and '' or ' voy-listing-map-inverse-img' )
end
local lon = tonumber( args.long )
local lat = tonumber( args.lat )
local tagArgs = {
zoom = tonumber( args.zoom ),
latitude = lat,
longitude = lon,
show = mg.showAll,
}
if mu.isSet( args.text ) then
tagArgs.text = args.text
tagArgs.class = 'no-icon'
end
if mu.isSet( args.mapGroup ) then
tagArgs.group, tagArgs.show = args.mapGroup, args.mapGroup
else
tagArgs.group = args.groupTranslated
end
if mu.isSet( args.image ) then
tagArgs.description = '[[File:' .. args.image .. '|100x100px|' .. title .. ']]'
end
local geoJson = {
type = 'Feature',
geometry = {
type = 'Point',
coordinates = { lon, lat }
},
properties = {
title = title,
description = tagArgs.description,
['marker-symbol'] = args.symbol,
['marker-color'] = args.color,
['marker-size'] = 'medium',
}
}
return tostring( mw.html.create( 'span' )
:addClass( 'voy-listing-map plainlinks printNoLink' .. extraClasses )
:attr( 'title', mi.texts.tooltip )
:css( colorAdjust )
-- color for print mode
:css( { ['background-color'] = args.color, color = args.inverse and '#000' or '#fff' } )
-- frame:extensionTag is expensive
:wikitext( frame:extensionTag( 'maplink', mw.text.jsonEncode( geoJson ), tagArgs ) )
)
end
-- icon functions
function mu.makeStatusIcons( args )
local result = ''
for i, v in ipairs( args.statusTable ) do
result = result .. mu.makeSpan( ' ', 'voy-listing-status voy-listing-status-' .. v,
false, { title = mi.statuses[ v ].label }, colorAdjust )
if mi.statuses[ v ].category then
result = result .. ( '[[Category:%s]]' ):format( mi.statuses[ v ].label )
end
end
return result
end
function mu.addLinkIcon( classes, link, title, text, mainClass )
local span = mu.makeSpan( ' ', nil, false, { title = title, ['data-icon'] = text },
colorAdjust ) -- space to keep the span tag
local lFormat = ( link:find( '^https?://' ) or link:find( '^//' ) )
and '[%s %s]' or '[[%s|%s]]'
local iconLink = mw.ustring.format( lFormat, link, span )
-- add leading space for wikidata icon which is necessary if visible
if text == 'wikidata' then
iconLink = mu.makeSpan( ' ', 'voy-listing-icon-with-space', true ) .. iconLink
end
mainClass = mainClass or 'voy-listing-icon'
return mu.makeSpan( iconLink, mainClass .. ' ' .. classes )
end
-- adding linked sister icons
local function addSisterIcons( icons, sisters, name, id )
local icon
for i, key in ipairs( { 'wikivoyage', 'wikipedia', 'commons', 'maps', 'wikidata' } ) do
if mu.isSet( sisters[ key ] ) then
icon = mu.addLinkIcon( 'voy-listing-sister-' .. key, sisters[ key ],
mw.ustring.format( mi.iconTitles[ key ], name, id ), key )
table.insert( icons, icon )
end
end
-- return true if only Wikidata icon
return mu.isSet( sisters.wikidata ) and #icons == 1
end
-- getting sister project links
local function getWikiLink( langArray, wiki, entity, wikilang )
local prefix = wiki == 'wiki' and 'w:' or 'voy:'
local link
for i, lang in ipairs( langArray ) do
if lang ~= '' then
link = wu.getFilteredSitelink( entity, lang .. wiki )
if link then
prefix = prefix .. ( lang ~= wikilang and ( lang .. ':' ) or '' )
return prefix .. link
end
end
end
return ''
end
-- adding Wikimedia sister project icons
local function makeSisterIcons( icons, args, page, country, entity, show )
local sisters = {
commons = '', -- link to Commons category
maps = '', -- link to Map Sources
wikidata = '', -- link to Wikidata
wikipedia = '', -- link to Wikipedia
wikivoyage = '', -- link to another branch, usually en, as a sister link
}
if not show.nositelinks then
if mu.isSet( args.wikipedia ) then
sisters.wikipedia = 'w:' .. args.wikipedia
end
if mu.isSet( args.wikidata ) then
local langs = mu.getLangTable( page.lang, country.lang )
if sisters.wikipedia == '' then
sisters.wikipedia = getWikiLink( langs, 'wiki', entity, page.lang )
end
if args.wikiPage == '' then
table.remove( langs, 1 ) -- exclude page.lang
sisters.wikivoyage = getWikiLink( langs, page.globalProject, entity, page.lang )
if sisters.wikivoyage ~= '' then
mu.addMaintenance( 'linkToOtherWV' )
end
end
end
if args.commonscat ~= '' then
sisters.commons = 'c:Category:' .. args.commonscat
end
end
if mu.isSet( args.wikidata ) then
sisters.wikidata = 'd:' .. args.wikidata
end
if args.lat ~= '' and args.long ~= '' then
sisters.maps = mw.ustring.format( mi.map.coordURLformat, page.lang, args.latMs,
args.longMs, mw.uri.encode( country.extra ), mw.uri.encode( args.givenName.name ) )
end
return addSisterIcons( icons, sisters, args.givenName.name, args.wikidata )
end
-- creating social media icons including value check
local function makeSocial( icons, args, fromWikidata, name )
local domain, span, t, which
for i, service in ipairs( mi.services ) do
-- check values first
t = args[ service.key ] or ''
domain = type( service.url ) == 'string' and service.url or service.url[ 1 ]
domain = domain:gsub( 'com/.*', 'com/' )
if t ~= '' then
if t:match( '^http' ) then
if not t:find( 'https', 1, true ) then
t = t:gsub( '^http', 'https' )
mu.addMaintenance( 'wrongSocialUrl', service.key )
end
if isUrl( t ) > 1 or
not t:match( '^' .. domain .. '.+$' ) then
t = ''
mu.addMaintenance( 'wrongSocialUrl', service.key )
end
if t ~= '' and not fromWikidata[ service.key ] then
mu.addMaintenance( 'socialUrlUsed', service.key )
end
else
local match = false
local sp = service.pattern
if type( sp ) == 'string' then
sp = { sp }
end
for j = 1, #sp do
if mw.ustring.match( t, sp[ j ] ) then
match = true
which = j
break
end
end
if not match then
t = ''
mu.addMaintenance( 'wrongSocialId', service.key )
end
end
end
args[ service.key ] = t
-- create symbol link
if t ~= '' then
if not t:find( domain, 1, true ) then
-- multiple service urls
local formatStr = type( service.url ) == 'string' and service.url or
service.url[ which ]
t = mw.ustring.format( formatStr, t )
end
span = mu.addLinkIcon( 'voy-listing-social-media-' ..
service.key .. mu.addWdClass( fromWikidata[ service.key ] ), t,
mw.ustring.format( mi.iconTitles[ service.key ], name ), service.key,
'voy-listing-social-media' )
table.insert( icons, span )
end
end
end
function mu.makeIcons( args, page, country, entity, show, fromWikidata )
local icons = {}
if mi.options.showSisters then
makeSisterIcons( icons, args, page, country, entity, show )
end
if show.socialmedia then
makeSocial( icons, args, fromWikidata, args.givenName.name )
end
return table.concat( icons, '' )
end
-- analyzing names for invalid parts
local function checkMalformedNames( args )
local s
for i, key in ipairs( { 'name', 'nameMap', 'nameLocal' } ) do
if mu.isSet( args[ key ] ) then
s = args[ key ]
-- remove italic and bold
args[ key ] = args[ key ]:gsub( "'''?", '' )
-- names shall not contain tags
:gsub( '<[^<>]*>', '' )
:gsub( '[<>]+', '' )
-- remove links
:gsub( '%[%s*http[^%s%]]+%s*%]', '' )
:gsub( '%[%s*http[^%s%]]+%s+([^%]]*)%]', '%1' )
:gsub( 'http%S+', '' )
-- remove images
for j = 1, #mi.texts.FileNS do
args[ key ] = mw.ustring.gsub( args[ key ],
'%[%[%s*' .. mi.texts.FileNS[ j ] .. '%s*:[^%[%]]*%]%]', '')
end
if s ~= args[ key ] then
args[ key ] = mw.text.trim( args[ key ] )
mu.addMaintenance( 'malformedName' )
end
args[ key ] = args[ key ]:gsub( '%s%s+', ' ' )
if key ~= 'name' and args[ key ]:find( '[%(%)%[%]{}]' ) and
args.officialName ~= args[ key ] then
mu.addMaintenance( 'nameWithBrackets' )
end
end
end
end
local function removeStars( args )
for i, key in ipairs( mi.options.noStarParams ) do
if mu.isSet( args[ key ] ) and args[ key ]:find( '*', 1, true ) then
args[ key ] = args[ key ]:gsub( '%*+', '' )
args[ key ] = mw.text.trim( args[ key ] )
mu.addMaintenance( 'nameWithStar' )
end
end
end
-- getting name table with linked and unlinked names
local function getName( name, pageTitle )
local r = {
all = '', -- name or linked name
name = '', -- only name
pageTitle = '', -- if pageTitle ~= '' name is already linked
}
if name == '' then
return r
end
local c, s, t
t, c = name:gsub( '^.*%[%[([^%[%]]*)%]%].*$', '%1' )
if c > 0 then -- is or contains wikilink [[...]]
-- name shall not contain characters outside the wikilink
if ( '[[' .. t .. ']]' ) ~= name then
mu.addMaintenance( 'malformedName' )
end
-- analyze wikilink
t = mw.text.trim( t )
r.all = '[[' .. t .. ']]'
s, c = t:gsub( '^.*|(.*)$', '%1' )
if c > 0 then -- is [[...|...]]
r.name = mw.text.trim( s )
r.pageTitle = t:gsub( '^(.*)|.*$', '%1' )
r.pageTitle = mw.text.trim( r.pageTitle )
else
r.name = t
r.pageTitle = t
end
else
r.name = name
r.all = name
if mu.isSet( pageTitle ) then
r.pageTitle = pageTitle
r.all = '[[' .. pageTitle .. '|' .. name .. ']]'
r.fromWD = true
end
end
return r
end
-- create givenName, displayName tables
function mu.prepareNames( args )
local function simplifyString( s, length )
s = mw.ustring.sub( s, 1, length )
s = mw.ustring.gsub( s, "[%.'" .. '"“”„‟«»‘’‚‛‹›]', '' )
s = mw.ustring.gsub( s, '[-‐‑‒–—―]', ' ' )
return s:ulower():gsub( '%s%s+', ' ' )
end
local function removeDuplicate( value1, key2 )
if not mu.isSet( value1 ) or not mu.isSet( args[ key2 ] ) then
return
end
local minLen = math.min( mw.ustring.len( value1 ), mw.ustring.len( args[ key2 ] ) )
if simplifyString( value1, minLen ) == simplifyString( args[ key2 ], minLen ) then
args[ key2 ] = ''
end
end
-- use local name if name is not given
if args.name == '' and args.nameLocal ~= '' then
args.name = args.nameLocal
args.nameLocal = ''
end
if args.name == args.nameMap then
args.nameMap = ''
end
-- missing name
if args.name == '' then
args.name = mi.texts.missingName
mu.addMaintenance( 'missingNameMsg' )
end
if args.langIsWikiLang and mu.isSet( args.nameLocal ) then
args.nameLocal = ''
mu.addMaintenance( 'noLocalParams' )
end
checkMalformedNames( args )
removeStars( args )
-- handling linked names like [[article|text]]
args.displayName = getName( args.name, args.wikiPage )
if mu.isSet( args.nameMap ) then
args.givenName = getName( args.nameMap, args.wikiPage )
else
-- real copy
args.givenName = {}
args.givenName.all = args.displayName.all
args.givenName.name = args.displayName.name
args.givenName.pageTitle = args.displayName.pageTitle
end
-- reset args.linkIsRedirect if Wikidata link is not used
-- args.linkIsRedirect is set by mu.getArticleLink()
if not args.displayName.fromWD then
args.linkIsRedirect = nil
end
if args.givenName.name:find( '[%(%)%[%]{}]' ) and
args.officialName ~= args.givenName.name then
mu.addMaintenance( 'nameWithBrackets' )
end
-- remove identical names
removeDuplicate( args.givenName.name, 'nameLocal' )
removeDuplicate( args.givenName.name, 'alt' )
removeDuplicate( args.givenName.name, 'comment' )
removeDuplicate( args.nameLocal, 'alt' )
removeDuplicate( args.alt, 'comment' )
removeDuplicate( args.directions, 'directionsLocal' )
removeDuplicate( args.address, 'addressLocal' )
end
function mu.prepareCoordinates( args )
args.latDMS, args.latMs = cd.getDMSString( args.lat, 4, 'lat', '', '', mi.map.defaultDmsFormat )
args.longDMS, args.longMs = cd.getDMSString( args.long, 4, 'long', '', '', mi.map.defaultDmsFormat )
end
local function _makeAirport( code, args )
local span = mu.makeSpan( args[ code ],
'voy-listing-' .. code .. '-code' .. mu.addWdClass( true ) )
return mu.makeSpan( mw.ustring.format( mi.texts[ code ], span ),
'voy-listing-airport voy-listing-' .. code )
end
local function makeAirport( args, show )
if show.noairport then
return ''
else
local t = args.type:gsub( ',.*$', '' ) -- only first type
if mt.types[ t ] and not mt.types[ t ].useIATA then
return ''
end
end
if mu.isSet( args.iata ) then
return _makeAirport( 'iata', args )
elseif mu.isSet( args.icao ) then
return _makeAirport( 'icao', args )
else
return ''
end
end
-- creating a list of nick names etc.
local function makeNameAffix( args, page, country, addClass, show )
local result = {}
if mi.options.showLocalData then
if mu.isSet( args.nameLocal ) then
table.insert( result,
mu.languageSpan( args.nameLocal, mi.texts.hintName, page, country,
'voy-listing-name-local' .. addClass ) )
end
if mu.isSet( args.nameLatin ) then
table.insert( result, mu.makeSpan( args.nameLatin,
'voy-listing-name-latin', false, { title = mi.texts.hintLatin,
lang = mu.isSet( country.lang ) and ( country.lang .. '-Latn' ) or nil } ) )
end
end
for i, key in ipairs( { 'alt', 'comment' } ) do
if mu.isSet( args[ key ] ) then
table.insert( result, mu.makeSpan( args[ key ], 'voy-listing-' .. key ) )
end
end
mu.tableInsert( result, makeAirport( args, show ) )
if #result == 0 then
return ''
end
return mu.makeSpan( mu.parentheses( table.concat( result, mu.comma ) ),
'voy-listing-add-names p-nickname nickname' )
end
-- replace brackets in names
local function replaceBrackets( s )
s = s:gsub( '%[', '[' ):gsub( '%]', ']' )
return s
end
-- creating (linked) name and its affix
function mu.makeName( result, args, show, page, country, nameClass, localClass )
local c, s
local r = {}
nameClass = nameClass ..
( args.displayName.fromWD and ' voy-listing-link-from-wd' or '' )
-- clear redirect wiki link if required
if args.linkIsRedirect and not show.wikilink then
args.displayName.pageTitle = ''
args.displayName.all = args.displayName.name
args.linkIsRedirect = nil
nameClass = nameClass .. ' voy-listing-unused-redirect'
mu.addMaintenance( 'unusedRedirect' )
end
if args.linkIsRedirect then
nameClass = nameClass .. ' mw-redirect voy-listing-link-is-redirect'
mu.addMaintenance( 'linkIsRedirect' )
end
if mu.isSet( args.url ) and args.displayName.pageTitle == '' then
s = '[' .. args.url .. ' '
.. replaceBrackets( args.displayName.name ) .. ']'
else
s = args.displayName.all
end
if mu.isSet( args.nameExtra ) then
args.nameExtra, c = args.nameExtra:gsub( "'''?", '' )
if c > 0 then
mu.addMaintenance( 'malformedName' )
end
end
if mu.isSet( args.nameExtra ) then
s = s .. ' ' .. args.nameExtra
end
-- insert name
if s ~= '' then
local attr = { style = args.styles }
s = mu.makeSpan( s, 'voy-listing-name p-name fn org' .. nameClass ..
( args.styleClass and args.styleClass or '' ), true, attr )
table.insert( r, s )
end
-- insert separate url icon
if mu.isSet( args.url ) and args.displayName.pageTitle ~= '' then
-- both article and web links
table.insert( r, mu.addLinkIcon( 'voy-listing-url', args.url,
mi.iconTitles.internet, 'internet' ) )
end
-- insert name affix
mu.tableInsert( r, makeNameAffix( args, page, country, localClass, show ) )
if #r > 0 then
table.insert( result, table.concat( r, mi.texts.space ) )
end
end
function mu.parentheses( s, trim )
if not mu.isSet( s ) then
return ''
end
local formatter = mi.texts.parentheses
if trim then
formatter = mw.text.trim( formatter )
end
return mw.ustring.format( formatter, s )
end
-- getting DMS coordinates
function mu.dmsCoordinates( args, page, country, fromWD, noBrackets )
local function coordSpan( title, text )
return mu.makeSpan( text, 'coordStyle', false, { title = title } )
end
local r = '[' .. mw.ustring.format( mi.map.coordURLformat, page.lang, args.latMs, args.longMs,
mw.uri.encode( country.extra ), mw.uri.encode( args.givenName.name ) ) ..
' ' .. coordSpan( mi.texts.latitude, args.latDMS ) ..
' ' .. coordSpan( mi.texts.longitude, args.longDMS ) .. ']'
r = noBrackets and r or mu.parentheses( r )
return mu.makeSpan( r, 'voy-listing-dms-coordinates printNoLink plainlinks'
.. mu.addWdClass( fromWD ) )
end
-- prepare value s for data attribute and replace all entities by characters
local function data( s )
return mu.isSet( s ) and mw.text.decode( s, true ) or nil
end
-- output functions
local function makeAnchorId( name )
if name and not name:match( '^Q%d+$' ) then
name = mw.uri.anchorEncode( name )
end
return mw.ustring.format( mi.texts.anchor, name )
end
-- adding wrapper and microformats
function mu.makeWrapper( result, args, page, country, show, list, frame )
if not mu.isSet( args.nameLocal ) and mu.isSet( args.addNameLocal ) then
args.nameLocal = args.addNameLocal
end
if not mu.isSet( args.addressLocal ) and mu.isSet( args.addAddressLocal ) then
args.addressLocal = args.addAddressLocal
end
local wrapper = mw.html.create( show.inline and 'span' or 'div' )
:addClass( string.format( 'voy-%s vcard h-card', args.template ) )
if args.noGpx then
wrapper:addClass( 'voy-listing-no-gpx' )
end
if show.outdent and not show.inline then
wrapper:addClass( 'voy-listing-outdent' )
end
if show.inlineSelected or args.template == 'Marker' then
wrapper:addClass( 'voy-listing-inline' )
end
if mu.isSet( args.copyMarker ) or not show.poi then
wrapper:addClass( 'voy-without-marker' )
end
if #args.statusTable > 0 then
wrapper:addClass( 'voy-listing-with-status' )
end
if not show.inline and mi.options.groupsWithLimit[ args.group ] then
wrapper:addClass( 'voy-listing-shrinkable' )
end
if args.givenName.name ~= mi.texts.missingName then
wrapper:attr( 'data-name', data( args.givenName.name ) )
end
if #mu.hints > 0 then
wrapper:attr( 'data-hints', table.concat( mu.hints, '; ' ) )
end
-- no Marker id if no marker is shown
if not( args.template == 'Marker' and not show.poi and not mu.isSet( args.id ) ) then
if not ( mu.isSet( args.copyMarker ) and args.copyMarker == args.wikidata ) then
local id = mu.isSet( args.wikidata ) and args.wikidata or args.id
if mu.isSet( id ) then
wrapper:attr( 'id', makeAnchorId( id ) )
end
end
end
local editClass = 'voy-listing-edit'
if mu.isSet( args.sectionFrom ) then
args.sectionFrom = replaceWithSpace( args.sectionFrom, '[_]+' )
if args.sectionFrom ~= page.text then
editClass = 'voy-listing-no-edit'
end
end
wrapper:addClass( editClass )
wrapper:attr( 'data-location', data( page.subpageText ) )
:attr( 'data-location-qid', page.entityId )
:attr( 'data-country', data( country.iso_3166 ) )
:attr( 'data-lang', data( country.lang ) )
:attr( 'data-country-calling-code', data( country.cc ) )
:attr( 'data-trunk-prefix', data( country.trunkPrefix ) )
:attr( 'data-currency', data( country.addCurrency ) )
:attr( 'data-coord-from', args.coordFrom )
local arg
for key, value in pairs( list ) do
if mu.isSet( args[ key ] ) then
arg = args[ key ]:gsub( '<[^<>]*>', '' ) -- remove html tags
wrapper:attr( value, data( arg ) )
end
end
if not show.name then
wrapper:node( mw.html.create( 'span' )
:addClass( 'voy-listing-name p-name fn org' )
:css( 'display', 'none' )
:wikitext( args.givenName.name )
)
end
wrapper:wikitext( result )
if not show.noCoord then
wrapper:node( mw.html.create( 'span' )
:addClass( 'voy-listing-coordinates p-geo geo' )
:css( 'display', 'none' )
:node( mw.html.create( 'span' )
:addClass( 'p-latitude latitude' )
:wikitext( args.lat )
)
:node( mw.html.create( 'span' )
:addClass( 'p-longitude longitude' )
:wikitext( args.long )
)
)
end
wrapper = tostring( wrapper )
-- adding coordinates to Mediawiki database
-- frame:callParserFunction is expensive
if not show.noCoord and mi.options.secondaryCoords then
wrapper = wrapper .. frame:callParserFunction{ name = '#coordinates',
args = { args.lat, args.long, country.extra, name = args.givenName.name } }
end
return wrapper
end
function mu.getPageData()
local page = mw.title.getCurrentTitle()
page.langObj = mw.getContentLanguage()
page.lang = page.langObj:getCode()
page.langName = mw.language.fetchLanguageName( page.lang, page.lang )
page.isRTL = page.langObj:isRTL()
page.entityId = mw.wikibase.getEntityIdForCurrentPage() -- can be nil
page.siteName = mw.site.siteName
page.globalProject = page.siteName:lower()
if page.globalProject == 'wikipedia' then
page.globalProject = 'wiki'
end
return page
end
return mu
02pcbtiscgfrgcp8c6ii32191f0g8ob
Modulo:Marker utilities/i18n
828
4808
73248
72147
2026-09-24T10:48:15Z
RolandUnger
168
Update
73248
Scribunto
text/plain
-- Separating code from internationalization
return {
-- module administration
moduleInterface = {
suite = 'Marker utilities',
sub = 'i18n',
serial = '2026-09-23',
item = 65441686
},
dates = { yyyymmdd = { p = '^20[0-5]%d%-[01]?%d%-[0-3]?%d$', f = 'j. M Y' },
yyyy = { p = '^20[0-5]%d$', f = 'Y' },
yy = { p = '^[0-5]%d$', f = 'Y' },
mmdd = { p = '^[01]?%d%-[0-3]?%d$', f = 'j. M' },
dd = { p = '^[0-3]?%d%.?$', f = 'j.' },
mm = { p = '^[01]?%d%.?$', f = 'M' },
lastedit = { f = 'M Y' },
asOf = { f = 'n/Y' }
},
fileExtensions = { 'tif', 'tiff', 'gif', 'png', 'jpg', 'jpeg', 'jpe',
'webp', 'xcf', 'ogg', 'ogv', 'svg', 'pdf', 'stl',
'djvu', 'webm', 'mpg', 'mpeg' },
months = { 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
'August', 'September', 'Oktober', 'November', 'Dezember' },
monthAbbr = { 'Jan%.?', 'Feb%.?', 'Mär%.?', 'Apr%.?', 'Mai%.?', 'Jun%.?',
'Jul%.?', 'Aug%.?', 'Sep%.?', 'Okt%.?', 'Nov%.?', 'Dez%.?' },
-- Map related constants
map = {
coordURLformat = '//%s.wikivoyage.org/w/index.php?title=Special%%3AMapsources¶ms=%s_%s_%s&locname=%s',
defaultDmsFormat = 'f1', -- see: Module:Coordinates/i18n
defaultSiteType = 'type:landmark_globe:earth',
defaultZoomLevel = 17,
maxZoomLevel = 19, -- also to set in Module:GeoData, Module:Mapshape utilities/i18n
},
-- Wikidata properties
properties = {
appliesToJurisdiction = 'P1001',
appliesToPart = 'P518',
appliesToPeople = 'P6001',
capacity = 'P1083',
centerCoordinates = 'P5140',
commonsCategory = 'P373',
coordinates = 'P625',
endTime = 'P582', -- time
headquartersLoc = 'P159',
image = 'P18',
instanceOf = 'P31',
iso4217 = 'P498',
languageOfName = 'P407',
mainCategory = 'P910',
maximumAge = 'P4135',
minimumAge = 'P2899',
nameInNativeLang = 'P1559',
occupation = 'P106',
of = 'P642',
officialName = 'P1448',
partOf = 'P361',
pointInTime = 'P585',
propertyScope = 'P5314', -- for fees
quantity = 'P1114',
retrieved = 'P813',
roomNumber = 'P8733',
startTime = 'P580', -- time, for fees
streetAddress = 'P6375',
subclassOf = 'P279',
unitSymbol = 'P5061',
use = 'P366',
validInPeriod = 'P1264'
},
-- Groups of Wikidata properties
propTable = {
accessibility = { 'P2846' },
contactComments = { 'P366', 'P518', 'P642', 'P1001', 'P1559', 'P106' },
feeComments = { 'P5314', 'P518', 'P6001', 'P1264', 'P585', 'P2899',
'P4135', 'P642', 'P580' },
policyComments = { 'P518', 'P1001', 'P6001' },
quantity = { 'P1114', 'P1083' },
accessQuantity = { 'P1114', 'P1083', 'P2846' },
unescoPartOf = { 'P361' }
},
-- Wikidata properties representing a qualifier
qualifiers = {
mobilePhone = 'Q17517',
P8733 = 'Q180516',
roomNumber = 'Q180516',
unescoHeritage = 'Q9259'
},
-- Languages for fallbacks, except wiki language
langs = { 'en', 'fr' }, -- array can be empty
-- Display and performance options for vCard / Listing and Marker modules
-- additional options in Module:VCard/i18n
options = {
excludeColorTypes = true,
normalizeValues = { 'type', 'subtype', 'show', 'status', 'symbol' },
noStarParams = { 'name', 'nameExtra', 'nameLocal', 'nameMap', 'alt', 'comment' },
noTypeMsgs = false, -- prevents display of maintenance( typeFromWD, typeIsGroup )
noRecommendations = true, -- prevents display of recommendation hints
parameters = { 'commonscat', 'country', 'id', 'localLang', 'nameExtra', 'wikipedia' }, -- parameter is used
showLocalData = true, -- names, addresses, directions
showSisters = true, -- possible values true, false, 'atEnd'
usePropertyCateg = true, -- create maintenance categories for Wikidata properties
useTypeCateg = true, -- create maintenance categories for marker types
markerMetadata = true, -- add metadata at marker templates
-- text limit of content/description parameter
contentLimit = 1000,
groupsWithLimit = { buy = 1, drink = 1, eat = 1, sleep = 1 },
-- Wikidata related constants
searchLimit = 4, -- count of levels for P31-P279 search
-- useful but not necessary function calls
WDmediaCheck = false, -- check file names retrieved from Wikidata
mediaCheck = false, -- for better performance, otherwise expensive
-- mw.title.new( 'Media:' .. image ) call is used
secondaryCoords = false, -- adding listing coordinates to article database
-- using #coordinates parser function
skipPathCheck = false -- for URL check, see Module:UrlCheck
},
-- strings
texts = {
asOf = '; Stand %s', -- with semicolon separator
from = 'ab %s',
fromTo = '%s–%s',
to = 'bis %s',
fromTo2 = '%s bis %s',
-- General, i18n
-- black x-like cross
closeX = '[[File:Close x - black.png|15px|link=|class=noviewer|Unbekanntes Marker-Symbol]]',
missingName = 'Name fehlt',
-- In case of CJK languages no spaces are used with punctuation
-- Enumeration commas. voy-listing-comma is used for alt names only
comma = '<span class="voy-listing-comma">, </span>', -- with zero-width space
commaSeparator = ', ',
period = '.',
periodSeparator= '. ',
-- Space following a punctuation mark
space = ' ',
nbSpace = ' ',
parentheses = ' (%s)',
emph = "''%s''",
-- Formatting numbers: replacement patterns
decimalPoint = ',',
groupSeparator = '.',
-- Anchor id
anchor = 'vCard_%s',
-- Marker
CategoryNS = { '[Cc]ategory', '[Kk]ategorie' },
FileNS = { '[Ff]ile', '[Ii]mage', '[Dd]atei', '[Bb]ild' },
latitude = 'Breitengrad',
longitude = 'Längengrad',
tooltip = 'Click auf den Marker öffnet die Karte direkt.',
-- vCard / Listing module
checkin = 'Check-in: %s',
checkout = 'Check-out: %s',
closed = 'Geschlossen: %s',
closedPattern = '^[Gg]eschlossen:?%s*',
editInSource = 'im Quellartikel bearbeiten',
email = 'E-Mail: %s',
expirationPeriod = 'now - 3 years',
fax = 'Fax: %s',
hintName = 'Name in %s',
hintLatin = 'Name in lateinischer Umschrift',
hintAddress = 'Anschrift in %s',
hintDirections = 'Wegbeschreibung in %s',
hours = 'Geöffnet: %s',
iata = '[[International Air Transport Association|IATA]]: %s',
icao = '[[Internationale Zivilluftfahrt-Organisation|ICAO]]: %s',
lastedit = 'letzte Änderung: %s',
lasteditNone = 'keine Angabe',
maybeOutdated = '(Angaben möglicherweise veraltet)[[Category:VCard: Angaben veraltet]]',
mobile = 'Mobil: %s',
payment = 'Akzeptierte Zahlungsarten: %s',
phone = '<abbr title="Telefon">Tel.</abbr>: %s',
price = 'Preis: %s',
subtype = 'Merkmal: %s.',
subtypes = 'Merkmale: %s.',
subtypeAbbr = '<abbr title="%s">%s</abbr>',
subtypeFile = '[[File:%s|x14px|link=|class=noviewer voy-listing-subtype-icon|%s]]',
-- for subtype icons like Michelin stars
subtypeSpan = '<span title="%s">%s</span>',
subtypeWithCount = '%d %s',
tollfree = '<abbr title="Telefon">Tel.</abbr> gebührenfrei: %s'
},
-- format strings for mu.addMaintenance
formats = {
category = '[[Category:%s]]',
error = ' <span class="error">%s</span>',
hint = ' <span class="voy-check-recommended" style="display: none;">%s</span>',
wikidata = '[[Category:Seiten, die die Wikidata-Eigenschaft %s benutzen]]'
},
-- maintenance
maintenance = {
-- general
type = { category = 'Seiten mit dem Markertyp %s' },
group = { category = 'Seiten mit der Markergruppe %s' },
urlWithIP = { category = 'URL enthält IP-Adresse', hint = 'URL enthält IP-Adresse' },
wrongUrl = { category = 'URL ist ungültig', err = 'URL ist ungültig' },
commonscatWD = { category = 'VCard: Parameter commonscat zusammen mit wikidata benutzt' },
contentTooLong = { category = 'VCard: Beschreibung ist zu lang', err = 'Beschreibung ist zu lang' },
currencyTooltip= { category = 'VCard: Währungstooltips eingesetzt' },
dmsCoordinate = { category = 'VCard: DMS-Koordinate', hint = 'DMS-Koordinate' },
duplicateAliases = { category = 'VCard: Doppelte Aliase', err = 'Doppelte Aliase: %s' },
headquarters = { category = 'VCard: Koordinate der Hauptverwaltung' },
labelFromWD = { category = 'VCard: Label aus Wikidata', hint = 'Label aus Wikidata' },
linkIsRedirect = { category = 'VCard: Artikellink ist Weiterleitung' },
linkToOtherWV = { category = 'VCard: Anderes Wikivoyage verlinkt' },
malformedName = { category = 'VCard: Fehlerhafter Name', err = 'Fehlerhafter Name' },
malformedAddress = { category = 'VCard: Fehlerhafte Adresse oder Wegbeschreibung', err = 'Fehlerhafte Adresse oder Wegbeschreibung' },
missingImg = { category = 'VCard: Datei existiert nicht', err = 'Nicht vorhandenes Bild: %s' },
missingNameMsg = { category = 'VCard: Ohne Namen', err = 'Name fehlt' },
missingType = { category = 'VCard: Typ fehlt', err = 'Fehlender Typ' },
nameFromWD = { category = 'VCard: Name aus Wikidata bezogen', err = 'Name aus Wikidata bezogen' },
nameWithBrackets = { category = 'VCard: Name mit Klammern', hint = 'Name mit Klammern' },
nameWithStar = { category = 'VCard: Name enthält Stern', err = 'Name enthält Stern' },
noLocalParams = { category = 'VCard: Lokale Parameter nicht verwendbar', err = 'Lokale Parameter nicht verwendbar' },
outdated = { category = 'VCard: Ereignis veraltet', err = 'Ereignis veraltet' },
parameterUsed = { category = 'VCard: Parameter %s benutzt' },
deleteShowCopy = { category = 'VCard: show=copy gelöscht', hint = 'show=copy gelöscht' },
showInlineUsed = { category = 'VCard: show=inline gesetzt' },
showNoneUsed = { category = 'Marker: show=none gesetzt' },
showPoiUsed = { category = 'VCard: show=poi gesetzt' },
typeFromWDchain= { category = 'VCard: Typ aus Wikidata-Kette bezogen', hint = 'Typ aus Wikidata bezogen' },
typeIsGroup = { category = 'VCard: Typ ist Gruppenbezeichnung', hint = 'Typ ist Gruppenbezeichnung' },
typeIsColor = { category = 'VCard: Typ ist Farbbezeichnung', hint = 'Typ ist Farbbezeichnung' },
-- typeIsColor is not used if excludeColorTypes = true
unknownCountry = { category = 'VCard: Unbekannter Ländercode', err = 'Unbekannter Ländercode' },
unknownGroup = { category = 'VCard: Unbekannte Gruppe', err = 'Unbekannte Gruppe' },
unknownLanguage= { category = 'VCard: Unbekannter Sprachcode', hint = 'Unbekannter Sprachcode' },
unknownParam = { category = 'VCard: Unbekannte Parameter', err = 'Unbekannter Parameter: %s' },
unknownParams = { category = 'VCard: Unbekannte Parameter', err = 'Unbekannte Parameter: %s' },
unknownPropertyLanguage= { category = 'VCard: Unbekannter Sprachcode für Eigenschaft', hint = 'Unbekannter Sprachcode für Eigenschaft' },
unknownStatus = { category = 'VCard: Unbekannter Status', err = 'Unbekannter Status' },
unknownType = { category = 'VCard: Unbekannter Typ', err = 'Unbekannter Typ: %s' },
unusedRedirect = { category = 'VCard: Unbenutzter Weiterleitungs-Sitelink' },
urlIsSocialMedia = { category = 'VCard: URL stammt von Social-Media-Dienst', err = 'URL stammt von Social-Media-Dienst' },
wikidata = { category = 'VCard: Einsatz von Wikidata' },
wrongCoord = { category = 'VCard: Fehlerhafte Koordinate', err = 'Fehlerhafte Koordinate' },
wrongImgName = { category = 'VCard: Fehlerhafter Mediendateiname', err = 'Fehlerhafter Mediendateiname' },
wrongQualifier = { category = 'VCard: Fehlerhafter Wikidata-Qualifikator', err = 'Fehlerhafter Wikidata-Qualifikator' },
-- Marker module
missingCoord = { category = 'Marker: Ohne Koordinaten', err = 'Länge und/oder Breite fehlt' },
numberUsed = { category = 'Marker: Nummer manuell vergeben' },
unknownIcon = { category = 'Marker: Unbekanntes Symbol' },
-- vCard / Listing module
countryFromWD = { category = 'VCard: Länderdaten aus Wikidata' },
missingCoordVc = { category = 'VCard: Ohne Koordinaten' },
paymentUsed = { category = 'VCard: Zahlungsarten spezifiziert' },
socialUrlUsed = { category = 'VCard: Social-Media-URL verwendet', hint = '%s-URL verwendet' },
unitFromWD = { category = 'VCard: Einheit aus Wikidata', hint = 'Einheit aus Wikidata' },
unknownLabel = { category = 'VCard: Unbekanntes Label oder Id' },
unknownMAKI = { category = 'VCard: Unbekanntes MAKI-Symbol', hint = 'Unbekanntes MAKI-Symbol' },
unknownShow = { category = 'VCard: Unbekannter Wert für show', err = 'Wert(e) für show unbekannt: %s' },
unknownSubtype = { category = 'VCard: Unbekannter Wert für subtype', err = 'Wert(e) für subtype unbekannt: %s' },
unknownUnit = { category = 'VCard: Unbekannte Einheit', hint = 'Unbekannte Einheit' },
unknowWDfeatures = { category = 'VCard: Unbekannte Wikidata-Merkmale', hint = 'Unbekannte Wikidata-Merkmale' },
wdWithGoogleCid = { category = 'VCard: Parameter google-maps zusammen mit wikidata benutzt', hint = 'google-maps mit wikidata benutzt' },
wikidataWithId = { category = 'VCard: Parameter id zusammen mit wikidata benutzt', hint = 'id mit wikidata benutzt' },
wrongDate = { category = 'VCard: Fehlerhaftes Datum', err = 'Fehlerhaftes Datum' },
wrongGoogleCid = { category = 'VCard: Fehlerhafte Google-Maps-Kundenkennung', err = 'Fehlerhafte Google-Maps-Kundenkennung' },
wrongId = { category = 'VCard: Fehlerhafte id', err = 'Fehlerhafte id' },
wrongSocialId = { category = 'VCard: Fehlerhafte Social-Media-Id', err = 'Fehlerhafte %s-Id' },
wrongSocialUrl = { category = 'VCard: Fehlerhafte Social-Media-URL', err = 'Fehlerhafte %s-URL' }
},
iconTitles = {
commons = '%s im Medienverzeichnis Wikimedia Commons',
facebook = '%s auf Facebook',
flickr = '%s auf Flickr',
instagram = '%s auf Instagram',
internet = 'Website dieser Einrichtung',
maps = '%s auf Karten und Routenplanern',
rss = 'RSS-Web-Feed dieser Einrichtung',
tiktok = '%s auf TikTok',
wikidata = '%s (%s) in der Datenbank Wikidata',
wikipedia = '%s in der Enzyklopädie Wikipedia',
wikivoyage = '%s im Reiseführer Wikivoyage in einer anderen Sprache',
x = '%s auf X',
youtube = '%s auf YouTube'
},
-- social media services
services = {
{ key = 'facebook', url = 'https://www.facebook.com/%s', pattern = { '^[-.%d%w][-_.%d%w]+$', '^[^%z\1-,/:-?\91-\94{-~]+/[1-9]%d+$' } },
{ key = 'flickr', url = 'https://www.flickr.com/photos/%s', pattern = '^%d%d%d%d%d+@N%d%d$' },
{ key = 'instagram', url = 'https://www.instagram.com/%s/', pattern = { '^[0-9a-z_][0-9a-z._]+[0-9a-z_]$', '^explore/locations/%d+$' } },
{ key = 'tiktok', url = 'https://www.tiktok.com/@%s', pattern = '^[0-9A-Za-z_][0-9A-Za-z_.]+$' },
{ key = 'x', url = 'https://x.com/%s', pattern = '^[0-9A-Za-z_]+$' },
{ key = 'youtube', url = { 'https://www.youtube.com/channel/%s', 'https://www.youtube.com/%s' },
pattern = { '^UC[-_0-9A-Za-z]+[AQgw]$', '^@[-0-9A-Za-z_.][-0-9A-Za-z_.][-0-9A-Za-z_.]+$' } }
},
--[[ status symbols
g: successive symbol group number
alias: status alias
label: image tag title
category = 1: add maintenance category
--]]
statuses = {
['top-hotel'] = { g = 1, label = 'Top-Hotel', category = 1 },
['top-restaurant'] = { g = 1, label = 'Top-Restaurant', category = 1 },
['top-sight'] = { g = 1, label = 'Top-Sehenswürdigkeit', category = 1 },
recommendation = { g = 1, label = 'Empfehlung' },
none = { g = 2, alias = 'class-0', label = 'Ohne Einstufung' },
stub = { g = 2, alias = 'class-1', label = 'Stub' },
outline = { g = 2, alias = 'class-2', label = 'Artikelentwurf' },
usable = { g = 2, alias = 'class-3', label = 'Brauchbarer Artikel' },
guide = { g = 2, alias = 'class-4', label = 'Vollständiger Artikel' },
star = { g = 2, alias = 'class-5', label = 'Empfehlenswerter Artikel' }
},
-- Marker name styles
-- Colors in Template:VCard/styles.css
nameStyles = {
inherit = 'font-weight: inherit; font-style: inherit;',
italic = 'font-weight: normal; font-style: italic;',
kursiv = 'font-weight: normal; font-style: italic;', -- de: kursiv = italic
normal = 'font-weight: normal; font-style: normal;',
station = 'font-weight: normal; white-space: nowrap; padding-left: 2px; padding-right: 2px;'
},
-- yes/no variants
yesno = {
y = 'y',
yes = 'y',
j = 'y',
ja = 'y',
n = 'n',
no = 'n',
nein = 'n'
},
-- List of currencies without conversion tooltips
noCurrencyConversion = {
-- all = 1, -- no rate conversion tooltips are shown
-- there is no confusion with (uppercase) ALL = "Q125999"
EUR = 1 -- local currency
},
-- Language-dependent sorting substitutes
substitutes = {
{ l = 'ä', as = 'a' },
{ l = 'ö', as = 'o' },
{ l = 'ü', as = 'u' },
{ l = 'ß', as = 'ss' }
}
}
hoztqhqpg1422ts5cyydh9m9i7ilc3v
Modulo:Marker utilities/Types
828
4814
73243
72959
2026-09-24T10:44:22Z
RolandUnger
168
Update
73243
Scribunto
text/plain
--[[
Please use only quotation marks instead of apostrophs for JSON export.
Do not change this modul without need. A change causes the parsing of the
majority of articles. Wishes for new types should be discussed and collected
on Module talk:Marker utilities/Types.
Types should conform to tags in Openstreetmap, if possible.
New types must be entered in Template:Marker/XML and Template:vCard/XML, too.
--]]
return {
-- administration
moduleInterface = {
suite = "Marker utilities",
sub = "types",
serial = "2026-09-24",
item = 65444106
},
types = {
-- do not remove the following line
-- ##start
-- journey and mobility
aerialway = { group = "go", wd = "Q1054650", label = "Seilbahn" },
airline = { group = "go", wd = "Q46970", label = "Fluggesellschaft" },
airport = { group = "go", wd = { "Q1248784", "Q62447", "Q644371" }, useIATA = "1", label = "Flughafen" },
airport_service = { group = "go", label = "Flughafendienst" },
bicycle_parking = { group = "go", wd = "Q16243822", label = "Fahrradparkplatz" },
bicycle_rental = { alias = "bicycle_share", group = "go", wd = { "Q10611118", "Q1358919", "Q61663696" }, label = "Fahrradverleih", icon = "bicycle-share" },
bicycle_repair = { group = "go", wd = { "Q96983545", "Q112663579" }, label = "Fahrradreparatur" },
boat_sharing = { group = "go", wd = "Q4931514", label = "Boot-Sharing, Boot-Charter" },
boat_trip = { group = "go", wd = "Q25040412", label = "Bootsfahrt, Schiffstour" },
border_control = { group = "go", wd = "Q218719", label = "Grenzkontrolle" },
bus = { alias = "bus_stop", group = "go", wd = { "Q953806", "Q494829" }, label = "Bushaltestelle" },
car_rental = { group = "go", wd = "Q291240", label = "Autoverleih, Autovermietung" },
car_repair = { group = "go", wd = "Q1310967", label = "Autowerkstatt" },
car_sharing = { group = "go", wd = "Q847201", label = "Carsharing" },
charging_station = { group = "go", wd = { "Q2140665", "Q55956304" }, label = "Ladestation, Stromtankstelle" },
cycle_track = { alias = "cycle_path", group = "go", wd = { "Q25037910", "Q221722" }, label = "Radweg" },
draisine = { group = "go", wd = "Q209658", label = "Draisine, Eisenbahn-Draisine" },
entrance = { group = "go", wd = "Q1137365", label = "Eingang" },
ferry = { group = "go", wd = { "Q100355757", "Q25653", "Q1478783" }, label = "Fähranleger" },
ford = { group = "go", wd = "Q12743", label = "Furt" },
fuel = { alias = "filling_station", group = "go", wd = "Q205495", label = "Tankstelle" },
funicular = { group = "go", wd = "Q142031", label = "Standseilbahnstation" },
harbor = { alias = "port", group = "go", wd = { "Q44782", "Q283202" }, label = "Hafen" },
heliport = { group = "go", wd = "Q502074", label = "Hubschrauberlandeplatz, Heliport" },
junction = { alias = { "road_junction", "intersection" }, group = "go", wd = { "Q1788454", "Q285783" }, label = "Kreuzung" },
landing_site = { group = "go", wd = "Q3631092", label = "Landeplatz" },
left_luggage = { group = "go", wd = "Q21996814", label = "Gepäckaufbewahrung" },
light_railway = { alias = "lrt", group = "go", wd = "Q32680449", label = "Light-Railway-Station" },
marina = { group = "go", wd = "Q721207", label = "Yachthafen, Marina" },
monorail = { group = "go", wd = "Q187934", label = "Monorail-Station" },
motorbike_rental = { group = "go", label = "Motorradverleih" },
motorway_junction = { group = "go", label = "Ausfahrt, Auffahrt, Anschlussstelle, Autobahnkreuz" },
parking = { group = "go", wd = "Q6501349", label = "Parkplatz" },
parking_garage = { group = "go", wd = "Q13218805", label = "Parkhaus" },
pier = { group = "go", wd = "Q863454", label = "Pier, Schiffsanleger" }, -- also jetty
public_transport = { group = "go", wd = "Q178512", label = "Öffentliche Verkehrsmittel" },
quay = { alias = "wharf", group = "go", wd = "Q828909", label = "Kai, Schiffsanleger, Kaje" },
rail = { alias = { "train", "railway", "railway_station" }, group = "go", wd = { "Q55488", "Q55678" }, label = "Bahnhof, Haltepunkt" },
scooter = { group = "go", wd = { "Q193234", "Q502057" }, label = "Scooter, Motorroller, Tretroller" },
service_area = { group = "go", wd = "Q786014", label = "Raststätte, Autohof" },
ship = { group = "go", wd = "Q11446", label = "Schiff" },
shipping_company = { group = "go", label = "Schifffahrtsgesellschaft, Reederei" },
shuttle_bus_service = { group = "go", label = "Shuttlebus-Service" },
station = { group = "go", wd = "Q12819564", label = "Station" },
suburban_rail = { alias = { "suburban_railway", "commuter_rail", "s-bahn" }, group = "go", wd = { "Q1412403", "Q95723" }, label = "S-Bahn-Station, Vorortbahnstation" },
subway = { alias = "metro", group = "go", wd = "Q928830", label = "U-Bahn-Station", icon = "rail-metro" },
taxi = { group = "go", wd = "Q1395196", label = "Taxistand" },
terminal = { group = "go", wd = "Q849706", label = "Terminal" },
toll_station = { group = "go", wd = "Q1364150", label = "Mautstation" },
tram = { group = "go", wd = "Q2175765", label = "Straßenbahnhaltestelle, Tramhaltestelle", icon = "rail-light" },
tunnel = { group = "go", wd = "Q44377", label = "Tunnel" },
waiting_room = { group = "go", wd = "Q674251", label = "Warteraum, Wartesaal" },
waypoint = { group = "go", wd = "Q138081", label = "Wegpunkt" },
-- group types
go = { group = "go", wd = { "Q334166", "Q740752" }, label = "Anreise" },
-- sights: religious sites and monuments
altar = { group = "religion", wd = "Q101687", label = "Altar" },
bahai_temple = { group = "religion", wd = "Q1568313", label = "Bahai-Tempel" },
basilica = { group = "religion", wd = { "Q163687", "Q4846867" }, label = "Basilika" },
buddharupa = { group = "religion", wd = "Q1000809", label = "Buddha-Statue", icon = "religious-buddhist" },
cathedral = { group = "religion", wd = "Q2977", label = "Kathedrale", icon = "religious-christian" },
chapel = { group = "religion", wd = "Q108325", label = "Kapelle", icon = "religious-christian" },
chapel_shrine = { group = "religion", wd = "Q14552192", label = "Heiligenhäuschen" },
church = { group = "religion", wd = { "Q16970", "Q580499" }, label = "Kirche", icon = "religious-christian" },
fire_temple = { group = "religion", wd = "Q115278", label = "Feuertempel" },
gurdwara = { group = "religion", wd = "Q337986", label = "Gurdwara" },
hindu_temple = { group = "religion", wd = "Q842402", label = "Hindutempel" },
lak_mueang = { group = "religion", wd = "Q974127", label = "Lak Müang" },
lourdes_grotto = { group = "religion", wd = "Q1433032", label = "Lourdesgrotte, Mariengrotte" },
mikveh = { group = "religion", wd = "Q211351", label = "Mikwe" },
minaret = { group = "religion", wd = "Q48356", label = "Minarett" },
monastery = { group = "religion", wd = { "Q44613", "Q160742" }, label = "Kloster, Abtei" },
mosque = { group = "religion", wd = "Q32815", label = "Moschee", icon = "religious-muslim" },
nunnery = { group = "religion", wd = "Q6021560", label = "Nonnenkloster" },
pagoda = { group = "religion", wd = "Q199451", label = "Pagode" },
pilgrimage_site = { group = "religion", wd = "Q15135589", label = "Wallfahrtsort" },
sanctuary = { group = "religion", wd = "Q29553", label = "Heiligtum" },
shinto_shrine = { group = "religion", wd = "Q845945", label = "Shintō-Schrein", icon = "religious-shinto" },
shrine = { group = "religion", wd = "Q697295", label = "Schrein" },
stupa = { group = "religion", wd = "Q180987", label = "Stupa" },
summit_cross = { group = "religion", wd = "Q361665", label = "Gipfelkreuz" },
synagogue = { group = "religion", wd = "Q34627", label = "Synagoge", icon = "religious-jewish" },
temple = { group = "religion", wd = { "Q44539", "Q927825", "Q58621988" }, label = "Tempel" },
wat = { group = "religion", wd = "Q427287", label = "Wat" },
wayside_cross = { group = "religion", wd = "Q2309609", label = "Flurkreuz, Wegkreuz" },
wayside_shrine = { group = "religion", wd = { "Q3395121", "Q12661150" }, label = "Bildstock" },
religion = { alias = "religious_site", group = "religion", wd = "Q1370598", label = "Religiöse Stätte" },
-- sights: natural
animal_shelter = { group = "nature", wd = "Q1411287", label = "Tierheim" },
animal_stable = { alias = "stable", group = "nature", wd = { "Q214252", "Q1207909" }, label = "Stall" },
aquarium = { group = "nature", wd = "Q2281788", label = "Aquarium" },
bay = { group = "nature", wd = { "Q39594", "Q17018380" }, label = "Bucht" },
botanical_garden = { group = "nature", wd = "Q167346", label = "Botanischer Garten" },
canal = { group = "nature", wd = "Q12284", label = "Kanal" },
canyon = { group = "nature", wd = "Q150784", label = "Canyon, Schlucht" },
cape = { group = "nature", wd = "Q185113", label = "Kap" },
cave = { group = "nature", wd = "Q35509", label = "Höhle" },
cliff = { group = "nature", wd = "Q107679", label = "Klippe" },
coast = { group = "nature", wd = "Q93352", label = "Küste" },
crater = { group = "nature", wd = "Q3240715", label = "Krater" },
crocodile_farm = { group = "nature", wd = "Q25691", label = "Krokodilfarm" },
depression = { group = "nature", wd = "Q190429", label = "Senke" },
desert = { group = "nature", wd = "Q8514", label = "Wüste" },
dive_site = { group = "nature", wd = "Q2141554", label = "Tauchplatz, Tauchgebiet" },
dog_park = { group = "nature", wd = "Q38516", label = "Hundezone, Hundewiese" },
dolphinarium = { group = "nature", wd = "Q491675", label = "Delfinarium" },
dune = { group = "nature", wd = "Q25391", label = "Düne" },
dyke = { group = "nature", wd = "Q105190", label = "Deich" },
farm = { group = "nature", wd = "Q131596", label = "Bauernhof, Gut" },
fish_pond = { group = "nature", wd = "Q1265665", label = "Fischteich" },
fjord = { group = "nature", wd = "Q45776", label = "Fjord" },
forest = { group = "nature", wd = "Q4421", label = "Wald" },
garden = { group = "nature", wd = "Q1107656", label = "Garten" },
geyser = { group = "nature", wd = "Q83471", label = "Geysir" },
glacier = { group = "nature", wd = "Q35666", label = "Gletscher" },
greenhouse = { group = "nature", wd = "Q165044", label = "Gewächshaus, Treibhaus" },
gulf = { group = "nature", wd = "Q1322134", label = "Golf (Bucht)" },
habitat = { group = "nature", label = "Habitat" },
heath = { group = "nature", wd = "Q27590", label = "Heide" },
hill = { group = "nature", wd = "Q54050", label = "Hügel" },
horticulture = { group = "nature", wd = "Q48803", label = "Gartenbau, Gärtnerei" },
hot_spring = { group = "nature", wd = "Q177380", label = "Thermalquelle" },
island = { group = "nature", wd = "Q23442", label = "Insel" },
lagoon = { group = "nature", wd = "Q187223", label = "Lagune" },
lake = { group = "nature", wd = "Q23397", label = "See, Teich" },
landscape = { group = "nature", wd = "Q107425", label = "Landschaft" },
mangrove = { group = "nature", wd = "Q19756", label = "Mangrove" },
meadow = { group = "nature", wd = "Q7777019", label = "Wiese" },
mountain = { group = "nature", wd = "Q8502", label = "Berg" },
mountain_chain = { group = "nature", wd = "Q2624046", label = "Gebirgszug" },
mountain_pass = { group = "nature", wd = "Q133056", label = "Gebirgspass" },
mountain_pasture = { alias = "alm", group = "nature", wd = "Q2082774", label = "Alm" },
mountain_range = { group = "nature", wd = "Q46831", label = "Gebirge" },
national_park = { group = "nature", wd = "Q46169", label = "Nationalpark" },
natural_heritage = { group = "nature", wd = "Q386426", label = "Naturerbe" },
natural_monument = { group = "nature", wd = "Q23790", label = "Naturdenkmal" },
nature_reserve = { group = "nature", wd = { "Q158454", "Q179049", "Q473972", "Q759421", "Q20268756" }, label = "Naturschutzgebiet" },
oasis = { group = "nature", wd = "Q43742", label = "Oase" },
palaeontological_site = { group = "nature", wd = "Q9096832", label = "Paläontologische Stätte" },
park = { group = "nature", wd = { "Q22698", "Q728904" }, label = "Park" },
peninsula = { group = "nature", wd = "Q34763", label = "Halbinsel" },
plantation = { group = "nature", wd = "Q188913", label = "Plantage" },
plateau = { group = "nature", wd = "Q75520", label = "Hochebene, Plateau" },
protected_area = { alias = "protectorate", group = "nature", wd = "Q473972", label = "Schutzgebiet" },
reef = { group = "nature", wd = "Q184358", label = "Riff" },
reservoir = { group = "nature", wd = "Q131681", label = "Stausee" },
river = { group = "nature", wd = "Q4022", label = "Fluss" },
river_mouth = { group = "nature", wd = "Q1233637", label = "Flussmündung" },
rock = { group = "nature", wd = { "Q1404150", "Q8063" }, label = "Felsen, Gestein" },
sea = { group = "nature", wd = "Q165", label = "Meer, Ozean" },
spring = { group = "nature", wd = "Q124714", label = "Quelle" },
steppe = { group = "nature", wd = "Q123991", label = "Steppe" },
strait = { group = "nature", wd = "Q37901", label = "Meerenge" },
stream = { group = "nature", wd = "Q47521", label = "Bach" },
stud = { group = "nature", wd = "Q108696", label = "Gestüt" },
summit = { group = "nature", wd = "Q207326", label = "Gipfel" },
tree = { group = "nature", wd = "Q10884", label = "Baum" },
valley = { group = "nature", wd = "Q39816", label = "Tal" },
volcano = { group = "nature", wd = "Q8072", label = "Vulkan" },
waterfall = { group = "nature", wd = "Q34038", label = "Wasserfall, Katarakt" },
wetland = { group = "nature", wd = "Q170321", label = "Feuchtgebiet" },
zoo = { group = "nature", wd = "Q43501", label = "Zoo, Tierpark" },
nature = { group = "nature", wd = "Q7860", label = "Natur" },
-- sights: arts, historic
amphitheater = { group = "see", wd = "Q54831", label = "Amphitheater" },
aqueduct = { group = "see", wd = "Q474", label = "Aquädukt" },
archaeological_site = { group = "see", wd = "Q839954", label = "Archäologische Stätte" },
architecture = { group = "see", wd = "Q12271", label = "Architektur" },
archive = { group = "see", wd = { "Q166118", "Q635719", "Q27032363" }, label = "Archiv" },
artwork = { group = "see", wd = "Q838948", label = "Kunstwerk" },
bakehouse = { group = "see", wd = "Q798436", label = "Backhaus" },
barracks = { group = "see", wd = "Q131263", label = "Kaserne" },
boat_lift = { group = "see", wd = "Q14908", label = "Schiffshebewerk" },
bridge = { group = "see", wd = "Q12280", label = "Brücke" },
building = { group = "see", wd = { "Q41176", "Q811979" }, label = "Gebäude" },
building_complex = { group = "see", wd = { "Q1497364", "Q18247357" }, label = "Gebäudekomplex, Bauwerkgruppe" },
bunker = { group = "see", wd = "Q91122", label = "Bunker" },
cannon = { group = "see", wd = "Q81103", label = "Kanone" },
castle = { group = "see", wd = "Q23413", label = "Burg" },
cellar = { group = "see", wd = "Q234852", label = "Keller" },
cemetery = { alias = "necropolis", group = "see", wd = "Q39614", label = "Friedhof, Nekropole" },
cenotaph = { group = "see", wd = "Q321053", label = "Kenotaph, Scheingrab" },
chateau = { alias = "château", group = "see", wd = "Q751876", label = "Schloss" },
city_center = { group = "see", wd = "Q1468524", label = "Stadtzentrum, Stadtkern" },
city_wall = { group = "see", wd = "Q16748868", label = "Stadtmauer" },
collection = { group = "see", wd = { "Q2668072", "Q7328910" }, label = "Sammlung" },
column = { group = "see", wd = { "Q4817", "Q51845395", "Q1930585" }, label = "Säule, Gedenksäule" },
communication_tower = { group = "see", wd = { "Q11166728", "Q1798641" }, label = "Fernsehturm, Fernmeldeturm" },
crematorium = { group = "see", wd = "Q157570", label = "Krematorium" },
cultural_heritage = { group = "see", wd = "Q210272", label = "Kulturerbe" },
dam = { group = "see", wd = "Q12323", label = "Talsperre" },
domain = { group = "see", wd = "Q155231", label = "Landgut, Domäne, Rittergut" },
embankment_dam = { group = "see", wd = "Q1244922", label = "Staudamm" },
exhibition = { group = "see", wd = "Q464980", label = "Ausstellung" },
exhibition_hall = { group = "see", wd = { "Q57659484", "Q3364296" }, label = "Ausstellungshalle" },
factory = { group = "see", wd = "Q83405", label = "Fabrik" },
fort = { group = "see", wd = "Q57831", label = "Festung, Fort" },
fountain = { group = "see", wd = "Q483453", label = "Springbrunnen" },
gallery = { group = "see", wd = "Q1007870", label = "Galerie", icon = "art-gallery" },
gate = { group = "see", wd = "Q53060", label = "Tor" },
ghost_town = { group = "see", wd = "Q74047", label = "Geisterstadt" },
glassmaker = { group = "see", wd = { "Q12184432", "Q110135697", "Q137431541" }, label = "Glasmacher, Glasmacherwerkstatt" },
graduation_tower = { group = "see", wd = "Q1541226", label = "Gradierwerk" },
grave = { group = "see", wd = "Q173387", label = "Grab" },
hall = { group = "see", wd = "Q240854", label = "Halle" },
handicraft = { group = "see", wd = "Q52105", label = "Handwerk, Kunsthandwerk" },
high_rise = { alias = "skyscraper", group = "see", wd = { "Q18142", "Q11303" }, label = "Hochhaus, Wolkenkratzer" },
historic_district = { group = "see", wd = "Q15243209", label = "historisches Gebiet", icon = "historic" },
house = { group = "see", wd = "Q3947", label = "Haus" },
hydraulic_structure = { group = "see", wd = "Q2466889", label = "Wasserbauwerk" },
landmark = { group = "see", wd = "Q2319498", label = "Wahrzeichen" },
lighthouse = { group = "see", wd = "Q39715", label = "Leuchtturm, Bake, Seezeichen" },
lock = { group = "see", wd = "Q105731", label = "Schiffsschleuse, Schleuse" },
mausoleum = { group = "see", wd = "Q162875", label = "Mausoleum" },
megalithic_tomb = { group = "see", wd = { "Q10521078", "Q101659" }, label = "Großsteingrab, Hünengrab, Dolmen" },
memorial = { group = "see", wd = "Q5003624", label = "Gedenkstätte" },
mill = { group = "see", wd = "Q44494", label = "Mühle" },
mine = { group = "see", wd = "Q820477", label = "Bergwerk, Mine" }, -- including surface mining
mining_museum = { group = "see", wd = "Q819426", label = "Bergbaumuseum" },
monument = { group = "see", wd = "Q4989906", label = "Denkmal, Monument" },
museum = { group = "see", wd = "Q33506", label = "Museum" },
museum_ship = { group = "see", wd = "Q575727", label = "Museumsschiff" },
national_monument = { group = "see", wd = "Q893745", label = "Nationaldenkmal" },
obelisk = { group = "see", wd = "Q170980", label = "Obelisk" },
observatory = { group = "see", wd = { "Q1254933", "Q62832" }, label = "Sternwarte" },
old_town = { group = "see", wd = "Q676050", label = "Altstadt", icon = "historic" },
open_air_museum = { group = "see", wd = "Q756102", label = "Freilichtmuseum" },
palace = { group = "see", wd = "Q16560", label = "Palast" },
pavilion = { alias = "arbor", group = "see", wd = { "Q276173", "Q23457088", "Q961082" }, label = "Pavillon, Gartenlaube" },
pedestrian = { group = "see", wd = "Q369730", label = "Fußgängerzone" },
planetarium = { group = "see", wd = "Q148319", label = "Planetarium" },
power = { group = "see", wd = "Q159719", label = "Kraftwerk, Energie" }, -- power station, transformers, towers etc.
promenade = { group = "see", wd = "Q787113", label = "Promenade" },
pyramid = { group = "see", wd = "Q12516", label = "Pyramide" },
quarry = { group = "see", wd = "Q15115254", label = "Steinbruch" },
road = { group = "see", wd = { "Q34442", "Q83620" }, label = "Straße" }, -- including street and lane
rock_art = { group = "see", wd = "Q1211146", label = "Felsbild" },
ruins = { group = "see", wd = "Q109607", label = "Ruine" },
shipyard = { group = "see", wd = "Q190928", label = "Werft" },
spaceport = { group = "see", wd = "Q194188", label = "Weltraumbahnhof" },
square = { group = "see", wd = "Q174782", label = "Platz" },
statue = { group = "see", wd = "Q179700", label = "Statue, Skulptur" },
stele = { group = "see", wd = "Q178743", label = "Stele" },
stolperstein = { group = "see", wd = "Q314003", label = "Stolperstein" },
technical_monument = { group = "see", wd = "Q1516537", label = "technisches Denkmal" },
tomb = { group = "see", wd = { "Q381885", "Q6023295" }, label = "Grabkammer" },
tower = { group = "see", wd = "Q12518", label = "Turm" },
town_hall = { group = "see", wd = "Q543654", label = "Rathaus" },
treasure_hall = { group = "see", wd = "Q133269026", label = "Schatzkammer" },
tumulus = { group = "see", wd = "Q34023", label = "Tumulus, Hügelgrab" },
viaduct = { group = "see", wd = "Q181348", label = "Viadukt" },
wall = { group = "see", wd = "Q42948", label = "Mauer" },
war_grave = { group = "see", wd = "Q90717531", label = "Kriegsgrab" },
war_memorial = { group = "see", wd = "Q575759", label = "Kriegsgedenkstätte, Kriegerdenkmal" },
watermill = { group = "see", wd = "Q185187", label = "Wassermühle" },
weather_station = { group = "see", wd = "Q190107", label = "Wetterstation" },
weir = { group = "see", wd = "Q1066997", label = "Stauwehr" },
well = { group = "see", wd = "Q43483", label = "Brunnen" },
windmill = { group = "see", wd = "Q38720", label = "Windmühle" },
wreck = { group = "see", wd = "Q852190", label = "Wrack" },
-- group types
see = { group = "see", wd = "Q570116", label = "Sehenswürdigkeit" },
-- culture
arena = { group = "do", wd = "Q641226", label = "Arena" },
arts_center = { group = "do", wd = "Q2190251", label = "Kunstzentrum" },
bird_watching = { group = "do", wd = "Q685629", label = "Vogelbeobachtung" },
bullring = { group = "do", wd = "Q1193438", label = "Stierkampfarena" },
cabaret = { group = "do", wd = "Q131183", label = "Cabaret, Kabarett, Musiktheater" },
cinema = { group = "do", wd = "Q41253", label = "Kino, Filmtheater" },
circus = { group = "do", wd = "Q47928", label = "Zirkus" },
concert_hall = { group = "do", wd = "Q1060829", label = "Konzerthaus" },
conference_center = { group = "do", wd = "Q1378975", label = "Tagungs- oder Konferenzzentrum" },
cultural_center = { group = "do", wd = "Q1329623", label = "Kulturzentrum" },
edutainment = { group = "do", wd = "Q1153173", label = "Edutainment" },
event = { group = "do", wd = "Q1190554", label = "Ereignis, Veranstaltung" },
event_venue = { group = "do", wd = "Q18674739", label = "Veranstaltungszentrum" },
fair = { group = "do", wd = { "Q57305", "Q2948561" }, label = "Messe, Handelsmesse" },
festival = { group = "do", wd = "Q132241", label = "Festspiele" },
heritage_railway = { group = "do", wd = "Q420962", label = "Museumsbahn, Museumseisenbahn" },
karaoke = { group = "do", wd = "Q229345", label = "Karaoke" },
labyrinth = { group = "do", wd = "Q48963", label = "Labyrinth" },
lazy_river = { group = "do", wd = "Q3220071", label = "Lazy River" },
[ "multi-purpose_hall" ] = { group = "do", wd = { "Q1763828", "Q2400020" }, label = "Mehrzweckhalle" },
music = { group = "do", wd = "Q638", label = "Musikdarbietung" }, -- different types of music theaters
opera_house = { group = "do", wd = "Q153562", label = "Opernhaus" },
puppet_theater = { group = "do", wd = "Q3982337", label = "Puppentheater" },
recording_studio = { group = "do", wd = "Q746369", label = "Tonstudio" },
sightseeing_flight = { alias = "pleasure_flight", group = "do", wd = "Q1425541", label = "Rundflug" },
theater = { group = "do", wd = { "Q11635", "Q24354" }, label = "Theater", icon = "theatre" }, -- speech theater, theater in general
themed_travel = { group = "do", label = "Themenreisen" },
wildlife_observation = { group = "do", wd = { "Q28455557", "Q241741" }, label = "Tierbeobachtung" },
-- recreation
amusement_park = { group = "do", wd = "Q194195", label = "Freizeitpark" },
attraction = { group = "do", wd = "Q2800000", label = "Attraktion" },
ballooning = { group = "do", wd = "Q805325", label = "Ballonfahren" },
brine_bath = { group = "do", wd = "Q1316853", label = "Solbad" },
canopy_walkway = { group = "do", wd = "Q811593", label = "Baumkronenpfad" },
casino = { group = "do", wd = "Q133215", label = "Spielbank, Casino" },
entertainment = { group = "do", wd = "Q173799", label = "Unterhaltung" },
escape_game = { group = "do", wd = "Q1201679", label = "Fluchtspiel, Escape Game" },
falconry_display = { group = "do", wd = "Q1169958", label = "Greifvogelschau, Freiflugvorführung" },
game = { group = "do", wd = "Q11410", label = "Spiel" },
massage = { group = "do", wd = "Q179415", label = "Massagesalon" },
onsen = { group = "do", wd = "Q655311", label = "Onsen" },
picnic = { group = "do", wd = "Q506294", label = "Picknick", icon = "picnic-site" },
playground = { group = "do", wd = "Q11875349", label = "Spielplatz" },
public_bath = { group = "do", wd = "Q785952", label = "Badehaus, Hammam" },
ropes_course = { group = "do", wd = "Q1939700", label = "Seilgarten, Kletterpark" },
sauna = { group = "do", wd = "Q57036", label = "Sauna, Dampfbad" },
spa = { alias = "wellness", group = "do", wd = "Q6882870", label = "Heilbad, Spa, Wellnesscenter" },
theme_park = { group = "do", wd = "Q2416723", label = "Themenpark" },
thermal_bath = { group = "do", wd = "Q1004887", label = "Thermalbad" },
water_park = { group = "do", wd = { "Q740326", "Q118559331" }, label = "Wasserpark, Aquapark, Freizeitbad, Spaßbad" },
water_playground = { group = "do", wd = "Q19984194", label = "Wasserspielplatz" },
youth_center = { group = "do", wd = "Q1302299", label = "Jugendzentrum" },
-- sports and fitness
["9pin"] = { group = "do", wd = "Q706199", label = "Kegeln" },
["10pin"] = { alias = "bowling", group = "do", wd = "Q172809", label = "Bowling", icon = "bowling-alley" },
athletics_track = { group = "do", wd = { "Q1004435", "Q37025296", "Q121072018" }, label = "Leichtathletikanlage" },
archery = { group = "do", wd = "Q108429", label = "Bogenschießen" },
badminton = { group = "do", wd = "Q7291", label = "Badminton" },
barefoot_path = { group = "do", wd = "Q2143241", label = "Barfußpfad" },
baseball = { group = "do", wd = { "Q5369", "Q701629" }, label = "Baseball" },
basketball_court = { group = "do", wd = "Q2341939", label = "Basketballfeld" },
beach = { group = "do", wd = "Q40080", label = "Strand" },
beachvolleyball = { group = "do", wd = "Q4543", label = "Beachvolleyball" },
bicycle_route = { group = "do", wd = { "Q353027", "Q102307360" }, label = "Radwanderweg" },
billiards = { group = "do", wd = "Q3341285", label = "Billard" },
bmx = { group = "do", wd = "Q215184", label = "BMX" },
boat_rental = { group = "do", wd = "Q25384001", label = "Bootsverleih" },
bobsleigh = { group = "do", wd = "Q177275", label = "Bobsport" },
bouldering = { group = "do", wd = "Q852989", label = "Bouldern, Klettern" },
boules = { group = "do", wd = "Q895060", label = "Boules" },
bungee_jumping = { group = "do", wd = "Q193847", label = "Bungeespringen" },
canoe = { group = "do", wd = "Q171529", label = "Bootssport" }, -- Kanu, Kayak
canyoning = { group = "do", wd = "Q206091", label = "Canyoning" },
city_beach = { group = "do", wd = "Q7900097", label = "Stadtstrand" }, -- incl. beach club
court = { group = "do", wd = { "Q41487", "Q136804782" }, label = "Gericht, Tribunal" },
cricket = { group = "do", wd = "Q5375", label = "Cricket" },
cycling = { group = "do", wd = "Q53121", label = "Radfahren" },
dive_center = { alias = { "dive_centre", "diving center" }, group = "do", wd = "Q3664857", label = "Tauchbasis" },
downhill = { group = "do", wd = { "Q319899", "Q121071424" }, label = "Ski Alpin, Abfahrt", icon = "skiing" }, -- alpine/downhill ski route
extreme_sports = { group = "do", wd = "Q309162", label = "Extremsport" },
fishing = { group = "do", wd = "Q14373", label = "Fischen, Angeln" },
fitness_center = { alias = "gym", group = "do", wd = { "Q1065656", "Q30750411" }, label = "Fitnessstudio", icon = "fitness-centre" },
football_pitch = { group = "do", wd = "Q105755419", label = "Fußballfeld" },
gliding = { group = "do", wd = "Q624161", label = "Segelflug" },
golf = { group = "do", wd = { "Q5377", "Q3177122" }, label = "Golf (Sport)" },
hiking = { alias = "trekking", group = "do", wd = "Q12014035", label = "Wandern" },
horse_racing = { group = "do", wd = "Q187916", label = "Pferderennen" },
horse_riding = { alias = "equestrian", group = "do", wd = { "Q179226", "Q902378" }, label = "Reiten" },
hunting = { group = "do", wd = "Q36963", label = "Jagd" },
ice_hockey = { group = "do", wd = "Q41466", label = "Eishockey" },
ice_rink = { group = "do", wd = "Q1282870", label = "Eisbahn" },
ice_skating = { group = "do", wd = "Q779272", label = "Eislaufen" },
ice_stadium = { group = "do", wd = "Q12019965", label = "Eissporthalle" },
indoor_pool = { group = "do", wd = "Q357380", label = "Hallenbad" },
karting = { group = "do", wd = "Q192420", label = "Kartsport" },
kitesurfing = { group = "do", wd = "Q219554", label = "Kitesurfen" },
laser_tag = { group = "do", wd = "Q998303", label = "Laser Tag" },
leisure_center = { group = "do", wd = "Q30313989", label = "Freizeitzentrum" },
minigolf = { group = "do", wd = "Q754796", label = "Minigolf" },
mountain_biking = { group = "do", wd = { "Q520611", "Q223705" }, label = "Mountainbikesport" },
mountain_hiking = { alias = "hillwalking", group = "do", wd = "Q1762646", label = "Bergwandern" },
mountaineering = { alias = "mountain_climbing", group = "do", wd = "Q22857", label = "Bergsteigen" },
motocross = { group = "do", wd = "Q215862", label = "Motocross" },
nordic = { group = "do", wd = "Q216613", label = "Ski Nordisch" }, -- nordic/cross country ski trail
orienteering = { group = "do", wd = "Q29358", label = "Orientierungslauf" },
outdoor_chess = { group = "do", wd = { "Q115997054", "Q110079" }, label = "Freiluftschach, Gartenschach" },
outdoor_pool = { group = "do", wd = "Q13586493", label = "Freibad" },
paintball = { group = "do", wd = "Q192832", label = "Paintball" },
parachuting = { alias = "skydiving", group = "do", wd = "Q193210", label = "Fallschirmspringen" },
paragliding = { group = "do", wd = "Q178380", label = "Paragliding" },
pedalo = { group = "do", wd = "Q1335189", label = "Tretboot" },
petanque = { group = "do", wd = { "Q189317", "Q114646415" }, label = "Pétanque" },
polo = { group = "do", wd = "Q134211", label = "Polo" },
quad_bike = { group = "do", wd = "Q3926537", label = "Quad-Bike" },
racetrack = { group = "do", wd = "Q1777138", label = "Rennbahn" },
rafting = { group = "do", wd = "Q207238", label = "Rafting" }, -- including whitewater rafting
roller_skating = { group = "do", wd = "Q1707432", label = "Rollsport" }, -- including inline roller skating
rowing = { group = "do", wd = "Q159354", label = "Rudern" },
running = { group = "do", wd = "Q3694569", label = "Laufsport" },
sailing = { group = "do", wd = "Q192520", label = "Segeln" },
sandboarding = { group = "do", wd = "Q570459", label = "Sandboarding" },
scuba_diving = { group = "do", wd = "Q1096878", label = "Tauchen" },
shooting_range = { group = "do", wd = "Q521839", label = "Schießstand, Schießplatz" },
skatepark = { group = "do", wd = "Q909906", label = "Skatepark" },
ski_jumping = { group = "do", wd = "Q7718", label = "Skispringen" },
ski_school = { group = "do", wd = "Q2292514", label = "Skischule" },
skitour = { group = "do", wd = "Q1075998", label = "Skitour" },
sledding = { group = "do", wd = "Q3266340", label = "Rodeln" },
snorkeling = { group = "do", wd = "Q2471422", label = "Schnorcheln" },
snow_park = { group = "do", wd = "Q3141488", label = "Snowpark" },
soccer = { group = "do", wd = "Q2736", label = "Fußball" },
summer_toboggan = { group = "do", wd = "Q3266345", label = "Sommerrodelbahn" },
sports = { group = "do", wd = "Q349", label = "Sport" },
sports_venue = { group = "do", wd = { "Q1076486", "Q121071543", "Q120169931" }, label = "Sportstätte" },
squash = { group = "do", wd = { "Q121072153", "Q121085278" }, label = "Squash" },
stadium = { group = "do", wd = { "Q483110", "Q37025296" }, label = "Stadion" },
standup_paddle_boarding = { alias = "sup", group = "do", wd = "Q2035123", label = "Stehpaddeln, Stand-up-Paddling" },
surfing = { group = "do", wd = "Q159992", label = "Surfen" },
swimming = { group = "do", wd = "Q6388", label = "Schwimmen" },
swimming_pool = { group = "do", wd = "Q200023", label = "Schwimmbad" },
table_tennis = { group = "do", wd = "Q3930", label = "Tischtennis" },
tennis = { alias = "tennis_court", group = "do", wd = { "Q847", "Q741118" }, label = "Tennisplatz" },
toboggan = { group = "do", wd = "Q56611604", label = "Rodelbahn" },
tour = { group = "do", label = "Tour, Rundfahrt" },
trail = { alias = "hiking_trail", group = "do", wd = { "Q2143825", "Q628179" }, label = "Wanderweg" },
trampoline_park = { group = "do", wd = "Q107338221", label = "Trampolinpark" },
triathlon = { group = "do", wd = "Q10980", label = "Triathlon" },
velodrome = { group = "do", wd = "Q830528", label = "Radrennbahn", icon = "racetrack-cycling" },
wakeboarding = { group = "do", wd = "Q376040", label = "Wakeboarding" },
water_skiing = { group = "do", wd = "Q472827", label = "Wasserski" },
water_sports = { group = "do", wd = "Q61065", label = "Wassersport" },
winter_sports = { group = "do", wd = "Q204686", label = "Wintersport" },
-- group types
["do"] = { group = "do", label = "Aktivität" },
-- shopping
alcohol_shop = { group = "buy", wd = "Q2632011", label = "Spirituosengeschäft" },
antiquarian = { group = "buy", wd = "Q582794", label = "Antiquariat" },
atm = { group = "buy", wd = "Q81235", label = "Geldautomat, Bankomat" },
bakery = { group = "buy", wd = "Q274393", label = "Bäckerei" },
bank = { group = "buy", wd = "Q22687", label = "Bank, Geldwesen" },
beauty_salon = { group = "buy", wd = "Q1195245", label = "Schönheitssalon" },
beverages = { group = "buy", wd = "Q47504516", label = "Getränkegeschäft" },
bike_shop = { group = "buy", wd = "Q26721034", label = "Fahrradladen" },
book_seller = { alias = "book_shop", group = "buy", wd = "Q200764", label = "Buchhandlung" },
boutique = { group = "buy", wd = "Q1068824", label = "Boutique" },
business_park = { group = "buy", wd = "Q338313", label = "Gewerbegebiet" },
butchery = { group = "buy", wd = "Q13164546", label = "Metzgerei, Fleischerei" },
carpet_shop = { group = "buy", wd = "Q47516346", label = "Teppichgeschäft" },
cheesery = { group = "buy", wd = "Q3088348", label = "Käserei" },
chemist = { alias = "drugstore", group = "buy", wd = "Q1260046", label = "Drogerie" },
collector_shop = { group = "buy", label = "Sammlergeschäft" },
computer_shop = { alias = "computer", wd = "Q43182520", group = "buy", label = "Computergeschäft" },
cosmetics_shop = { group = "buy", wd = "Q47508166", label = "Kosmetik" },
crafts_shop = { group = "buy", wd = "Q101061294", label = "Handwerksgeschäft" },
currency_exchange = { group = "buy", wd = "Q2002539", label = "Wechselstube" },
delicatessen = { group = "buy", wd = { "Q3231410", "Q48635101" }, label = "Feinkostladen" },
department_store = { group = "buy", wd = "Q216107", label = "Warenhaus, Kaufhaus" },
["duty-free_shop"] = { group = "buy", wd = "Q545609", label = "Duty-Free-Geschäft" },
fashion_store = { alias = "clothing_store", group = "buy", wd = "Q2090555", label = "Modeladen, Bekleidungsgeschäft", icon = "clothing-store" },
farm_shop = { group = "buy", wd = "Q1371823", label = "Hofladen" },
flea_market = { group = "buy", wd = "Q385870", label = "Flohmarkt" },
florist = { group = "buy", wd = "Q10431511", label = "Blumenladen" },
grocery = { group = "buy", wd = "Q1295201", label = "Lebensmittelladen" },
hairdresser = { group = "buy", wd = "Q95856773", label = "Friseur" },
industrial_park = { group = "buy", wd = "Q1662100", label = "Industriepark" },
jewellery = { group = "buy", wd = "Q20708021", label = "Juwelier", icon = "jewelry-store" },
kiosk = { group = "buy", wd = "Q693369", label = "Kiosk" },
livestock_market = { group = "buy", wd = "Q13592976", label = "Viehmarkt, Tiermarkt" },
mall = { group = "buy", wd = { "Q11315", "Q31374404" }, label = "Einkaufszentrum, Mall" },
market = { group = "buy", wd = "Q37654", label = "Markt" },
market_hall = { group = "buy", wd = "Q2080521", label = "Markthalle" },
music_shop = { group = "buy", wd = "Q24284215", label = "Musikgeschäft" },
optician = { group = "buy", wd = "Q80144507", label = "Optiker" },
outdoor_retailer = { group = "buy", label = "Outdoor-Händler" },
outlet = { group = "buy", wd = "Q76470", label = "Outlet, Fabrikverkauf" },
pastry_shop = { alias = "confectionery", group = "buy", wd = "Q47505416", label = "Konditorei, Feinbäckerei" },
photo_store = { group = "buy", wd = "Q57262241", label = "Fotogeschäft" },
second_hand = { group = "buy", wd = "Q2925872", label = "Gebrauchtwarenladen" },
shoe_shop = { group = "buy", wd = "Q7500021", label = "Schuhladen", icon = "shoe" },
shop = { group = "buy", wd = "Q213441", label = "Geschäft, Laden, Shop" },
shopping_arcade = { alias = "shopping_passage", group = "buy", wd = "Q97495053", label = "Ladenpassage, Einkaufspassage" },
shopping_district = { group = "buy", wd = "Q27095213", label = "Einkaufsviertel" },
shopping_street = { group = "buy", wd = "Q21000333", label = "Einkaufsstraße" },
souvenir_shop = { group = "buy", wd = "Q865693", label = "Souvenirgeschäft, Andenkenladen" },
sports_shop = { group = "buy", wd = "Q47516567", label = "Sportgeschäft" },
supermarket = { group = "buy", wd = "Q180846", label = "Supermarkt" },
ticket_shop = { alias = { "box_office", "ticket_sales", "ticket_office" }, group = "buy", wd = { "Q47519615", "Q877435", "Q100681367" }, label = "Ticketverkauf" },
vending_machine = { group = "buy", wd = "Q211584", label = "Verkaufsautomat" },
watersports_shop = { group = "buy", label = "Wassersportgeschäft" },
-- group types
buy = { group = "buy", label = "Einkaufen" },
-- cuisine, eating
agriculture = { group = "eat", wd = "Q11451", label = "Landwirtschaft" },
bistro = { group = "eat", wd = "Q866742", label = "Bistro" },
brasserie = { group = "eat", wd = "Q1581509", label = "Brasserie" },
cafe = { group = "eat", wd = "Q30022", label = "Café, Kaffeehaus" },
cafeteria = { group = "eat", wd = "Q8463304", label = "Cafeteria" },
canteen = { group = "eat", wd = "Q54957790", label = "Kantine, Mensa" },
community_kitchen = { group = "eat", wd = "Q28854744", label = "Gemeinschaftsküche, Langar" },
fast_food = { group = "eat", wd = "Q1751429", label = "Fastfood, Schnellrestaurant" },
fish_restaurant = { group = "eat", wd = "Q125216847", label = "Fischrestaurant" },
food = { group = "eat", wd = { "Q2095", "Q736427" }, label = "Lebensmittel" },
grill_site = { group = "eat", wd = "Q1546788", label = "Grillplatz" },
ice_cream = { group = "eat", wd = "Q1311064", label = "Eisdiele" },
izakaya = { group = "eat", wd = "Q1193068", label = "Izakaya-Restaurant" },
pizzeria = { group = "eat", wd = "Q1501212", label = "Pizzeria", icon = "restaurant-pizza" },
restaurant = { group = "eat", wd = "Q11707", label = "Restaurant, Gaststätte, Lokal" },
seafood_restaurant = { alias = "seafood", group = "eat", wd = "Q17102985", label = "Seefisch-Restaurant, Meeresfrüchte-Restaurant", icon = "restaurant-seafood" },
snack_bar = { group = "eat", wd = "Q1318768", label = "Imbissstand, Food-counter, Würstelstand" },
steak_house = { group = "eat", wd = "Q3109696", label = "Steakhaus" },
street_food = { group = "eat", wd = "Q1316209", label = "Street Food" },
takeaway = { group = "eat", wd = { "Q154383", "Q506946" }, label = "Take-away" },
tavern = { group = "eat", wd = { "Q154250", "Q2387565" }, label = "Taverne" },
teahouse = { group = "eat", wd = "Q1072166", label = "Teehaus" },
wine_tavern = { group = "eat", wd = { "Q2556304", "Q1922416" }, label = "Weinstube, Weinlokal, Bodega" },
-- group types
eat = { group = "eat", wd = { "Q27038993", "Q27077054" }, label = "Küche, Essen" },
-- drinking, going out
bar = { group = "drink", wd = "Q187456", label = "Bar" },
beer_garden = { group = "drink", wd = "Q857909", label = "Biergarten", icon = "beer" },
brewery = { group = "drink", wd = "Q131734", label = "Brauerei" },
club = { group = "drink", label = "Club" },
discotheque = { group = "drink", wd = "Q1228895", label = "Diskothek" },
distillery = { group = "drink", wd = "Q1251750", label = "Brennerei" },
drinking_hall = { group = "drink", wd = "Q4101440", label = "Trinkhalle" },
drinking_water = { group = "drink", wd = "Q7892", label = "Trinkwasser" },
nightclub = { group = "drink", wd = "Q622425", label = "Nachtclub" },
pub = { group = "drink", wd = { "Q19754932", "Q12341378" }, label = "Kneipe" },
vineyard = { group = "drink", wd = "Q22715", label = "Weingut, Weinberg" },
wine_cellar = { group = "drink", wd = "Q22995", label = "Weinkeller" },
winery = { group = "drink", wd = "Q20181766", label = "Kellerei" },
-- group types
drink = { group = "drink", wd = "Q5307737", label = "Trinken" },
-- accommodation
appartment = { group = "sleep", wd = "Q617839", label = "Appartement-Hotel" },
alpine_hut = { group = "sleep", wd = "Q182676", label = "Berghütte" },
bed_and_bike = { group = "sleep", label = "Bett und Bike" },
bnb = { group = "sleep", subtype = "y", wd = "Q367914", label = "Bed & Breakfast", icon = "lodging" },
boarding_house = { group = "sleep", subtype = "y", wd = { "Q1558858", "Q1065252" }, label = "Pension" },
boutique_hotel = { group = "sleep", wd = "Q259618", label = "Boutique-Hotel" },
campsite = { group = "sleep", wd = "Q832778", label = "Campingplatz, Zeltplatz" },
caravan_site = { group = "sleep", label = "Caravan-Campingplatz" },
chalet = { group = "sleep", label = "Chalet, Ferienhaus" },
ecolodge = { group = "sleep", wd = "Q3577646", label = "Ecolodge" },
group_accomodation = { group = "sleep", label = "Gruppenunterkunft" },
guest_house = { group = "sleep", wd = "Q2460422", label = "Gästehaus" },
holiday_flat = { group = "sleep", wd = "Q336532", label = "Ferienwohnung" },
hostel = { group = "sleep", wd = "Q654772", label = "Herberge, Hostel", icon = "lodging" },
hotel = { group = "sleep", wd = { "Q27686", "Q63099748" }, label = "Hotel", icon = "lodging" },
hotel_garni = { group = "sleep", subtype = "y", wd = "Q1631103", label = "Hotel garni", icon = "lodging" },
hut = { group = "sleep", wd = "Q5784097", label = "Hütte" },
lodge = { group = "sleep", wd = "Q56439882", label = "Lodge" },
motel = { group = "sleep", wd = "Q216212", label = "Motel", icon = "lodging" },
resort = { group = "sleep", wd = "Q875157", label = "Resort" },
wilderness_hut = { group = "sleep", wd = "Q17087359", label = "Wildnishütte" },
youth_hostel = { group = "sleep", wd = "Q1589077", label = "Jugendherberge" },
-- group types
sleep = { group = "sleep", wd = "Q5056668", label = "Unterkunft" },
-- people
children = { group = "other", wd = "Q7569", label = "Kinder" },
-- health
animal_hospital = { group = "health", wd = "Q1706476", label = "Tierklinikum" },
defibrillator = { group = "health", wd = "Q1450682", label = "Defibrillator" },
dental_emergency_service = { group = "health", label = "Zahnärztlicher Notdienst" },
dentist = { group = "health", wd = "Q2979300", label = "Zahnarzt" },
diving_chamber = { alias = "", group = "health", wd = "Q549046", label = "Dekompressionskammer" },
doctor = { alias ="surgery", group = "health", wd = "Q718966", label = "Arztpraxis" },
emergency = { alias = "emergency_department", group = "health", wd = "Q1295316", label = "Notaufnahme, Notfallstation" },
emergency_medical_services = { group = "health", wd = "Q860447", label = "Rettungsdienst, Notfallrettung" },
first_aid = { group = "health", wd = "Q133981", label = "Erste Hilfe" },
health = { group = "health", wd = "Q12147", label = "Gesundheit" },
health_center = { alias = "clinic", group = "health", wd = { "Q569500", "Q1774898" }, label = "Ärztehaus, Poliklinik" },
hospital = { group = "health", wd = { "Q16917", "Q180370" }, label = "Krankenhaus, Spital" },
kneipp_facility = { group = "health", wd = "Q66425029", label = "Kneipp-Anlage" },
laboratory = { group = "health", wd = { "Q483242", "Q112203425" }, label = "Labor" },
["medical_on-call_service"] = { group = "health", label = "Ärztlicher Bereitschaftsdienst" },
naturopathy = { group = "health", wd = "Q213403", label = "Naturheilkunde" },
nursing_home = { group = "health", wd = "Q837142", label = "Pflegeheim" },
pharmacy = { group = "health", wd = "Q13107184", label = "Apotheke" },
pharmacy_on_standby_duty = { group = "health", label = "Apotheken-Notdienst" },
rehabilitation = { group = "health", wd = "Q2795791", label = "Rehabilitation, Rehaklinik, Kurklinik" },
rescue_center = { group = "health", label = "Rettungsstation" },
veterinary = { group = "health", wd = "Q15850915", label = "Tierarzt" },
-- teaching & learning
academy = { group = "other", wd = "Q162633", label = "Akademie" },
boarding_school = { group = "other", wd = { "Q269770", "Q125783335" }, label = "Internatsschule" },
bookcase = { group = "other", wd = "Q215857", label = "Bücherschrank" },
college = { group = "other", wd = "Q189004", label = "Hochschule, College" },
community_center = { group = "other", wd = "Q77115", label = "Gemeindezentrum" },
cooking_class = { group = "other", label = "Kochkurs" },
education = { alias = "learn", group = "other", wd = "Q8434", label = "Ausbildung" },
folk_high_school = { group = "other", wd = "Q170087", label = "Volkshochschule" },
gymnasium = { group = "other", wd = "Q55043", label = "Gymnasium" },
institute = { group = "other", wd = "Q1664720", label = "Institut" },
kindergarten = { group = "other", wd = "Q126807", label = "Kindergarten" },
language_school = { group = "other", wd = "Q897403", label = "Sprachschule" },
library = { group = "other", wd = { "Q7075", "Q6503358", "Q2061246", "Q50984122" }, label = "Bücherei, Bibliothek" },
nursery = { group = "other", wd = "Q20174673", label = "Kinderkrippe" },
school = { group = "other", wd = "Q3914", label = "Schule" },
university = { group = "other", wd = "Q3918", label = "Universität" },
-- administration and uncategorized
administration = { group = "other", wd = { "Q327333", "Q5283295" }, label = "Verwaltung, Behörde, Amt" },
association = { alias = "society", group = "other", wd = { "Q48204", "Q15911314" }, label = "Verein" },
business_development_agency = { group = "other", label = "Wirtschaftsförderungsgesellschaft" },
checkpoint = { group = "other", wd = "Q88871664", label = "Kontrollpunkt" },
company = { group = "other", wd = "Q6881511", label = "Unternehmen" },
consulate = { group = "other", wd = "Q7843791", label = "Konsulat" },
coworking_space = { group = "other", wd = "Q97307779", label = "Coworking Space" },
customs = { group = "other", wd = "Q182290", label = "Zoll" },
cultural_organisation = { group = "other", wd = "Q29918292", label = "Kulturorganisation" },
embassy = { group = "other", wd = "Q3917681", label = "Botschaft" },
emergency_call = { group = "other", wd = "Q694554", label = "Notruf", icon = "emergency-phone" },
fire_brigade = { group = "other", wd = "Q6498663", label = "Feuerwehr", icon = "fire-station" },
government = { group = "other", wd = "Q16831714", label = "Regierungsgebäude" },
guide = { group = "other", wd = "Q14290559", label = "Fremdenführer" },
hotline = { group = "other", wd = "Q1482145", label = "Hotline" },
internet_cafe = { group = "other", wd = "Q272399", label = "Internetcafé" },
laundry = { group = "other", wd = "Q12893467", label = "Wäscherei" },
list = { group = "other", wd = { "Q12139612", "Q13406463" }, label = "Liste" },
lost_and_found = { group = "other", wd = "Q15983979", label = "Fundbüro" },
military = { group = "other", wd = "Q8473", label = "Militär" },
mobile_telephony = { group = "other", wd = "Q47516435", label = "Mobilfunkgeschäft" },
newspaper = { group = "other", wd = "Q11032", label = "Zeitung, Zeitungsverlag" },
office = { group = "other", wd = "Q182060", label = "Büro" },
organisation = { group = "other", wd = "Q43229", label = "Organisation" },
passport_office = { group = "other", label = "Passstelle" },
payphone = { group = "other", wd = "Q900977", label = "Münzfernsprecher", icon = "telephone" },
phone = { group = "other", wd = "Q11035", label = "Telefon", icon = "telephone" },
police = { group = "other", wd = "Q35535", label = "Polizei" },
post = { group = "other", wd = "Q35054", label = "Postamt" },
register_office = { alias = { "standesamt", "registry_office" }, group = "other", wd = { "Q745221", "Q29127138", "Q206946" }, label = "Standesamt" },
relief_organisation = { group = "other", wd = "Q708676", label = "Wohltätigkeitsorganisation" },
roadside_assistance = { group = "other", wd = "Q337810", label = "Pannenhilfe, Unfallhilfe" },
shelter = { group = "other", wd = { "Q7493941", "Q989946" }, label = "Unterstand" },
toilet = { group = "other", wd = "Q7857", label = "Toiletten" },
tour_operator = { group = "other", wd = "Q133744", label = "Reiseveranstalter" },
tourism_authority = { group = "other", label = "Tourismusbehörde" },
tourist_information = { alias = "visitor_center", group = "other", wd = { "Q1587716", "Q18411786", "Q6031029" }, label = "Touristinformation, Besucherzentrum, Fremdenverkehrsamt", icon = "information" },
travel_agency = { group = "other", wd = "Q217107", label = "Reisebüro" },
weblink = { group = "other", wd = "Q102014", label = "Weblink" },
wlan = { group = "other", wd = "Q334765", label = "WLAN-Hotspot" },
work = { group = "other", wd = "Q6958747", label = "Arbeit" },
-- group types
other = { group = "other", label = "Anderes" },
listing = { group = "other", label = "Listung" },
-- populated areas
city = { group = "populated", wd = "Q515", label = "Stadt" },
fraction = { group = "populated", label = "Ortsteil einer Gemeinde" },
holiday_resort = { group = "populated", wd = "Q3077815", label = "Feriensiedlung" },
municipality = { group = "populated", wd = { "Q15284", "Q17376095", "Q562061" }, label = "Gemeinde" },
quarter = { alias = "neighborhood", group = "populated", wd = { "Q2983893", "Q253019" }, label = "Stadtteil" },
refugee_camp = { group = "populated", wd = "Q622499", label = "Flüchtlingscamp" },
settlement = { group = "populated", wd = "Q486972", label = "Siedlung" },
town = { group = "populated", wd = "Q3957", label = "Kleinstadt" },
village = { group = "populated", wd = "Q532", label = "Dorf" },
-- views
observation_tower = { group = "view", wd = "Q1440300", label = "Aussichtsturm" },
scenic_view = { group = "view", label = "Bildmotiv", icon = "attraction" },
viewpoint = { group = "view", wd = "Q6017969", label = "Aussichtspunkt" },
-- areas
adm1st = { group = "area", wd = "Q10864048", label = "Verwaltungseinheit 1. Ebene" },
adm2nd = { group = "area", wd = "Q13220204", label = "Verwaltungseinheit 2. Ebene" },
adm3rd = { group = "area", wd = "Q13221722", label = "Verwaltungseinheit 3. Ebene" },
country = { group = "area", wd = "Q6256", label = "Land, Staat" },
district = { group = "area", wd = "Q149621", label = "Distrikt" },
region = { group = "area", wd = "Q82794", label = "Region" },
surroundings = { group = "area", wd = "Q2920644", label = "Umgebung" },
vicinity = { group = "area", wd = "Q16968816", label = "Nähe, nahe Umgebung" },
-- error
error = { group = "error", wd = "Q29485", label = "Fehler" }
-- do not remove the following line
-- ##end
}
}
nodf05clh2le0d9awt8uygmptz7wf6e
Modulo:CountryData/Geography
828
4821
73244
71057
2026-09-24T10:44:25Z
RolandUnger
168
Update
73244
Scribunto
text/plain
-- Preventing expensive Wikidata calls
return {
-- administration
moduleInterface = {
suite = 'CountryData',
sub = 'Geography',
serial = '2026-08-19',
item = 65433242
},
-- wiki-specific exceptions for articles with many vCard calls or topic articles
-- to prevent data retrieval on the base of article's Wikidata qualifier id
articles = {
_default = "Q183", -- DE
Q24879 = "Q183", -- Bremen
Q2814 = "Q183", -- Halle (Saale)
Q452401 = "Q183", -- Deutsche Fachwerkstraße
Q1741 = "Q40", -- Wien -> AT
Q19386 = "Q25227", -- ABC-Inseln -> AN
Q5604 = "Q30", -- Arizona/Frank Lloyd Wright -> US
Q15112104= "Q79", -- Hamada -> EG
Q214077 = "Q801", -- Via Dolorosa -> IL
-- historic regions
Q564882 = "Q36", -- Dobriner Land -> PL
Q661110 = "Q36", -- Glatzer Ländchen
Q178813 = "Q38", -- Herculaneum -> IT
Q283680 = "Q43", -- Karkemisch -> TR
Q672344 = "Q36", -- Kulmer Land
Q22880 = "Q183", -- Kurpfalz
Q1801987 = "Q36", -- Lande Lauenburg und Bütow
Q158445 = "Q183", -- Mecklenburg-Schwerin
Q819411 = "Q36", -- Neumark -> PL
Q767089 = "Q23681", -- Salamis -> Nordzypern
Q1294629 = "Q407199", -- Samaria -> PS
Q151005 = "Q183", -- Völkerschlacht
Q159626 = "Q183", -- Württemberg
},
-- continent list
continents = {
Q15 = "af",
Q51 = "an",
Q48 = "as",
Q3960 = "au",
Q46 = "eu",
Q49 = "na",
Q538 = "oc",
Q18 = "sa"
},
-- countries list sorted by ISO 3166 code
-- add contains additional show parameters link all, inline
-- de-wiki: exceptions: at, ch, de, it: show = "inline"
countries = {
Q244165 = { cont = "as", iso_3166 = "", cc = "+37447", lang = "hy", currency = "Q130498", country = "Arzach" }, -- Bergkarabach
Q228 = { cont = "eu", iso_3166 = "AD", cc = "+376", lang = "ca", currency = "Q4916", country = "Andorra" },
Q878 = { cont = "as", iso_3166 = "AE", cc = "+971", lang = "ar", currency = "Q200294", country = "Vereinigte Arabische Emirate" },
Q889 = { cont = "as", iso_3166 = "AF", cc = "+93", lang = "ps", currency = "Q199471", country = "Afghanistan" },
Q781 = { cont = "na", iso_3166 = "AG", cc = "+1-268", lang = "en", currency = "Q26365", country = "Antigua und Barbuda" },
Q222 = { cont = "eu", iso_3166 = "AL", cc = "+355", lang = "sq", currency = "Q125999", country = "Albanien" },
Q399 = { cont = "as", iso_3166 = "AM", cc = "+374", lang = "hy", currency = "Q130498", country = "Armenien" },
Q916 = { cont = "af", iso_3166 = "AO", cc = "+244", lang = "pt", currency = "Q200337", country = "Angola" },
Q1555938 = { cont = "an", iso_3166 = "AQ", cc = "", lang = "en", currency = "", country = "Antarktis" },
Q21590062= { id = "Q1555938" },
Q414 = { cont = "sa", iso_3166 = "AR", cc = "+54", lang = "es", currency = "Q199578", country = "Argentinien" },
Q40 = { cont = "eu", iso_3166 = "AT", cc = "+43", lang = "de", currency = "Q4916", show = "inline", country = "Österreich" },
Q408 = { cont = "au", iso_3166 = "AU", cc = "+61", lang = "en", currency = "Q259502", country = "Australien" },
Q227 = { cont = "as", iso_3166 = "AZ", cc = "+994", lang = "az", currency = "Q483725", country = "Aserbaidschan" },
Q225 = { cont = "eu", iso_3166 = "BA", cc = "+387", lang = "bs", currency = "Q179620", country = "Bosnien und Herzegowina" },
Q244 = { cont = "na", iso_3166 = "BB", cc = "+1-246", lang = "en", currency = "Q194351", country = "Barbados" },
Q902 = { cont = "as", iso_3166 = "BD", cc = "+880", lang = "bn", currency = "Q194453", country = "Bangladesch" },
Q31 = { cont = "eu", iso_3166 = "BE", cc = "+32", lang = "nl", currency = "Q4916", country = "Belgien" },
Q29999 = { id = "Q31" },
Q965 = { cont = "af", iso_3166 = "BF", cc = "+226", lang = "fr", currency = "Q861690", country = "Burkina Faso" },
Q219 = { cont = "eu", iso_3166 = "BG", cc = "+359", lang = "bg", currency = "Q172540", country = "Bulgarien" },
Q398 = { cont = "as", iso_3166 = "BH", cc = "+973", lang = "ar", currency = "Q201871", country = "Bahrain" },
Q967 = { cont = "af", iso_3166 = "BI", cc = "+257", lang = "fr", currency = "Q238007", country = "Burundi" },
Q962 = { cont = "af", iso_3166 = "BJ", cc = "+229", lang = "fr", currency = "Q861690", country = "Benin" },
Q921 = { cont = "as", iso_3166 = "BN", cc = "+673", lang = "ms", currency = "Q206319", country = "Brunei" },
Q750 = { cont = "sa", iso_3166 = "BO", cc = "+591", lang = "es", currency = "Q200737", country = "Bolivien" },
Q155 = { cont = "sa", iso_3166 = "BR", cc = "+55", lang = "pt", currency = "Q173117", country = "Brasilien" },
Q778 = { cont = "na", iso_3166 = "BS", cc = "+1-242", lang = "en", currency = "Q194339", country = "Bahamas" },
Q917 = { cont = "as", iso_3166 = "BT", cc = "+975", lang = "dz", currency = "Q201799", country = "Bhutan" },
Q963 = { cont = "af", iso_3166 = "BW", cc = "+267", lang = "en", currency = "Q186794", country = "Botsuana" },
Q184 = { cont = "eu", iso_3166 = "BY", cc = "+375", lang = "be", currency = "Q160680", country = "Belarus" },
Q242 = { cont = "na", iso_3166 = "BZ", cc = "+501", lang = "en", currency = "Q275112", country = "Belize" },
Q16 = { cont = "na", iso_3166 = "CA", cc = "+1", lang = "en", currency = "Q1104069", country = "Kanada" },
Q974 = { cont = "af", iso_3166 = "CD", cc = "+243", lang = "fr", currency = "Q4734", country = "Demokratische Republik Kongo" },
Q929 = { cont = "af", iso_3166 = "CF", cc = "+236", lang = "fr", currency = "Q847739", country = "Zentralafrikanische Republik" },
Q971 = { cont = "af", iso_3166 = "CG", cc = "+242", lang = "fr", currency = "Q847739", country = "Republik Kongo" },
Q39 = { cont = "eu", iso_3166 = "CH", cc = "+41", lang = "de", currency = "Q25344", show = "inline", country = "Schweiz" },
Q1008 = { cont = "af", iso_3166 = "CI", cc = "+225", lang = "fr", currency = "Q861690", country = "Elfenbeinküste" },
Q26988 = { cont = "oc", iso_3166 = "CK", cc = "+682", lang = "en", currency = "Q1472704", country = "Cookinseln" },
Q298 = { cont = "sa", iso_3166 = "CL", cc = "+56", lang = "es", currency = "Q200050", country = "Chile" },
Q1009 = { cont = "af", iso_3166 = "CM", cc = "+237", lang = "fr", currency = "Q847739", country = "Kamerun" },
Q148 = { cont = "as", iso_3166 = "CN", cc = "+86", lang = "zh", currency = "Q39099", country = "China" },
Q739 = { cont = "sa", iso_3166 = "CO", cc = "+57", lang = "es", currency = "Q244819", country = "Kolumbien" },
Q800 = { cont = "na", iso_3166 = "CR", cc = "+506", lang = "es", currency = "Q242915", country = "Costa Rica" },
Q241 = { cont = "na", iso_3166 = "CU", cc = "+53", lang = "es", currency = "Q201505", country = "Kuba" },
Q1011 = { cont = "af", iso_3166 = "CV", cc = "+238", lang = "pt", currency = "Q4591", country = "Kap Verde" },
Q229 = { cont = "eu", iso_3166 = "CY", cc = "+357", lang = "el", currency = "Q4916", country = "Zypern" },
Q213 = { cont = "eu", iso_3166 = "CZ", cc = "+420", lang = "cs", currency = "Q131016", country = "Tschechien" },
Q183 = { cont = "eu", iso_3166 = "DE", cc = "+49", lang = "de", currency = "Q4916", show = "inline", country = "Deutschland" },
Q977 = { cont = "af", iso_3166 = "DJ", cc = "+253", lang = "fr", currency = "Q4594", country = "Dschibuti" },
Q35 = { cont = "eu", iso_3166 = "DK", cc = "+45", lang = "da", currency = "Q25417", country = "Dänemark" },
Q756617 = { id = "Q35" },
Q784 = { cont = "na", iso_3166 = "DM", cc = "+1-767", lang = "en", currency = "Q26365", country = "Dominica" },
Q786 = { cont = "na", iso_3166 = "DO", cc = "+1-809", lang = "es", currency = "Q242922", country = "Dominikanische Republik" },
Q262 = { cont = "af", iso_3166 = "DZ", cc = "+213", lang = "fr", currency = "Q199674", country = "Algerien" },
Q736 = { cont = "sa", iso_3166 = "EC", cc = "+593", lang = "es", currency = "Q4917", country = "Ecuador" },
Q191 = { cont = "eu", iso_3166 = "EE", cc = "+372", lang = "et", currency = "Q4916", country = "Estland" },
Q79 = { cont = "af", iso_3166 = "EG", cc = "+20", lang = "ar", currency = "Q199462", phoneDigits = 4, show = "all", country = "Ägypten" },
Q6250 = { cont = "af", iso_3166 = "EH", cc = "+212", lang = "ar", currency = "Q200192", country = "Westsahara" },
Q40362 = { id = "Q6250" },
Q986 = { cont = "af", iso_3166 = "ER", cc = "+291", lang = "ti", currency = "Q171503", country = "Eritrea" },
Q29 = { cont = "eu", iso_3166 = "ES", cc = "+34", lang = "es", currency = "Q4916", country = "Spanien" },
Q115 = { cont = "af", iso_3166 = "ET", cc = "+251", lang = "am", currency = "Q206243", show = "all", country = "Äthiopien" },
Q33 = { cont = "eu", iso_3166 = "FI", cc = "+358", lang = "fi", currency = "Q4916", country = "Finnland" },
Q712 = { cont = "oc", iso_3166 = "FJ", cc = "+679", lang = "fj", currency = "Q4592", country = "Fidschi" },
Q702 = { cont = "oc", iso_3166 = "FM", cc = "+691", lang = "en", currency = "Q4917", country = "Mikronesien" },
Q4628 = { cont = "eu", iso_3166 = "FO", cc = "+298", lang = "da", currency = "Q191068", country = "Färöer" },
Q142 = { cont = "eu", iso_3166 = "FR", cc = "+33", lang = "fr", currency = "Q4916", country = "Frankreich" },
Q1000 = { cont = "af", iso_3166 = "GA", cc = "+241", lang = "fr", currency = "Q847739", country = "Gabun" },
Q145 = { cont = "eu", iso_3166 = "GB", cc = "+44", lang = "en-gb", currency = "Q25224", country = "Vereinigtes Königreich" },
Q124653007 = { id = "Q145" },
Q769 = { cont = "na", iso_3166 = "GD", cc = "+1-473", lang = "en", currency = "Q26365", country = "Grenada" },
Q230 = { cont = "as", iso_3166 = "GE", cc = "+995", lang = "ka", currency = "Q4608", country = "Georgien" },
Q31354462= { cont = "as", iso_3166 = "GE-AB", cc ="+7", lang = "ab", currency = "Q41044", country = "Abchasien" },
Q117 = { cont = "af", iso_3166 = "GH", cc = "+233", lang = "en", currency = "Q183530", country = "Ghana" },
Q1005 = { cont = "af", iso_3166 = "GM", cc = "+220", lang = "en", currency = "Q202885", country = "Gambia" },
Q1006 = { cont = "af", iso_3166 = "GN", cc = "+224", lang = "fr", currency = "Q213311", country = "Guinea" },
Q983 = { cont = "af", iso_3166 = "GQ", cc = "+240", lang = "es", currency = "Q847739", country = "Äquatorialguinea" },
Q41 = { cont = "eu", iso_3166 = "GR", cc = "+30", lang = "el", currency = "Q4916", country = "Griechenland" },
Q774 = { cont = "na", iso_3166 = "GT", cc = "+502", lang = "es", currency = "Q207396", country = "Guatemala" },
Q1007 = { cont = "af", iso_3166 = "GW", cc = "+245", lang = "pt", currency = "Q861690", country = "Guinea-Bissau" },
Q734 = { cont = "sa", iso_3166 = "GY", cc = "+592", lang = "en", currency = "Q213005", country = "Guyana" },
Q783 = { cont = "na", iso_3166 = "HN", cc = "+504", lang = "es", currency = "Q4719", phoneDigits = 4, country = "Honduras" },
Q224 = { cont = "eu", iso_3166 = "HR", cc = "+385", lang = "hr", currency = "Q4916", country = "Kroatien" },
Q790 = { cont = "na", iso_3166 = "HT", cc = "+509", lang = "fr", currency = "Q203955", country = "Haiti" },
Q28 = { cont = "eu", iso_3166 = "HU", cc = "+36", lang = "hu", currency = "Q47190", country = "Ungarn" },
Q252 = { cont = "as", iso_3166 = "ID", cc = "+62", lang = "id", currency = "Q41588", country = "Indonesien" },
Q27 = { cont = "eu", iso_3166 = "IE", cc = "+353", lang = "ga", currency = "Q4916", country = "Irland" },
Q801 = { cont = "as", iso_3166 = "IL", cc = "+972", lang = "he", currency = "Q131309", country = "Israel" },
Q575187 = { id = "Q801" },
Q668 = { cont = "as", iso_3166 = "IN", cc = "+91", lang = "hi", currency = "Q80524", country = "Indien" },
Q796 = { cont = "as", iso_3166 = "IQ", cc = "+964", lang = "ar", currency = "Q193094", country = "Irak" },
Q794 = { cont = "as", iso_3166 = "IR", cc = "+98", lang = "fa", currency = "Q188608", country = "Iran" },
Q189 = { cont = "eu", iso_3166 = "IS", cc = "+354", lang = "is", currency = "Q131473", country = "Island" },
Q38 = { cont = "eu", iso_3166 = "IT", cc = "+39", lang = "it", currency = "Q4916", show = "inline", country = "Italien" },
Q766 = { cont = "na", iso_3166 = "JM", cc = "+1-876", lang = "en", currency = "Q209792", country = "Jamaika" },
Q810 = { cont = "as", iso_3166 = "JO", cc = "+962", lang = "ar", currency = "Q203722", country = "Jordanien" },
Q17 = { cont = "as", iso_3166 = "JP", cc = "+81", lang = "ja", currency = "Q8146", country = "Japan" },
Q114 = { cont = "af", iso_3166 = "KE", cc = "+254", lang = "sw", currency = "Q202882", country = "Kenia" },
Q813 = { cont = "as", iso_3166 = "KG", cc = "+996", lang = "ky", currency = "Q35881", country = "Kirgisistan" },
Q424 = { cont = "as", iso_3166 = "KH", cc = "+855", lang = "km", currency = "Q204737", country = "Kambodscha" },
Q710 = { cont = "oc", iso_3166 = "KI", cc = "+686", lang = "en", currency = "Q1049963", country = "Kiribati" },
Q970 = { cont = "af", iso_3166 = "KM", cc = "+269", lang = "ar", currency = "Q267264", country = "Komoren" },
Q763 = { cont = "na", iso_3166 = "KN", cc = "+1-869", lang = "en", currency = "Q26365", country = "Saint Kitts und Nevis" },
Q423 = { cont = "as", iso_3166 = "KP", cc = "+850", lang = "ko", currency = "Q106720", country = "Nordkorea" },
Q884 = { cont = "as", iso_3166 = "KR", cc = "+82", lang = "ko", currency = "Q202040", country = "Südkorea" },
Q817 = { cont = "as", iso_3166 = "KW", cc = "+965", lang = "ar", currency = "Q193098", country = "Kuwait" },
Q232 = { cont = "as", iso_3166 = "KZ", cc = "+7", lang = "kk", currency = "Q173751", country = "Kasachstan" },
Q819 = { cont = "as", iso_3166 = "LA", cc = "+856", lang = "lo", currency = "Q200055", country = "Laos" },
Q822 = { cont = "as", iso_3166 = "LB", cc = "+961", lang = "ar", currency = "Q201880", country = "Libanon" },
Q760 = { cont = "na", iso_3166 = "LC", cc = "+1-758", lang = "en", currency = "Q26365", country = "Saint Lucia" },
Q347 = { cont = "eu", iso_3166 = "LI", cc = "+423", lang = "de", currency = "Q25344", country = "Liechtenstein" },
Q854 = { cont = "as", iso_3166 = "LK", cc = "+94", lang = "si", currency = "Q4596", country = "Sri Lanka" },
Q1014 = { cont = "af", iso_3166 = "LR", cc = "+231", lang = "en", currency = "Q242988", country = "Liberia" },
Q1013 = { cont = "af", iso_3166 = "LS", cc = "+266", lang = "en", currency = "Q208039", country = "Lesotho" },
Q37 = { cont = "eu", iso_3166 = "LT", cc = "+370", lang = "lt", currency = "Q4916", country = "Litauen" },
Q32 = { cont = "eu", iso_3166 = "LU", cc = "+352", lang = "lb", currency = "Q4916", country = "Luxemburg" },
Q211 = { cont = "eu", iso_3166 = "LV", cc = "+371", lang = "lv", currency = "Q4916", country = "Lettland" },
Q1016 = { cont = "af", iso_3166 = "LY", cc = "+218", lang = "ar", currency = "Q190699", country = "Libyen" },
Q1028 = { cont = "af", iso_3166 = "MA", cc = "+212", lang = "ar", currency = "Q200192", country = "Marokko" },
Q235 = { cont = "eu", iso_3166 = "MC", cc = "+377", lang = "fr", currency = "Q4916", country = "Monaco" },
Q217 = { cont = "eu", iso_3166 = "MD", cc = "+373", lang = "mo", currency = "Q181129", country = "Moldau" },
Q236 = { cont = "eu", iso_3166 = "ME", cc = "+382", lang = "sr-me", currency = "Q4916", country = "Montenegro" },
Q1019 = { cont = "af", iso_3166 = "MG", cc = "+261", lang = "mg", currency = "Q4584", country = "Madagaskar" },
Q709 = { cont = "oc", iso_3166 = "MH", cc = "+692", lang = "en", currency = "Q4917", country = "Marshallinseln" },
Q221 = { cont = "eu", iso_3166 = "MK", cc = "+389", lang = "mk", currency = "Q177875", country = "Nordmazedonien" },
Q912 = { cont = "af", iso_3166 = "ML", cc = "+223", lang = "fr", currency = "Q861690", country = "Mali" },
Q836 = { cont = "as", iso_3166 = "MM", cc = "+95", lang = "my", currency = "Q201875", country = "Myanmar" },
Q711 = { cont = "as", iso_3166 = "MN", cc = "+976", lang = "mn", currency = "Q183435", country = "Mongolei" },
Q16644 = { cont = "oc", iso_3166 = "MP", cc ="+1-670", lang = "en", currency = "Q4917", country = "Nördliche Marianen" },
Q1025 = { cont = "af", iso_3166 = "MR", cc = "+222", lang = "ar", currency = "Q207024", country = "Mauretanien" },
Q233 = { cont = "eu", iso_3166 = "MT", cc = "+356", lang = "mt", currency = "Q4916", country = "Malta" },
Q1027 = { cont = "af", iso_3166 = "MU", cc = "+230", lang = "en", currency = "Q212967", country = "Mauritius" },
Q826 = { cont = "as", iso_3166 = "MV", cc = "+960", lang = "dv", currency = "Q206600", country = "Malediven" },
Q1020 = { cont = "af", iso_3166 = "MW", cc = "+265", lang = "en", currency = "Q211694", country = "Malawi" },
Q96 = { cont = "na", iso_3166 = "MX", cc = "+52", lang = "es", currency = "Q4730", country = "Mexiko" },
Q833 = { cont = "as", iso_3166 = "MY", cc = "+60", lang = "ms", currency = "Q163712", country = "Malaysia" },
Q1029 = { cont = "af", iso_3166 = "MZ", cc = "+222", lang = "pt", currency = "Q200753", country = "Mosambik" },
Q1030 = { cont = "af", iso_3166 = "NA", cc = "+264", lang = "en", currency = "Q202462", country = "Namibia" },
Q1032 = { cont = "af", iso_3166 = "NE", cc = "+227", lang = "fr", currency = "Q861690", country = "Niger" },
Q1033 = { cont = "af", iso_3166 = "NG", cc = "+234", lang = "en", currency = "Q203567", country = "Nigeria" },
Q811 = { cont = "na", iso_3166 = "NI", cc = "+505", lang = "es", currency = "Q207312", country = "Nicaragua" },
Q55 = { cont = "eu", iso_3166 = "NL", cc = "+31", lang = "nl", currency = "Q4916", country = "Niederlande" },
Q20 = { cont = "eu", iso_3166 = "NO", cc = "+47", lang = "no", currency = "Q132643", country = "Norwegen" },
Q837 = { cont = "as", iso_3166 = "NP", cc = "+977", lang = "ne", currency = "Q202895", country = "Nepal" },
Q697 = { cont = "oc", iso_3166 = "NR", cc = "+674", lang = "na", currency = "Q259502", country = "Nauru" },
Q34020 = { cont = "oc", iso_3166 = "NU", cc = "+683", lang ="niu", currency = "Q1472704", country = "Niue" },
Q664 = { cont = "oc", iso_3166 = "NZ", cc = "+64", lang = "en", currency = "Q1472704", country = "Neuseeland" },
Q23681 = { cont = "eu", iso_3166 = "", cc = "+90-392", lang = "tr", currency = "Q172872", country = "Nordzypern" },
Q842 = { cont = "as", iso_3166 = "OM", cc = "+968", lang = "ar", currency = "Q272290", country = "Oman" },
Q804 = { cont = "na", iso_3166 = "PA", cc = "+507", lang = "es", currency = "Q210472", country = "Panama" },
Q419 = { cont = "sa", iso_3166 = "PE", cc = "+51", lang = "es", currency = "Q204656", country = "Peru" },
Q691 = { cont = "oc", iso_3166 = "PG", cc = "+675", lang = "ho", currency = "Q200759", country = "Papua-Neuguinea" },
Q928 = { cont = "as", iso_3166 = "PH", cc = "+63", lang = "fil", currency = "Q17193", country = "Philippinen" },
Q843 = { cont = "as", iso_3166 = "PK", cc = "+92", lang = "ur", currency = "Q188289", country = "Pakistan" },
Q36 = { cont = "eu", iso_3166 = "PL", cc = "+48", lang = "pl", currency = "Q123213", country = "Polen" },
Q407199 = { cont = "as", iso_3166 = "PS", cc = "+970", lang = "ar", currency = "Q203722", country = "Palästina" },
Q23792 = { id = "Q407199" },
Q42620 = { id = "Q407199" },
Q219060 = { id = "Q407199" },
Q45 = { cont = "eu", iso_3166 = "PT", cc = "+351", lang = "pt", currency = "Q4916", country = "Portugal" },
Q695 = { cont = "oc", iso_3166 = "PW", cc = "+680", lang = "en", currency = "Q4917", country = "Palau" },
Q733 = { cont = "sa", iso_3166 = "PY", cc = "+595", lang = "es", currency = "Q207514", country = "Paraguay" },
Q846 = { cont = "as", iso_3166 = "QA", cc = "+974", lang = "ar", currency = "Q206386", country = "Katar" },
Q218 = { cont = "eu", iso_3166 = "RO", cc = "+40", lang = "ro", currency = "Q131645", country = "Rumänien" },
Q403 = { cont = "eu", iso_3166 = "RS", cc = "+381", lang = "sr", currency = "Q172524", country = "Serbien" },
Q159 = { cont = "eu", iso_3166 = "RU", cc = "+7", lang = "ru", currency = "Q41044", country = "Russland" },
Q1037 = { cont = "af", iso_3166 = "RW", cc = "+250", lang = "rw", currency = "Q4741", country = "Ruanda" },
Q851 = { cont = "as", iso_3166 = "SA", cc = "+966", lang = "ar", currency = "Q199857", country = "Saudi-Arabien" },
Q685 = { cont = "oc", iso_3166 = "SB", cc = "+677", lang = "en", currency = "Q4597", country = "Salomonen" },
Q1042 = { cont = "af", iso_3166 = "SC", cc = "+248", lang = "en", currency = "Q4595", country = "Seychellen" },
Q1049 = { cont = "af", iso_3166 = "SD", cc = "+249", lang = "ar", currency = "Q271206", show = "all", country = "Sudan" },
Q34 = { cont = "eu", iso_3166 = "SE", cc = "+46", lang = "sv", currency = "Q122922", country = "Schweden" },
Q334 = { cont = "as", iso_3166 = "SG", cc = "+65", lang = "en", currency = "Q190951", country = "Singapur" },
Q215 = { cont = "eu", iso_3166 = "SI", cc = "+386", lang = "sl", currency = "Q4916", country = "Slowenien" },
Q214 = { cont = "eu", iso_3166 = "SK", cc = "+421", lang = "sk", currency = "Q4916", country = "Slowakei" },
Q1044 = { cont = "af", iso_3166 = "SL", cc = "+232", lang = "en", currency = "Q122922", country = "Sierra Leone" },
Q238 = { cont = "eu", iso_3166 = "SM", cc = "+378", lang = "it", currency = "Q4916", country = "San Marino" },
Q1041 = { cont = "af", iso_3166 = "SN", cc = "+221", lang = "fr", currency = "Q861690", country = "Senegal" },
Q1045 = { cont = "af", iso_3166 = "SO", cc = "+252", lang = "so", currency = "Q4603", country = "Somalia" },
Q730 = { cont = "sa", iso_3166 = "SR", cc = "+597", lang = "nl", currency = "Q202036", country = "Suriname" },
Q958 = { cont = "af", iso_3166 = "SS", cc = "+211", lang = "en", currency = "Q244366", country = "Südsudan" },
Q1039 = { cont = "af", iso_3166 = "ST", cc = "+239", lang = "pt", currency = "Q193712", country = "São Tomé und Príncipe" },
Q792 = { cont = "na", iso_3166 = "SV", cc = "+503", lang = "es", currency = "Q4917", country = "El Salvador" },
Q858 = { cont = "as", iso_3166 = "SY", cc = "+963", lang = "ar", currency = "Q240468", country = "Syrien" },
Q1050 = { cont = "af", iso_3166 = "SZ", cc = "+268", lang = "en", currency = "Q4823", country = "Eswatini" },
Q657 = { cont = "af", iso_3166 = "TD", cc = "+235", lang = "ar", currency = "Q847739", country = "Tschad" },
Q945 = { cont = "af", iso_3166 = "TG", cc = "+228", lang = "fr", currency = "Q861690", country = "Togo" },
Q869 = { cont = "as", iso_3166 = "TH", cc = "+66", lang = "th", currency = "Q177882", country = "Thailand" },
Q863 = { cont = "as", iso_3166 = "TJ", cc = "+992", lang = "tg", currency = "Q199886", country = "Tadschikistan" },
Q574 = { cont = "as", iso_3166 = "TL", cc = "+670", lang = "pt", currency = "Q4917", country = "Osttimor" },
Q874 = { cont = "as", iso_3166 = "TM", cc = "+993", lang = "tk", currency = "Q486637", country = "Turkmenistan" },
Q948 = { cont = "af", iso_3166 = "TN", cc = "+216", lang = "ar", currency = "Q4602", country = "Tunesien" },
Q678 = { cont = "oc", iso_3166 = "TO", cc = "+676", lang = "to", currency = "Q4613", country = "Tonga" },
Q43 = { cont = "eu", iso_3166 = "TR", cc = "+90", lang = "tr", currency = "Q172872", country = "Türkei" },
Q754 = { cont = "na", iso_3166 = "TT", cc = "+1-868", lang = "en", currency = "Q242890", country = "Trinidad und Tobago" },
Q672 = { cont = "oc", iso_3166 = "TV", cc = "+688", lang = "tvl", currency = "Q4406", country = "Tuvalu" },
Q865 = { cont = "as", iso_3166 = "TW", cc = "+886", lang = "zh", currency = "Q208526", country = "Taiwan" },
Q924 = { cont = "af", iso_3166 = "TZ", cc = "+255", lang = "sw", currency = "Q4589", country = "Tansania" },
Q907112 = { cont = "eu", iso_3166 = "", cc = "+373", lang = "ru", currency = "Q200979", country = "Transnistrien" }, -- auch Pridnestrowien
Q212 = { cont = "eu", iso_3166 = "UA", cc = "+380", lang = "uk", currency = "Q81893", country = "Ukraine" },
Q1036 = { cont = "af", iso_3166 = "UG", cc = "+256", lang = "sw", currency = "Q4598", country = "Uganda" },
Q30 = { cont = "na", iso_3166 = "US", cc = "+1", lang = "en-us", currency = "Q4917", phoneDigits = 4, country = "Vereinigte Staaten" },
Q77 = { cont = "sa", iso_3166 = "UY", cc = "+598", lang = "es", currency = "Q209272", country = "Uruguay" },
Q265 = { cont = "as", iso_3166 = "UZ", cc = "+998", lang = "uz", currency = "Q487888", country = "Usbekistan" },
Q237 = { cont = "eu", iso_3166 = "VA", cc = "+39", lang = "it", currency = "Q4916", country = "Vatikanstadt" },
Q757 = { cont = "na", iso_3166 = "VC", cc = "+1-784", lang = "en", currency = "Q26365", country = "Saint Vincent und die Grenadinen" },
Q717 = { cont = "sa", iso_3166 = "VE", cc = "+58", lang = "es", currency = "Q56349362", country = "Venezuela" },
Q881 = { cont = "as", iso_3166 = "VN", cc = "+84", lang = "vi", currency = "Q192090", country = "Vietnam" },
Q686 = { cont = "oc", iso_3166 = "VU", cc = "+678", lang = "en", currency = "Q207523", country = "Vanuatu" },
Q683 = { cont = "oc", iso_3166 = "WS", cc = "+685", lang = "sm", currency = "Q4588", country = "Samoa" },
Q1246 = { cont = "eu", iso_3166 = "XK", cc = "+383", lang = "sq", currency = "Q4916", country = "Kosovo" },
Q805 = { cont = "as", iso_3166 = "YE", cc = "+967", lang = "ar", currency = "Q240512", country = "Jemen" },
Q258 = { cont = "af", iso_3166 = "ZA", cc = "+27", lang = "en", currency = "Q181907", country = "Südafrika" },
Q953 = { cont = "af", iso_3166 = "ZM", cc = "+260", lang = "en", currency = "Q21596813", country = "Sambia" },
Q954 = { cont = "af", iso_3166 = "ZW", cc = "+263", lang = "en", currency = "Q4917", country = "Simbabwe" }
},
-- list of administrative entities usually outside of their home countries.
-- These entities are favored over its home countries.
adminEntities = {
-- extraterritorial areas
Q25228 = { cont = "na", iso_3166 = "AI", cc = "+1-264", lang = "en", currency = "Q26365", country = "Anguilla" },
Q25227 = { cont = "na", iso_3166 = "AN", cc = "+599", lang = "nl", currency = "Q4917", country = "Niederländische Antillen" },
Q16641 = { cont = "oc", iso_3166 = "AS", cc = "+1-684", lang = "en", currency = "Q4917", country = "Amerikanisch-Samoa" },
Q21203 = { cont = "na", iso_3166 = "AW", cc = "+297", lang = "nl", currency = "Q232270", country = "Aruba" },
Q5689 = { cont = "eu", iso_3166 = "AX", cc ="+358-18", lang = "sv", currency = "Q4916", country = "Åland" },
Q25362 = { cont = "na", iso_3166 = "BL", cc = "+590", lang = "fr", currency = "Q4916", country = "Saint-Barthélemy" },
Q23635 = { cont = "na", iso_3166 = "BM", cc = "+1-441", lang = "en", currency = "Q210478", country = "Bermuda" },
Q26180 = { cont = "na", iso_3166 = "BQ-SE", cc = "+599", lang = "nl", currency = "Q4917", country = "Niederländische Antillen" }, -- Sint Eustatius, +599-3
Q25528 = { cont = "na", iso_3166 = "BQ-SA", cc = "+599", lang = "nl", currency = "Q4917", country = "Niederländische Antillen" }, -- Saba, +599-4
Q25396 = { cont = "na", iso_3166 = "BQ-BO", cc = "+599", lang = "nl", currency = "Q4917", country = "Niederländische Antillen" }, -- Bonaire, +599-7
Q23408 = { cont = "an", iso_3166 = "BV", cc = "", lang = "", currency = "", country = "Bouvetinsel" },
Q36004 = { cont = "oc", iso_3166 = "CC", cc = "+61891", lang = "en", currency = "Q259502", country = "Kokosinseln" },
Q25279 = { cont = "na", iso_3166 = "CW", cc = "+599-9", lang = "nl", currency = "Q522701", country = "Curaçao" },
Q31063 = { cont = "oc", iso_3166 = "CX", cc = "+61", lang = "en", currency = "Q259502", country = "Weihnachtsinsel" },
Q9648 = { cont = "sa", iso_3166 = "FK", cc = "+500", lang = "en", currency = "Q330044", country = "Falklandinseln" },
Q3769 = { cont = "sa", iso_3166 = "GF", cc = "+594", lang = "fr", currency = "Q4916", country = "Französisch-Guayana" },
Q25230 = { cont = "eu", iso_3166 = "GG", cc = "+44", lang = "en-gb", currency = "Q25224", country = "Guernsey" },
Q1410 = { cont = "eu", iso_3166 = "GI", cc = "+350", lang = "en", currency = "Q41429", country = "Gibraltar" },
Q223 = { cont = "na", iso_3166 = "GL", cc = "+299", lang = "kl", currency = "Q25417", country = "Grönland" },
Q695387 = { id = "Q223" }, -- Kommuneqarfik Sermersooq
Q478813 = { id = "Q223" }, -- Kommune Kujalleq
Q17012 = { cont = "na", iso_3166 = "GP", cc = "+590", lang = "fr", currency = "Q4916", country = "Guadeloupe" },
Q35086 = { cont = "an", iso_3166 = "GS", cc = "+500", lang = "en", currency = "Q25224", country = "Südgeorgien und die Südlichen Sandwichinseln" },
Q16635 = { cont = "oc", iso_3166 = "GU", cc = "+1-671", lang = "en", currency = "Q4917", country = "Guam" },
Q8646 = { cont = "as", iso_3166 = "HK", cc = "+852", lang = "zh", currency = "Q31015", country = "Hongkong" },
Q131198 = { cont = "oc", iso_3166 = "HM", cc = "", lang = "en", currency = "", country = "Heard und McDonaldinseln" },
Q9676 = { cont = "eu", iso_3166 = "IM", cc = "+44", lang = "en-gb", currency = "Q25224", country = "Isle of Man" },
Q43448 = { cont = "af", iso_3166 = "IO", cc = "+246", lang = "en", currency = "Q25224", country = "Britisches Territorium im Indischen Ozean" },
Q785 = { cont = "eu", iso_3166 = "JE", cc = "+44", lang = "en-gb", currency = "Q25224", country = "Jersey" },
Q5785 = { cont = "na", iso_3166 = "KY", cc = "+1-345", lang = "en", currency = "Q319885", country = "Kaymaninseln" },
Q737765 = { id = "Q5785" }, -- Grand Cayman
Q4936407 = { id = "Q5785" }, -- Bodden Town District, Grand Cayman
Q126125 = { cont = "na", iso_3166 = "MF", cc = "+590", lang = "fr", currency = "Q4916", country = "Saint-Martin" }, -- French overseas collectivity
Q14773 = { cont = "as", iso_3166 = "MO", cc = "+853", lang = "zh", currency = "Q241214", country = "Macau" },
Q17054 = { cont = "na", iso_3166 = "MQ", cc = "+596", lang = "fr", currency = "Q4916", country = "Martinique" },
Q13353 = { cont = "na", iso_3166 = "MS", cc = "+1-664", lang = "en", currency = "Q26365", country = "Montserrat" },
Q33788 = { cont = "oc", iso_3166 = "NC", cc = "+687", lang = "fr", currency = "Q214393", country = "Neukaledonien" },
Q31057 = { cont = "oc", iso_3166 = "NF", cc = "+6723", lang = "en", currency = "Q259502", country = "Norfolkinsel" },
Q30971 = { cont = "oc", iso_3166 = "PF", cc = "+689", lang = "fr", currency = "Q214393", country = "Französisch-Polynesien" },
Q34617 = { cont = "na", iso_3166 = "PM", cc = "+508", lang = "fr", currency = "Q4916", country = "Saint Pierre und Miquelon" },
Q35672 = { cont = "oc", iso_3166 = "PN", cc = " +649", lang = "en", currency = "Q1472704", country = "Pitcairninseln" },
Q1183 = { cont = "na", iso_3166 = "PR", cc = "+1-787", lang = "es", currency = "Q4917", country = "Puerto Rico" },
Q485112 = { cont = "af", iso_3166 = "SO", cc = "+252", lang = "so", currency = "Q4603", country = "Puntland" },
Q17070 = { cont = "af", iso_3166 = "RE", cc = "+262", lang = "fr", currency = "Q4916", country = "Réunion" },
Q653514 = { id = "Q17070" }, -- Arrondissement Saint-Denis
Q47045 = { id = "Q17070" }, -- Saint-Denis
Q316887 = { id = "Q17070" }, -- Saint-Paul
Q612189 = { id = "Q17070" }, -- Arrondissement Saint-Paul
Q702426 = { id = "Q17070" }, -- Arrondissement Saint-Pierre
Q192184 = { cont = "af", iso_3166 = "SH", cc = "+290", lang = "en", currency = "Q374453", country = "St. Helena, Ascension und Tristan da Cunha" }, -- Sonderbehandlung Tristan da Cunha, Ascension, Gough-Insel
Q842829 = { cont = "eu", iso_3166 = "SJ", cc = "+47", lang = "no", currency = "Q4916", country = "Svalbard und Jan Mayen" },
Q34754 = { cont = "af", iso_3166 = "SO", cc = "+252", lang = "so", currency = "Q737384", country = "Somaliland" },
Q26273 = { cont = "na", iso_3166 = "SX", cc = "+1-721", lang = "nl", currency = "Q522701", country = "Niederländische Antillen" }, -- Sint Maarten
Q18221 = { cont = "na", iso_3166 = "TC", cc = "+1-649", lang = "en", currency = "Q4917", country = "Turks- und Caicosinseln" },
Q129003 = { cont = "an", iso_3166 = "TF", cc = "+262", lang = "fr", currency = "Q4916", country = "Französische Süd- und Antarktisgebiete" },
Q36823 = { cont = "oc", iso_3166 = "TK", cc = "+690", lang ="tkl", currency = "Q1472704", country = "Tokelau" },
Q16645 = { cont = "oc", iso_3166 = "UM", cc = "", lang = "en", currency = "", country = "United States Minor Outlying Islands" },
Q25305 = { cont = "na", iso_3166 = "VG", cc = "+1-284", lang = "en", currency = "Q4917", country = "Britische Jungferninseln" },
Q11703 = { cont = "na", iso_3166 = "VI", cc = "+1-340", lang = "en", currency = "Q4917", country = "Amerikanische Jungferninseln" },
Q642481 = { id = "Q11703" }, -- Saint Croix
Q849441 = { id = "Q11703" }, -- Saint John
Q463937 = { id = "Q11703" }, -- Saint Thomas
Q35555 = { cont = "oc", iso_3166 = "WF", cc = "+681", lang = "fr", currency = "Q214393", country = "Wallis und Futuna" },
Q17063 = { cont = "af", iso_3166 = "YT", cc = "+262", lang = "fr", currency = "Q4916", country = "Mayotte" },
-- terrae nullius
Q620634 = { cont = "af", iso_3166 = "", cc = "", lang = "ar", currency = "", country = "Bir Tawil" },
-- Antarctica
Q140948 = { cont = "an", iso_3166 = "", cc = "", lang = "en", currency = "", country = "Südliche Shetlandinseln" },
}
}
jqnhna2eyfoje2wd86cwixqlptfa1jh
Modulo:Hours
828
4824
73246
72502
2026-09-24T10:44:37Z
RolandUnger
168
Update
73246
Scribunto
text/plain
-- getting opening hours from Wikidata
-- module variable and administration
local hr = {
moduleInterface = {
suite = 'Hours',
serial = '2026-09-23',
item = 99600452
},
labelTable = nil,
typeTables = nil
}
-- module import
-- require( 'strict' )
local hi = require( 'Module:Hours/i18n' )
local wu = require( 'Module:Wikidata utilities' )
-- local variables
local categIds = {}
local showOptions = {}
local function isSet( s )
return s and s ~= ''
end
-- insert a value into a table only if it is set
local function tableInsert( tab, value )
if isSet( value ) then
table.insert( tab, value )
end
end
-- value count for any variable
local function getCount( tab )
return type( tab ) == 'table' and #tab or 0
end
local function getLabelFromTables( id )
local label = hi.dateIds[ id ]
if not label and hr.labelTable then
label = hr.labelTable[ id ]
end
if not label and hr.typeTables and hr.typeTables.idTable then
local item = hr.typeTables.typeTable[ hr.typeTables.idTable[ id ] ]
if item then
item = item.label or item.n or item
local at = mw.ustring.find( item, ',' )
if at then
item = mw.ustring.sub( item, 1, at - 1 )
end
label = mw.text.trim( item )
end
end
return label
end
-- getting normalized time hh:dd
local function getNormalizedTime( s )
local count
s, count = mw.ustring.gsub( s, hi.texts.timePattern, '%1:%2' )
return ( count > 0 ) and s or nil
end
function hr.formatTime( s )
local t = getNormalizedTime( s )
if not t then
return s
end
local formatStr = hi.texts.formatTime
t = mw.text.split( t, ':', true )
if #t == 1 then
t[ 2 ] = '00'
end
if hi.options.hour12 then
local isAM = true
local n = tonumber( t[ 1 ] )
if n > 12 then
isAM = false
t[ 1 ] = '' .. ( n - 12 )
end
formatStr = isAM and hi.texts.formatAM or hi.texts.formatPM
end
s = mw.ustring.format( formatStr, mw.text.trim( t[ 1 ] ),
mw.text.trim( t[ 2 ] ) )
if hi.options.leadingZero then
s = s:gsub( '^(%d):', '0%1:' )
else
s = s:gsub( '^0(%d):', '%1:' )
end
if hi.options.removeZeros then
s = s:gsub( '^(%d%d?):00', '%1' )
end
return s
end
-- getting label for a qualifier id
-- to save computing time firstly the id will fetched from Hours/i18n table
-- if available, otherwise from Wikidata
local function getLabelFromId( id, wikilang, fallbackLang )
if not isSet( id ) then
return ''
end
-- from table
local label = getLabelFromTables( id )
-- from Wikidata
if not label and mw.wikibase.isValidEntityId( id ) then
label = wu.getLabel( id, wikilang )
if not label and isSet( fallbackLang ) then
label = wu.getLabel( id, fallbackLang )
if label then
categIds.fallbackLabel = 1
end
end
if label then
categIds.hoursLabelFromWikidata = 1
end
end
-- abbreviate labels
if isSet( label ) then
for i, abbr in ipairs( hi.abbr ) do
label = mw.ustring.gsub( label, abbr.f, abbr.a )
end
label = mw.ustring.gsub( label, '', '' ) -- zero-width space
end
-- additional time formatting
if isSet( label ) then
if hi.months then
for full, short in pairs( hi.months ) do
label = mw.ustring.gsub( label, full, short )
end
end
label = hr.formatTime( label )
end
return label or ''
end
local function abbreviateTimeStr( s, all, pattern, repl )
if not isSet( s ) or not isSet( pattern ) or not repl then
return s or ''
end
if all then
s = mw.ustring.gsub( s, pattern, repl )
else
local matchPattern = mw.ustring.gsub( pattern, '%(%%d%)', '' )
local first, stop = mw.ustring.find( s, pattern )
if first then
local second = mw.ustring.find( s, pattern, stop + 1 )
if second and mw.ustring.match( s, matchPattern ) ==
mw.ustring.match( s, matchPattern, stop + 1 ) then
s = mw.ustring.gsub( s, pattern, repl, 1 )
end
end
end
return s
end
-- getting time period string
-- i: position in from and to arrays
-- id: label for P3035 value
local function getTimePeriod( from, to, i, id )
local result = ''
if id and ( id == getLabelFromTables( hi.times.daily )
or id == getLabelFromTables( hi.times.is24_7 ) )
and from and to and from[ i ] == getLabelFromTables( hi.times.Jan1 ) and
to[ i ] == getLabelFromTables( hi.times.Dec31 ) then
return ''
end
if from and isSet( from[ i ] ) and to and isSet( to[ i ] ) then
result = mw.ustring.format( hi.texts.fromTo, from[ i ], to[ i ] )
if isSet( hi.texts.hourPattern ) then
result = abbreviateTimeStr( result, hi.texts.hourReplAll,
hi.texts.hourPattern, hi.texts.hourRepl )
end
elseif from and isSet( from[ i ] ) then
result = mw.ustring.format( hi.texts.from, from[ i ] )
elseif to and isSet( to[ i ] ) then
result = mw.ustring.format( hi.texts.to, to[ i ] )
end
return result
end
local function contains( new, ar )
for i = 1, #ar do
if ar[ i ] == new then
return true
end
end
return false
end
-- collecting all maintenance categories
function hr.getCategories( formatStr, hintsTable )
local result = wu.getCategories( formatStr )
local s, tab
for k, v in pairs( categIds ) do
tab = hi.maintenance[ k ] or hi.maintenance.unknownError
s = hi.formats.category:format( tab.category )
if hi.options.noRecommendations and hintsTable then
if tab.hint and not contains( tab.hint, hintsTable ) then
table.insert( hintsTable, tab.hint )
end
elseif not hi.options.noRecommendations then
s = s .. ( tab.hint and hi.formats.hint:format( tab.hint ) or '' )
end
result = result .. s
end
if showOptions.demo then
-- remove category links
result = result:gsub( '%[%[[^%[]*%]%]', '' )
end
return result
end
-- getting a string with listed days at which an establishment is closed
local function getClosed( arr )
return ( arr and #arr > 0 ) and mw.ustring.format( hi.texts.closed or '%s',
table.concat( arr, hi.texts.comma ) ) or ''
end
-- converting day range from Mo, Tu, We to Mo–We, and so on
local function getRange( arr, minPos, maxPos )
if maxPos > 0 and minPos > 0 and maxPos > minPos then
arr[ minPos ] = mw.ustring.format( hi.texts.fromTo, arr[ minPos ],
arr[ maxPos ] )
for i = maxPos, minPos + 1, -1 do
table.remove( arr, i )
end
end
end
-- looking for day ranges like Mo, Tu, We and so on and converting them
local function convertDayRange( arr )
local count = #arr
local minPos = 0
local maxPos = 0
local value, valueMin
while count > 0 do
value = hi.weekdays[ arr[ count ] ]
if not value then
getRange( arr, minPos, maxPos )
maxPos = 0
elseif maxPos == 0 then
maxPos = count
valueMin = value
elseif maxPos > 0 and value == valueMin - 1 then
minPos = count
valueMin = value
else
getRange( arr, minPos, maxPos )
maxPos = 0
end
count = count - 1
end
getRange( arr, minPos, maxPos )
end
-- concating non-empty strings
local function concatStrings( sep, str1, str2 )
local tab = {}
tableInsert( tab, str1 )
tableInsert( tab, str2 )
return table.concat( tab, sep )
end
-- add comment if not yet exists
local function addComment( tab, value )
if not isSet( value ) then
return
elseif #tab == 0 then
table.insert( tab, value )
else
for i = 1, #tab, 1 do
if tab[ i ] == value then
break
end
if i == #tab then
table.insert( tab, value )
end
end
end
end
-- main function for usage in Lua modules
-- entity: entity id or entity table
-- wikilang: content language of the wiki
-- fallbackLang: optional additional language for fallback
-- formatStr: optional format string for property categories
-- show: table of show options (addCategories, msg, nomsg) or nil
-- lastedit: dat of last edit. If false no date will be fetched
-- labelTabel: additional table with Q-id label pairs
function hr.getHoursFromWikidata( entity, wikilang, fallbackLang, formatStr,
show, lastEdit, labelTable, typeTables )
-- collecting days at which an establishment is closed
local closeDays = {}
local closeDaysHelper = {}
local withStateOfUse = false
local function mergeDays( days )
if not days or #days == 0 then
return
end
for i, day in ipairs( days ) do
if not closeDaysHelper[ day ] then
table.insert( closeDays, day )
closeDaysHelper[ day ] = ''
end
end
end
local function clearDays()
closeDays = {}
closeDaysHelper = {}
end
-- adding additional properties if an additional Q-id table is given
hr.labelTable = labelTable
hr.typeTables = typeTables
-- preparing show options
showOptions = show or {}
showOptions.addCategories = hi.options.addCategories
if showOptions.msg then
showOptions.addCategories = true
elseif showOptions.nomsg then
showOptions.addCategories = false
end
-- format string for property categories
if not isSet( formatStr ) then
formatStr = hi.formats.wikidata
end
-- 1st step: getting statements for P3025: open days
local statements = wu.getValuesWithQualifiers( entity, hi.wd.opened, nil,
hi.wd.all, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang )
lastEdit = wu.getLastedit( lastEdit, statements )
-- converting statements to human-readable strings
local result = {}
local comments, s
local is24_7 = getLabelFromTables( hi.times.is24_7 )
for i, statement in ipairs( statements ) do
-- opening times
local times = {}
local count = math.max( getCount( statement[ hi.wd.hourOpenFrom ] ),
getCount( statement[ hi.wd.hourOpenTo ] ) )
if count > 0 then
for j = 1, count, 1 do
s = getTimePeriod( statement[ hi.wd.hourOpenFrom ],
statement[ hi.wd.hourOpenTo ], j )
if isSet( s ) then
table.insert( times, s )
elseif statement.value ~= is24_7 then
categIds.withoutTime = 1
end
end
elseif statement.value ~= is24_7 then
categIds.withoutTime = 1
end
s = table.concat( times, hi.texts.comma )
-- comments
comments = {}
count = math.max( getCount( statement[ hi.wd.dayOpenFrom ] ),
getCount( statement[ hi.wd.dayOpenTo ] ) )
for j = 1, count, 1 do
addComment( comments,
getTimePeriod( statement[ hi.wd.dayOpenFrom ],
statement[ hi.wd.dayOpenTo ], j, statement.value ) )
end
for j, key in ipairs( hi.wd.comments ) do
if statement[ key ] then
addComment( comments, table.concat( statement[ key ],
hi.texts.comma ) )
end
end
-- concating times and comments
times = {}
tableInsert( times, s )
s = table.concat( comments, hi.texts.comma )
if isSet( s ) then
table.insert( times, mw.ustring.format( hi.texts.parentheses, s ) )
end
local item = {}
tableInsert( item, table.concat( times, hi.texts.space ) )
-- close statements (P3026) as qualifiers for open days property (P3025)
mergeDays( statement[ hi.wd.closed ] )
if not hi.options.clusterClosed and ( i == #statements or
statements[ i ].value ~= statements[ i + 1 ].value ) then
convertDayRange( closeDays )
tableInsert( item, getClosed( closeDays ) )
clearDays()
end
s = table.concat( item, hi.texts.comma )
-- copying each statement to result table
if statement.sort2 == 1 then
tableInsert( result, { value = { statement.value }, times = s } )
elseif s ~= '' then
result[ #result ].times = concatStrings( hi.texts.comma,
result[ #result ].times, s )
end
end
-- checking for duplicates
for i = #result, 2, -1 do
if result[ i ].times == result[ i - 1 ].times then
for j, value in ipairs( result[ i ].value ) do
table.insert( result[ i - 1 ].value, value )
end
table.remove( result, i )
end
end
-- converting day range
for i = 1, #result, 1 do
local arr = result[ i ].value
convertDayRange( arr )
result[ i ] = concatStrings( hi.texts.space,
table.concat( arr, hi.texts.comma ), result[ i ].times )
end
-- 2nd step: getting separated close statements (P3026)
statements = wu.getValuesWithQualifiers( entity, hi.wd.closed,
nil, hi.wd.commentsForClosed, hi.wd.retrieved, nil, getLabelFromId, wikilang,
fallbackLang )
if #statements > 0 then
lastEdit = wu.getLastedit( lastEdit, statements )
-- getting closed values
local closed = {}
for i, statement in ipairs( statements ) do
local closedDate = {}
table.insert( closedDate, statement.value )
-- getting comments
comments = {}
for j, key in ipairs( hi.wd.commentsForClosed ) do
if statement[ key ] then
addComment( comments, table.concat( statement[ key ],
hi.texts.comma ) )
end
end
s = table.concat( comments, hi.texts.comma )
if isSet( s ) then
table.insert( closedDate, mw.ustring.format( hi.texts.parentheses, s ) )
end
table.insert( closed, table.concat( closedDate, hi.texts.space ) )
end
mergeDays( closed )
end
convertDayRange( closeDays )
tableInsert( result, getClosed( closeDays ) )
-- 3rd step: adding additional statements
statements = wu.getValuesWithQualifiers( entity, hi.wd.stateOfUse,
nil, {}, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang )
if #statements > 0 then
lastEdit = wu.getLastedit( lastEdit, statements )
for i, statement in ipairs( statements ) do
if statement.value ~= '' then
withStateOfUse = true
table.insert( result, statement.value )
end
end
end
-- merging all statements
result = table.concat( result, hi.texts.semicolon )
-- adding maintenance categories
if result ~= '' then
categIds.hoursFromWikidata = 1
if withStateOfUse then
categIds.isClosed = 1
end
if showOptions.addCategories then
result = result .. hr.getCategories( formatStr )
end
end
return result, lastEdit
end
-- invoke helper functions
-- splitting show parameters
local function splitAndCheck( s )
local arr = {}
local err = {}
if isSet( s ) then
for i, v in ipairs( mw.text.split( s, ',', true ) ) do
v = mw.text.trim( v )
if not hi.show[ v ] then
table.insert( err, v )
else
arr[ v ] = ''
end
end
end
return arr, err
end
-- check if pareameters are valid
local function checkParameters( args )
local err = {}
if not args and type( args ) ~= 'table' then
return err
end
for k, v in pairs( args ) do
if not hi.params[ k ] then
table.insert( err, k )
end
end
return err
end
-- formating and concating error strings
local function getErrorStr( arr, key )
if #arr == 0 then
return ''
end
local tab = hi.maintenance[ key ]
if tab then
local s = hi.formats.category:format( tab.category ) ..
( tab.err and hi.formats.error:format( tab.err ) or '' )
return mw.ustring.format( s, table.concat( arr, hi.texts.comma ) )
end
return key
end
-- main function for template #invoke calls
-- id: Q id of an establishment
-- format: output format like 'opened at %s'
-- fallback: fallback language if labels are not available in content language
function hr.getHours( frame )
local args = frame.args
args.id = mw.text.trim( args.id or '' )
if not isSet( args.id ) or not mw.wikibase.isValidEntityId( args.id ) then
return getErrorStr( { args.id }, 'invalidId' )
end
if not isSet( args.format ) then
args.format = hi.texts.format
else
local count
args.format, count = args.format:gsub( '%%s', '%%s' )
if count ~= 1 then
args.format = hi.texts.format
end
end
args.fallback = args.fallback or ''
local wikilang = mw.getContentLanguage():getCode()
local paramErr = checkParameters( args )
local show, showErr = splitAndCheck( args.show )
local result = hr.getHoursFromWikidata( args.id, wikilang,
args.fallback, '', show, false, nil )
if result ~= '' then
result = mw.ustring.format( args.format, result )
end
return result .. getErrorStr( paramErr, 'unknownParams' )
.. getErrorStr( showErr, 'unknownShowOptions' )
end
return hr
tke67ekooj93psdirvq231h89cf1713
Modulo:Hours/i18n
828
4825
73245
72062
2026-09-24T10:44:32Z
RolandUnger
168
Update
73245
Scribunto
text/plain
-- This module contains wiki-language specific strings to translate.
return {
-- administration
moduleInterface = {
suite = "Hours",
sub = "Hours/i18n",
serial = "2026-09-23",
item = 99744685
},
-- invoke call parameters
params = {
fallback = "",
format = "",
id = "",
show = ""
},
-- invoke-call show options
show = {
demo = "",
msg = "",
nomsg = ""
},
-- Wikidata property identifiers
wd = {
retrieved = "P813",
validInPeriod = "P1264",
opened = "P3025",
closed = "P3026",
dayOpenFrom = "P3027",
dayOpenTo = "P3028",
natureOfStatement = "P5102",
stateOfUse = "P5817",
hourOpenFrom = "P8626",
hourOpenTo = "P8627",
appliesToJurisdiction = "P1001",
appliesToPart = "P518",
appliesToPeople = "P6001",
occupation = "P106",
of = "P642",
use = "P366",
all = { "P3026", "P3027", "P3028", "P8626", "P8627",
"P1264", "P5102", "P5817",
"P366", "P518", "P642", "P1001", "P6001", "P106" },
comments = { "P1264", "P5102", "P5817",
"P366", "P518", "P642", "P1001", "P6001", "P106" },
commentsForClosed = { "P5102", "P5817",
"P366", "P518", "P642", "P1001", "P6001", "P106" }
},
-- abbreviations for month names
months = {
Januar = "Jan.",
Februar = "Feb.",
[ "März" ] = "Mär.",
April = "Apr.",
Mai = "Mai",
Juni = "Jun.",
Juli = "Jul.",
August = "Aug.",
September = "Sep.",
Oktober = "Okt.",
November = "Nov.",
Dezember = "Dez."
},
weekdays = {
Mo = 1,
Di = 2,
Mi = 3,
Do = 4,
Fr = 5,
Sa = 6,
So = 7
},
-- several strings
texts = {
closed = "geschlossen: %s",
format = "Geöffnet: %s",
-- punctuation
parentheses = "(%s)",
space = " ", -- for instance between days and times
comma = ", ", -- several dates
semicolon = "; ", -- several statesments
from = "ab %s",
fromTo = "%s–%s",
to = "bis %s",
-- formatting of a single time
timePattern = "^(%d%d?)[.:](%d%d?)%s*Uhr$", -- for German wiki
formatTime = "%s:%s", -- or "%s:%s Uhr" etc.
formatDate = "j. M Y",
formatAM = "%s:%s AM",
formatPM = "%s:%s PM",
-- formatting of a time range
hourReplAll = true, -- (formally) replace all occurrences
hourPattern = "", -- empty if no replacement is requested
hourRepl = "",
-- hourReplAll = false, -- replace only first occurrence
-- hourPattern = "(%d)%s+[aApP][mM]", -- empty if no replacement is requested
-- hourRepl = "%1",
},
options = {
addCategories = false,
clusterClosed = true, -- cluster all closing dates at the end
hour12 = false, -- 12 or 24 hours mode
leadingZero = false, -- add or remove zero for hours
noRecommendations = true, -- prevents display of recommendation hints
removeZeros = false -- remove zeros :00 for full hours
},
-- format strings for mu.addMaintenance
formats = {
category = '[[Category:%s]]',
error = ' <span class="error">%s</span>',
hint = ' <span class="voy-check-recommended" style="display: none;">%s</span>',
wikidata = '[[Category:Seiten, die die Wikidata-Eigenschaft %s benutzen]]'
},
-- Category names
maintenance = {
fallbackLabel = { category = 'VCard: Öffnungszeit-Label in Englisch', hint = 'Öffnungszeit-Label in Englisch' },
hoursFromWikidata = { category = 'VCard: Öffnungszeit aus Wikidata' },
isClosed = { category = 'VCard: Einrichtung ist geschlossen', hint = 'Einrichtung ist geschlossen' },
hoursLabelFromWikidata = { category = 'VCard: Öffnungszeit-Label aus Wikidata', hint = 'Öffnungszeit-Label aus Wikidata' },
unknownError = { category = 'VCard: Öffnungszeit mit Fehler', hint = 'Öffnungszeit mit Fehler' },
withoutTime = { category = 'VCard: Öffnungszeit ohne Uhrzeit', hint = 'Öffnungszeit ohne Uhrzeit' },
-- #invoke error messages
invalidId = { category = 'Hours: Ungültige Wikidata-Id', err = 'Ungültige Wikidata-Id: %s' },
unknownParams = { category = 'Hours: Unbekannter Parameter', err = 'Parameter unbekannt: %s' },
unknownShowOptions = { category = 'Hours: Unbekannter Wert für show', err = 'Wert(e) für show unbekannt: %s' }
},
-- time to id conversion
times = {
daily = "Q26214163",
Dec31 = "Q2912",
is24_7 = "Q1571749",
Jan1 = "Q2150"
},
-- several abbreviations
abbr = {
{ f = "[Mm]ontags?", a = "Mo" },
{ f = "[Dd]ienstags?", a = "Di" },
{ f = "[Mm]ittwochs?", a = "Mi" },
{ f = "[Dd]onnerstags?", a = "Do" },
{ f = "[Ff]reitags?", a = "Fr" },
{ f = "[Ss]amstags?", a = "Sa" },
{ f = "[Ss]onnabends?", a = "Sa" },
{ f = "[Ss]onntags?", a = "So" },
{ f = "[Ee]rste[rs]?", a = "1." },
{ f = "[Zz]weite[rs]?", a = "2." },
{ f = "[Dd]ritte[rs]?", a = "3." },
{ f = "[Vv]ierte[rs]?", a = "4." },
{ f = "[Ff]ünfte[rs]?", a = "5." }
},
-- selections of date labels to prevent fetching from Wikidata
dateIds = {
-- Table contains common values only and is used for reduction of
-- computing time. Others will be taken from Wikidata labels.
-- days
Q105 = "Mo",
Q127 = "Di",
Q128 = "Mi",
Q129 = "Do",
Q130 = "Fr",
Q131 = "Sa",
Q132 = "So",
Q211391 = "Wochenende",
-- use Q99528581 instead of Q211391 because it is culturally dependent
Q26214163 = "täglich", -- do not remove this item because it is used in Lua script
Q100274304 = "Mo–Di",
Q116445783 = "Mo–Di, Do",
Q118773943 = "Mo–Di, Do–Fr",
Q104786164 = "Mo–Mi",
Q104057082 = "Mo–Do",
Q97120402 = "Mo–Fr",
Q21282379 = "Mo–Sa",
Q101072294 = "Di–Mi",
Q100320771 = "Di–Do",
Q100157387 = "Di–Fr",
Q100148056 = "Di–Sa",
Q99731947 = "Di–So",
Q100427721 = "Mi–Do",
Q99714084 = "Mi–Fr",
Q100148065 = "Mi–Fr",
Q118773278 = "Mi, Fr",
Q31689308 = "Mi–Sa",
Q116328326 = "Mi, Sa",
Q65681627 = "Mi–So",
Q100332183 = "Mi–So",
Q99731117 = "Mi–Mo",
Q106714964 = "Do–Di",
Q106538987 = "Do–Fr",
Q106541052 = "Do–Sa",
Q100274433 = "Do–So",
Q100427930 = "Fr–Sa",
Q100451849 = "Fr–So",
Q138501313 = "Fr, So",
Q111977440 = "Fr–Mi",
Q102268431 = "Sa–Mi",
Q101766385 = "Sa–Do",
Q99528581 = "Sa–So",
Q106538981 = "So–Mo",
Q111127796 = "So–Mi",
Q100587968 = "So–Do",
Q112703547 = "So–Fr",
Q1571749 = "24/7", -- do not remove this item because it is used in Lua script
Q819073 = "Werktag",
Q1445650 = "Feiertag",
Q1197685 = "Feiertag",
Q2174956 = "Ruhetag",
Q12779928 = "Arbeitstag",
Q116213 = "Ferien",
-- Zero-width spaces are used to keep the week-day terms and to
-- prevent abbreviation
Q14915111 = "Weiberfastnacht",
Q15834118 = "Weiberfastnacht",
Q2245828 = "Nelkensamstag",
Q1241858 = "Tulpensonntag",
Q2085192 = "Tulpensonntag",
Q153134 = "Rosenmontag",
Q4845365 = "Fastnachtsdienstag",
Q123542 = "Aschermittwoch",
Q153308 = "Laetare",
Q2033651 = "Judika",
Q42236 = "Palmsonntag",
Q106333 = "Gründonnerstag",
Q40317 = "Karfreitag",
Q186206 = "Karsamstag",
Q21196 = "Ostern",
Q1512337 = "Ostersonntag",
Q209663 = "Ostermontag",
Q14795170 = "Ostermontag",
Q14916781 = "Osterdienstag",
Q51638 = "Christi Himmelfahrt",
Q39864 = "Pfingsten",
Q2512993 = "Pfingstmontag",
Q14795386 = "Pfingstdienstag",
Q152395 = "Fronleichnam",
Q2304773 = "Erntedankfest",
Q2913791 = "Thanksgiving",
Q59833 = "Totensonntag",
Q19809 = "Weihnachten",
Q10901070 = "Tag der Arbeit",
Q10274 = "Dashahara",
Q464458 = "Fest des Fastenbrechens",
Q10259 = "Holi",
Q131772 = "Chinesisches Neujahrsfest",
Q718778 = "Qingming-Fest",
Q1145566 = "Chinesischer Nationalfeiertag",
Q1622041 = "Hochsaison",
Q99932986 = "Nebensaison",
Q1777301 = "Normalzeit",
Q36669 = "Sommerzeit",
Q107376657 = "Januar bis März",
Q107376740 = "März bis Oktober",
Q121914265 = "März bis November",
Q100157218 = "April bis Oktober",
Q107376636 = "April bis Dezember",
Q107359921 = "Mai bis Oktober",
Q107376754 = "November bis Februar",
Q100157227 = "November bis März",
Q1312 = "Frühling",
Q1313 = "Sommer",
Q1314 = "Herbst",
Q1311 = "Winter",
Q100320775 = "erstes Wochenende im Monat",
Q23034736 = "erster Montag im Monat",
Q51119351 = "zweiter Montag im Monat",
Q51119371 = "dritter Montag im Monat",
Q51119385 = "vierter Montag im Monat",
Q51119411 = "fünfter Montag im Monat",
Q51120546 = "letzter Montag im Monat",
Q51119341 = "erster Donnerstag im Monat",
Q51119361 = "zweiter Donnerstag im Monat",
Q51119378 = "dritter Donnerstag im Monat",
Q51119395 = "vierter Donnerstag im Monat",
Q51119421 = "fünfter Donnerstag im Monat",
Q51120559 = "letzter Donnerstag im Monat",
Q51119344 = "erster Freitag im Monat",
Q51119363 = "zweiter Freitag im Monat",
Q51119381 = "dritter Freitag im Monat",
Q51119398 = "vierter Freitag im Monat",
Q51119425 = "fünfter Freitag im Monat",
Q51120563 = "letzter Freitag im Monat",
Q51119345 = "erster Samstag im Monat",
Q51119367 = "zweiter Samstag im Monat",
Q51119382 = "dritter Samstag im Monat",
Q51119402 = "vierter Samstag im Monat",
Q51119427 = "fünfter Samstag im Monat",
Q51120565 = "letzter Samstag im Monat",
Q51119350 = "erster Sonntag im Monat",
Q51119369 = "zweiter Sonntag im Monat",
Q51119383 = "dritter Sonntag im Monat",
Q51119404 = "vierter Sonntag im Monat",
Q51119429 = "fünfter Sonntag im Monat",
Q51120567 = "letzter Sonntag im Monat",
Q108 = "Jan.",
Q2150 = "1. Jan.", -- do not remove this item because it is used in Lua script
Q196627 = "1. Jan.",
Q2151 = "2. Jan.",
Q2156 = "3. Jan.",
Q2221 = "6. Jan.",
Q1139536 = "26. Jan.", -- India Republic Day
Q2289 = "31. Jan.",
Q109 = "Feb.",
Q2312 = "1. Feb.",
Q2332 = "14. Feb.",
Q2334 = "15. Feb.",
Q2362 = "28. Feb.",
Q2364 = "29. Feb.",
Q110 = "Mär.",
Q2393 = "1. Mär.",
Q2404 = "14. Mär.",
Q2403 = "15. Mär.",
Q2457 = "27. Mär.",
Q2458 = "28. Mär.",
Q2461 = "31. Mär.",
Q118 = "Apr.",
Q2510 = "1. Apr.",
Q2505 = "7. Apr.",
Q2504 = "9. Apr.",
Q2500 = "14. Apr.",
Q2497 = "15. Apr.",
Q2536 = "30. Apr.",
Q119 = "Mai",
Q2544 = "1. Mai",
Q47499 = "1. Mai",
Q2574 = "16. Mai",
Q2591 = "31. Mai",
Q120 = "Jun.",
Q2625 = "1. Jun.",
Q2657 = "30. Jun.",
Q121 = "Jul.",
Q2700 = "1. Jul.",
Q2715 = "31. Jul.",
Q122 = "Aug.",
Q2788 = "1. Aug.",
Q2774 = "15. Aug.",
Q162691 = "15. Aug.", -- Assumption of Mary
Q56106 = "15. Aug.", -- Independence Day, India
Q2830 = "31. Aug.",
Q123 = "Sep.",
Q2859 = "1. Sep.",
Q2846 = "15. Sep.",
Q2881 = "30. Sep.",
Q124 = "Okt.",
Q2913 = "1. Okt.",
Q2932 = "2. Okt.",
Q2931 = "3. Okt.",
Q157582 = "3. Okt.", -- German Unity Day
Q2919 = "15. Okt.",
Q2963 = "16. Okt.",
Q2949 = "31. Okt.",
Q153093 = "31. Okt.", -- Reformation Day
Q125 = "Nov.",
Q2997 = "1. Nov.",
Q2996 = "2. Nov.",
Q2995 = "3. Nov.",
Q2982 = "15. Nov.",
Q3029 = "16. Nov.",
Q3015 = "30. Nov.",
Q126 = "Dez.",
Q2297 = "1. Dez.",
Q2451 = "19. Dez.",
Q2705 = "24. Dez.",
Q106010 = "24. Dez.",
Q2745 = "25. Dez.",
Q2703710 = "25. Dez.", -- Christmas Day
Q2761 = "26. Dez.",
Q15113728 = "26. Dez.",
Q2800 = "27. Dez.",
Q2832 = "28. Dez.",
Q2862 = "29. Dez.",
Q2901 = "30. Dez.",
Q2912 = "31. Dez.", -- do not remove this item because it is used in Lua script
Q11269 = "31. Dez.",
-- points of time
Q573 = "Tag",
Q575 = "Nacht",
Q7722 = "Morgen",
Q986787 = "Vormittag",
Q283102 = "Nachmittag",
Q7725 = "Abend",
Q193294 = "Sonnenaufgang",
Q166564 = "Sonnenuntergang",
Q36402 = "0:00 Uhr",
Q55812411 = "0:00 Uhr",
Q55449532 = "0:30 Uhr",
Q41618001 = "1:00 Uhr",
Q55517345 = "1:00 Uhr",
Q55518450 = "1:30 Uhr",
Q41618006 = "2:00 Uhr",
Q55521280 = "2:00 Uhr",
Q55524996 = "2:30 Uhr",
Q41618076 = "3:00 Uhr",
Q55527754 = "3:00 Uhr",
Q55560170 = "3:30 Uhr",
Q41618081 = "4:00 Uhr",
Q55810628 = "4:00 Uhr",
Q55810646 = "4:15 Uhr",
Q55811293 = "4:30 Uhr",
Q55811308 = "4:45 Uhr",
Q41618165 = "5:00 Uhr",
Q55810695 = "5:00 Uhr",
Q55810711 = "5:15 Uhr",
Q55811314 = "5:30 Uhr",
Q55811331 = "5:45 Uhr",
Q41618168 = "6:00 Uhr",
Q55810762 = "6:00 Uhr",
Q55810778 = "6:15 Uhr",
Q55810795 = "6:30 Uhr",
Q55811354 = "6:45 Uhr",
Q41618172 = "7:00 Uhr",
Q55811431 = "7:00 Uhr",
Q55810845 = "7:15 Uhr",
Q55810863 = "7:30 Uhr",
Q55811437 = "7:45 Uhr",
Q41618176 = "8:00 Uhr",
Q55811455 = "8:00 Uhr",
Q55810913 = "8:15 Uhr",
Q55810929 = "8:30 Uhr",
Q55810940 = "8:40 Uhr",
Q55812499 = "8:45 Uhr",
Q41618181 = "9:00 Uhr",
Q55811413 = "9:00 Uhr",
Q55811478 = "9:15 Uhr",
Q55810994 = "9:30 Uhr",
Q55811012 = "9:45 Uhr",
Q41618185 = "10:00 Uhr",
Q55811483 = "10:00 Uhr",
Q55811062 = "10:30 Uhr",
Q41618189 = "11:00 Uhr",
Q55811097 = "11:00 Uhr",
Q55811133 = "11:30 Uhr",
Q168182 = "12:00 Uhr",
Q55812521 = "12:00 Uhr",
Q55811197 = "12:30 Uhr",
Q47454201 = "12:30 Uhr",
Q55811213 = "12:45 Uhr",
Q41618345 = "13:00 Uhr",
Q55811230 = "13:00 Uhr",
Q55812556 = "13:15 Uhr",
Q55811580 = "13:30 Uhr",
Q55811277 = "13:45 Uhr",
Q41620570 = "14:00 Uhr",
Q55811610 = "14:00 Uhr",
Q55811657 = "14:15 Uhr",
Q55811674 = "14:30 Uhr",
Q55811761 = "14:45 Uhr",
Q41620574 = "15:00 Uhr",
Q55811778 = "15:00 Uhr",
Q55811726 = "15:15 Uhr",
Q55811745 = "15:30 Uhr",
Q55811798 = "15:45 Uhr",
Q41620578 = "16:00 Uhr",
Q55812393 = "16:00 Uhr",
Q55812563 = "16:15 Uhr",
Q55811847 = "16:30 Uhr",
Q55811864 = "16:45 Uhr",
Q41620582 = "17:00 Uhr",
Q55811883 = "17:00 Uhr",
Q55812585 = "17:15 Uhr",
Q55812595 = "17:25 Uhr",
Q55813015 = "17:30 Uhr",
Q55811932 = "17:45 Uhr",
Q41620584 = "18:00 Uhr",
Q55811949 = "18:00 Uhr",
Q55813021 = "18:15 Uhr",
Q55813038 = "18:30 Uhr",
Q55812002 = "18:45 Uhr",
Q41620587 = "19:00 Uhr",
Q55812019 = "19:00 Uhr",
Q55812659 = "19:30 Uhr",
Q41620591 = "20:00 Uhr",
Q55812694 = "20:00 Uhr",
Q55812122 = "20:30 Uhr",
Q41620593 = "21:00 Uhr",
Q55812716 = "21:00 Uhr",
Q55812732 = "21:15 Uhr",
Q55812192 = "21:30 Uhr",
Q55812210 = "21:45 Uhr",
Q41620595 = "22:00 Uhr",
Q55813122 = "22:00 Uhr",
Q55812769 = "22:30 Uhr",
Q44529925 = "23:00 Uhr",
Q55812301 = "23:00 Uhr",
Q55813170 = "23:30 Uhr",
Q55812370 = "24:00 Uhr",
-- for P1264
Q41662 = "Ramadan",
-- for P5102
Q29509043 = "offiziell",
Q29509080 = "inoffiziell",
Q132555 = "de jure",
Q712144 = "de facto",
Q28962310 = "kaum",
Q28962312 = "häufig",
Q18603603 = "möglich",
Q30230067 = "möglich",
Q53737447 = "ursprünglich",
Q18912752 = "umstritten",
Q28831311 = "unbestätigt",
Q24025284 = "ändert sich gelegentlich",
Q4895105 = "Interim",
Q18122778 = "vermutlich",
Q32188232 = "angeblich",
Q1520777 = "gewiss",
Q5727902 = "ungefähr",
Q56644435 = "wahrscheinlich",
-- for P5817
-- empty strings are not displayed
Q29415466 = "", -- "aktiv"
Q29933838 = "außer Betrieb",
Q56651571 = "außer Betrieb",
Q111802839 = "außer Betrieb",
Q104664889 = "dauerhaft geschlossen",
Q55570821 = "", -- "für die Öffentlichkeit zugänglich"
Q55570340 = "für die Öffentlichkeit geschlossen",
Q55654238 = "", -- "in Benutzung"
Q811683 = "im Bau befindlich",
Q12377751 = "im Bau befindlich",
Q109551035 = "", -- "in eingeschränkter Benutzung"
Q63065035 = "", -- "nicht erhalten"
Q11639308 = "stillgelegt",
Q55653430 = "zeitweilig geschlossen",
Q63187954 = "laufende Sanierung",
Q4989906 = "", -- "Denkmal"
Q2086116 = "", -- "Nachnutzung"
Q110713763 = "noch nicht in Benutzung"
}
}
2g5epjtqvwj96gbl2mad56g4yd8f93n
Orienta Riviero
0
5538
73251
71324
2026-09-24T11:39:27Z
Tiguliano
53
73251
wikitext
text/x-wiki
{{Informkesto subregiono
| nomo = Orienta Riviero
| flago =
| flagograndeco =
| lando = Italio
| regiono = Ligurio
| bildo = Dosiero:Liguria 5Terre1 tango7174.jpg
| bildotitolo = La vilaĝo Porto Venere
| situo =
| ĉefurbo =
| areo =
| loĝantaro =
| horzono =
}}
[[File:Costa da Camogli a Genova.jpg|thumb|Marbordo de la Orienta Riviero inter Camogli kaj Ĝenovo, vidita de la monteto malantaŭ Camogli]]
La '''Orienta Riviero''' de Ligurio, (itale: Riviera di Levante; "Rivêa de Levante" en la liguria) estas la marborda parto de Ligurio, kiu, etendiĝas de la urbo Ĝenovo ĝis la regiona limo kun Toskanio.
[[File:Moneglia costa rocciosa.jpg|thumb|La roka marbordo en la proksimaĵoj de [[Moneglia]]]]
[[File:Baia del silenzio panorama-Sestri Levante.JPG|thumb|[[Sestri Levante]] kaj la golfo de Tigulio]]
Turismo sendube reprezentas la ĉefan ekonomian agadon de la Riviero, danke al la milda klimato kaj la natura beleco de la lokoj. Krom somera turismo, dediĉita ĉefe al la uzo de strandoj kaj marbordoj, estas ankaŭ ekskursa kaj kultura turismo distribuata tra la monatoj de la jaro, precipe en lokoj kiel [[Cinque Terre]], [[Porto Venere]] kaj [[Portofino]].
[[Framura]], [[Moneglia]], [[Montemarcello]], [[Vernazza]] kaj [[Tellaro (Lerici) | Tellaro]] estas la marbordaj vilaĝoj de la orienta marbordo kiuj estas parto de la listo de [[La plej belaj vilaĝoj en Italio | plej belaj vilaĝoj en Italio]]. Ankaŭ la turismo de familioj kun infanoj gravegas. La travideblaj akvoj de Ligurio, tiel plenaj de vivo, estas idealaj por sperti aventurojn kun masko kaj spirtubo: infanoj povas ĝui naĝi observante malgrandajn fiŝojn, krabojn, stelojn, mar-erinacojn kaj polpojn.
La "Riviera di Levante" povas esti dividita en malsamajn distriktojn, de okcidento ĝis oriento:
* Golfo Paradiso, de [[Bogliasco]] al [[Monte di Portofino]]
* Golfo de Tigullio, de Monte di Portofino al [[Sestri Levante]]
* Golfetoj de "Levante", de Sestri Levante ĝis Punta Mesco
* [[Cinque Terre]], de Punta Mesco ĝis la Insulo [[Palmaria]]
* Golfo de la Poetoj
* Sarzana marbordo, de la enfluejo de la rivero Magra ĝis la limo kun [[Toskanio]]
=== Urboj ===
*[[Genova]] - Ĉefurbo de la regiono kaj elstara mara urbo, iama mara respubliko.
*[[Camogli]] - Tipa ĉemara vilaĝo, turisma centro konata pro sia ja marinatejo kaj buntaj konstruaĵoj ĉe la marbordo. Ĝi estas parto de la Regiona Natura Parko Portofino.
*[[Chiavari]] - Mezepoka vilaĝo
*[[La Spezia]] - Turisma urbo, sed ankaŭ ŝipkonstruaĵoj kaj grava mararmea haveno.
*[[Porto Venere]] - Malgranda ĉemara vilaĝo fronte al la insuloj [[Palmaria]], Tino kaj Tinetto
*[[Portofino]] - Fama famul-feriejo kun bela haveneto.
*[[Rapallo]] - Turisma urbo ĉe la maro kun longa tradicio de gastamo, (iam precipe de reĝoj kaj nobeloj, kiuj pasigis siajn feriojn tie).
*[[Santa Margherita Ligure]] - Je Kelkaj kilometroj de Imperia kaj Sanremo.
*[[Sestri Levante]] -
=== Aliaj vizitindaj lokoj ===
[[File:Palmaria and Tino.jpg|thumb|la insuloj [[Palmaria]] kaj [[Isola del Tino|Tino]], viditaj de la plaĝo de [[San Terenzo]]]]
*[[Area marina protetta Cinque Terre]]
*[[Parco nazionale delle Cinque Terre]]
*[[Area naturale marina protetta Portofino]]
*[[Parco naturale regionale di Portofino]]
*[[Parco naturale regionale di Montemarcello-Magra-Vara]]
*[[Parco naturale regionale di Porto Venere]] - Komprenas la komunumoj de Porto Venere kaj la insuloj [[Palmaria]], [[Isola del Tino|Tino]] kaj [[Tinetto]]
== Kiel alveni ==
Grava turisma regiono en norda Italio, la Rivera di Ponente estas facile atingebla plurmaniere.
=== Aŭte ===
Estas du aŭtovojoj sur la teritorio de la Orienta Bordo.
* Aŭtovojo A12, trairas la marbordon konektante [[Ĝenovo]]n al [[Livorno]].
* Aŭtovojo A15, ligas [[Parmo]] al [[La Spezia]] transirante la malaltan Taro-valon, la [[Lunigiana]] areo kaj alvenante en la malalta valo de rivero Magra.
La ŝtata vojo 1 Aurelia laŭiras la tutan Riviera. En la sekcio inter Ĝenovo kaj [[Sestri Levante]] ĝi fluas sur marnivelo aŭ, por mallongaj streĉoj, duonvoje laŭ la marbordo. De [[Riva Trigoso]] al La Spezia la vojo foriras de la marbordo kaj grimpas supren tra la montetoj sekvante la naturajn levojn kaj mallevojn de la areo. De La Spezia al la toskana limo ĝi rekomencas ebenan iron.
=== Per ŝipo ===
[[File:Porto di Lavagna.JPG|thumb|left|La haveno de [[Lavagna]]]]
[[File:Portofino_-_2016-06-02_-_View_from_Chiesa_San_Giorgio_-_3284.jpg|thumb|[[Portofino]]]]
Ekzistas multaj turisthavenoj kaj havenetoj sur la marbordo.
=== Per trajno ===
La Riviera di Levante estas trairita de la fervoja linio [[Ĝenovo]] - [[La Spezia]].
{{-}}
{{Parto de|Ligurio}}
gwswesmj5xh7fjhe5b5sa404hhaamc6