Merge pull request #424 from pietervdvn/develop-extra-feature

Location following feature
This commit is contained in:
Pieter Vander Vennet 2021-07-13 15:04:35 +02:00 committed by GitHub
commit 7a06ec1bd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 592 additions and 491 deletions

View file

@ -1,244 +1,262 @@
import * as L from "leaflet";
import {UIEventSource} from "../UIEventSource";
import {Utils} from "../../Utils";
import { UIEventSource } from "../UIEventSource";
import { Utils } from "../../Utils";
import Svg from "../../Svg";
import Img from "../../UI/Base/Img";
import {LocalStorageSource} from "../Web/LocalStorageSource";
import { LocalStorageSource } from "../Web/LocalStorageSource";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
import {VariableUiElement} from "../../UI/Base/VariableUIElement";
import { VariableUiElement } from "../../UI/Base/VariableUIElement";
export default class GeoLocationHandler extends VariableUiElement {
/**
* Wether or not the geolocation is active, aka the user requested the current location
* @private
*/
private readonly _isActive: UIEventSource<boolean>;
/**
* Wether or not the geolocation is active, aka the user requested the current location
* @private
*/
private readonly _isActive: UIEventSource<boolean>;
/**
* Wether or not the geolocation is locked, aka the user requested the current location and wants the crosshair to follow the user
* @private
*/
private readonly _isLocked: UIEventSource<boolean>;
/**
* The callback over the permission API
* @private
*/
private readonly _permission: UIEventSource<string>;
/***
* The marker on the map, in order to update it
* @private
*/
private _marker: L.Marker;
/**
* Literally: _currentGPSLocation.data != undefined
* @private
*/
private readonly _hasLocation: UIEventSource<boolean>;
private readonly _currentGPSLocation: UIEventSource<{ latlng: any; accuracy: number }>;
/**
* Kept in order to update the marker
* @private
*/
private readonly _leafletMap: UIEventSource<L.Map>;
/**
* The date when the user requested the geolocation. If we have a location, it'll autozoom to it the first 30 secs
* @private
*/
private _lastUserRequest: Date;
/**
* A small flag on localstorage. If the user previously granted the geolocation, it will be set.
* On firefox, the permissions api is broken (probably fingerprint resistiance) and "granted + don't ask again" doesn't stick between sessions.
*
* Instead, we set this flag. If this flag is set upon loading the page, we start geolocating immediately.
* If the user denies the geolocation this time, we unset this flag
* @private
*/
private readonly _previousLocationGrant: UIEventSource<string>;
private readonly _layoutToUse: UIEventSource<LayoutConfig>;
/**
* The callback over the permission API
* @private
*/
private readonly _permission: UIEventSource<string>;
/***
* The marker on the map, in order to update it
* @private
*/
private _marker: L.Marker;
/**
* Literally: _currentGPSLocation.data != undefined
* @private
*/
private readonly _hasLocation: UIEventSource<boolean>;
private readonly _currentGPSLocation: UIEventSource<{
latlng: any;
accuracy: number;
}>;
/**
* Kept in order to update the marker
* @private
*/
private readonly _leafletMap: UIEventSource<L.Map>;
/**
* The date when the user requested the geolocation. If we have a location, it'll autozoom to it the first 30 secs
* @private
*/
private _lastUserRequest: Date;
/**
* A small flag on localstorage. If the user previously granted the geolocation, it will be set.
* On firefox, the permissions api is broken (probably fingerprint resistiance) and "granted + don't ask again" doesn't stick between sessions.
*
* Instead, we set this flag. If this flag is set upon loading the page, we start geolocating immediately.
* If the user denies the geolocation this time, we unset this flag
* @private
*/
private readonly _previousLocationGrant: UIEventSource<string>;
private readonly _layoutToUse: UIEventSource<LayoutConfig>;
constructor(
currentGPSLocation: UIEventSource<{ latlng: any; accuracy: number }>,
leafletMap: UIEventSource<L.Map>,
layoutToUse: UIEventSource<LayoutConfig>
) {
const hasLocation = currentGPSLocation.map(
(location) => location !== undefined
);
const previousLocationGrant = LocalStorageSource.Get(
"geolocation-permissions"
);
const isActive = new UIEventSource<boolean>(false);
const isLocked = new UIEventSource<boolean>(false);
constructor(currentGPSLocation: UIEventSource<{ latlng: any; accuracy: number }>,
leafletMap: UIEventSource<L.Map>,
layoutToUse: UIEventSource<LayoutConfig>) {
super(
hasLocation.map(
(hasLocationData) => {
if (isLocked.data) {
return Svg.up_ui();
} else if (hasLocationData) {
return Svg.crosshair_blue_ui();
} else if (isActive.data) {
return Svg.crosshair_blue_center_ui();
} else {
return Svg.crosshair_ui();
}
},
[isActive, isLocked]
)
);
this._isActive = isActive;
this._isLocked = isLocked;
this._permission = new UIEventSource<string>("");
this._previousLocationGrant = previousLocationGrant;
this._currentGPSLocation = currentGPSLocation;
this._leafletMap = leafletMap;
this._layoutToUse = layoutToUse;
this._hasLocation = hasLocation;
const self = this;
const hasLocation = currentGPSLocation.map((location) => location !== undefined);
const previousLocationGrant = LocalStorageSource.Get("geolocation-permissions")
const isActive = new UIEventSource<boolean>(false);
const currentPointer = this._isActive.map(
(isActive) => {
if (isActive && !self._hasLocation.data) {
return "cursor-wait";
}
return "cursor-pointer";
},
[this._hasLocation]
);
currentPointer.addCallbackAndRun((pointerClass) => {
self.SetClass(pointerClass);
});
super(
hasLocation.map(hasLocation => {
this.onClick(() => {
self.init(true);
if (self._isActive.data) {
self._isLocked.setData(!self._isLocked.data);
}
});
this.init(false);
if (hasLocation) {
return Svg.crosshair_blue_ui()
}
if (isActive.data) {
return Svg.crosshair_blue_center_ui();
}
return Svg.crosshair_ui();
}, [isActive])
this._currentGPSLocation.addCallback((location) => {
self._previousLocationGrant.setData("granted");
const timeSinceRequest =
(new Date().getTime() - (self._lastUserRequest?.getTime() ?? 0)) / 1000;
if (timeSinceRequest < 30) {
self.MoveToCurrentLoction(16);
} else if (self._isLocked.data) {
self.MoveToCurrentLoction();
}
let color = "#1111cc";
try {
color = getComputedStyle(document.body).getPropertyValue(
"--catch-detail-color"
);
this._isActive = isActive;
this._permission = new UIEventSource<string>("")
this._previousLocationGrant = previousLocationGrant;
this._currentGPSLocation = currentGPSLocation;
this._leafletMap = leafletMap;
this._layoutToUse = layoutToUse;
this._hasLocation = hasLocation;
const self = this;
} catch (e) {
console.error(e);
}
const icon = L.icon({
iconUrl: Img.AsData(Svg.crosshair.replace(/#000000/g, color)),
iconSize: [40, 40], // size of the icon
iconAnchor: [20, 20], // point of the icon which will correspond to marker's location
});
const currentPointer = this._isActive.map(isActive => {
if (isActive && !self._hasLocation.data) {
return "cursor-wait"
}
return "cursor-pointer"
}, [this._hasLocation])
currentPointer.addCallbackAndRun(pointerClass => {
self.SetClass(pointerClass);
})
const map = self._leafletMap.data;
const newMarker = L.marker(location.latlng, { icon: icon });
newMarker.addTo(map);
this.onClick(() => self.init(true))
this.init(false)
if (self._marker !== undefined) {
map.removeLayer(self._marker);
}
self._marker = newMarker;
});
}
private init(askPermission: boolean) {
const self = this;
if (self._isActive.data) {
self.MoveToCurrentLoction(16);
return;
}
private init(askPermission: boolean) {
const self = this;
const map = this._leafletMap.data;
this._currentGPSLocation.addCallback((location) => {
self._previousLocationGrant.setData("granted");
const timeSinceRequest = (new Date().getTime() - (self._lastUserRequest?.getTime() ?? 0)) / 1000;
if (timeSinceRequest < 30) {
self.MoveToCurrentLoction(16)
}
let color = "#1111cc";
try {
color = getComputedStyle(document.body).getPropertyValue("--catch-detail-color")
} catch (e) {
console.error(e)
}
const icon = L.icon(
{
iconUrl: Img.AsData(Svg.crosshair.replace(/#000000/g, color)),
iconSize: [40, 40], // size of the icon
iconAnchor: [20, 20], // point of the icon which will correspond to marker's location
})
const newMarker = L.marker(location.latlng, {icon: icon});
newMarker.addTo(map);
if (self._marker !== undefined) {
map.removeLayer(self._marker);
}
self._marker = newMarker;
});
try {
navigator?.permissions?.query({name: 'geolocation'})
?.then(function (status) {
console.log("Geolocation is already", status)
if (status.state === "granted") {
self.StartGeolocating(false);
}
self._permission.setData(status.state);
status.onchange = function () {
self._permission.setData(status.state);
}
});
} catch (e) {
console.error(e)
}
if (askPermission) {
self.StartGeolocating(true);
} else if (this._previousLocationGrant.data === "granted") {
this._previousLocationGrant.setData("");
try {
navigator?.permissions
?.query({ name: "geolocation" })
?.then(function (status) {
console.log("Geolocation is already", status);
if (status.state === "granted") {
self.StartGeolocating(false);
}
}
self._permission.setData(status.state);
status.onchange = function () {
self._permission.setData(status.state);
};
});
} catch (e) {
console.error(e);
}
private locate() {
const self = this;
const map: any = this._leafletMap.data;
if (askPermission) {
self.StartGeolocating(true);
} else if (this._previousLocationGrant.data === "granted") {
this._previousLocationGrant.setData("");
self.StartGeolocating(false);
}
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
self._currentGPSLocation.setData({
latlng: [position.coords.latitude, position.coords.longitude],
accuracy: position.coords.accuracy
});
}, function () {
console.warn("Could not get location with navigator.geolocation")
});
return;
} else {
map.findAccuratePosition({
maxWait: 10000, // defaults to 10000
desiredAccuracy: 50 // defaults to 20
});
}
private MoveToCurrentLoction(targetZoom?: number) {
const location = this._currentGPSLocation.data;
this._lastUserRequest = undefined;
if (
this._currentGPSLocation.data.latlng[0] === 0 &&
this._currentGPSLocation.data.latlng[1] === 0
) {
console.debug("Not moving to GPS-location: it is null island");
return;
}
private MoveToCurrentLoction(targetZoom = 16) {
const location = this._currentGPSLocation.data;
this._lastUserRequest = undefined;
// We check that the GPS location is not out of bounds
const b = this._layoutToUse.data.lockLocation;
let inRange = true;
if (b) {
if (b !== true) {
// B is an array with our locklocation
inRange =
b[0][0] <= location.latlng[0] &&
location.latlng[0] <= b[1][0] &&
b[0][1] <= location.latlng[1] &&
location.latlng[1] <= b[1][1];
}
}
if (!inRange) {
console.log(
"Not zooming to GPS location: out of bounds",
b,
location.latlng
);
} else {
this._leafletMap.data.setView(location.latlng, targetZoom);
}
}
private StartGeolocating(zoomToGPS = true) {
const self = this;
console.log("Starting geolocation");
if (this._currentGPSLocation.data.latlng[0] === 0 && this._currentGPSLocation.data.latlng[1] === 0) {
console.debug("Not moving to GPS-location: it is null island")
return;
}
// We check that the GPS location is not out of bounds
const b = this._layoutToUse.data.lockLocation
let inRange = true;
if (b) {
if (b !== true) {
// B is an array with our locklocation
inRange = b[0][0] <= location.latlng[0] && location.latlng[0] <= b[1][0] &&
b[0][1] <= location.latlng[1] && location.latlng[1] <= b[1][1];
}
}
if (!inRange) {
console.log("Not zooming to GPS location: out of bounds", b, location.latlng)
} else {
this._leafletMap.data.setView(
location.latlng, targetZoom
);
}
this._lastUserRequest = zoomToGPS ? new Date() : new Date(0);
if (self._permission.data === "denied") {
self._previousLocationGrant.setData("");
return "";
}
if (this._currentGPSLocation.data !== undefined) {
this.MoveToCurrentLoction(16);
}
private StartGeolocating(zoomToGPS = true) {
const self = this;
console.log("Starting geolocation")
console.log("Searching location using GPS");
this._lastUserRequest = zoomToGPS ? new Date() : new Date(0);
if (self._permission.data === "denied") {
self._previousLocationGrant.setData("");
return "";
}
if (this._currentGPSLocation.data !== undefined) {
this.MoveToCurrentLoction(16)
}
console.log("Searching location using GPS")
this.locate();
if (!self._isActive.data) {
self._isActive.setData(true);
Utils.DoEvery(60000, () => {
if (document.visibilityState !== "visible") {
console.log("Not starting gps: document not visible")
return;
}
this.locate();
})
}
if (self._isActive.data) {
return;
}
self._isActive.setData(true);
navigator.geolocation.watchPosition(
function (position) {
self._currentGPSLocation.setData({
latlng: [position.coords.latitude, position.coords.longitude],
accuracy: position.coords.accuracy,
});
},
function () {
console.warn("Could not get location with navigator.geolocation");
}
);
}
}

View file

@ -26,7 +26,8 @@
"en": "The layer showing picnic tables",
"nl": "Deze laag toont picnictafels",
"it": "Il livello che mostra i tavoli da picnic",
"fr": "La couche montrant les tables de pique-nique"
"fr": "La couche montrant les tables de pique-nique",
"ru": "Слой, отображающий столы для пикника"
},
"tagRenderings": [
{
@ -34,13 +35,15 @@
"en": "What material is this picnic table made of?",
"nl": "Van welk materiaal is deze picnictafel gemaakt?",
"it": "Di che materiale è fatto questo tavolo da picnic?",
"de": "Aus welchem Material besteht dieser Picknicktisch?"
"de": "Aus welchem Material besteht dieser Picknicktisch?",
"ru": "Из чего изготовлен этот стол для пикника?"
},
"render": {
"en": "This picnic table is made of {material}",
"nl": "Deze picnictafel is gemaakt van {material}",
"it": "Questo tavolo da picnic è fatto di {material}",
"de": "Dieser Picknicktisch besteht aus {material}"
"de": "Dieser Picknicktisch besteht aus {material}",
"ru": "Этот стол для пикника сделан из {material}"
},
"freeform": {
"key": "material"

View file

@ -93,7 +93,8 @@
"nl": "De ondergrond bestaat uit <b>houtsnippers</b>",
"en": "The surface consist of <b>woodchips</b>",
"it": "La superficie consiste di <b>trucioli di legno</b>",
"de": "Die Oberfläche besteht aus <b>Holzschnitzeln</b>"
"de": "Die Oberfläche besteht aus <b>Holzschnitzeln</b>",
"ru": "Покрытие из <b>щепы</b>"
}
},
{
@ -154,7 +155,8 @@
"en": "Is this playground lit at night?",
"it": "È illuminato di notte questo parco giochi?",
"fr": "Ce terrain de jeux est-il éclairé la nuit ?",
"de": "Ist dieser Spielplatz nachts beleuchtet?"
"de": "Ist dieser Spielplatz nachts beleuchtet?",
"ru": "Эта игровая площадка освещается ночью?"
},
"mappings": [
{
@ -163,7 +165,8 @@
"nl": "Deze speeltuin is 's nachts verlicht",
"en": "This playground is lit at night",
"it": "Questo parco giochi è illuminato di notte",
"de": "Dieser Spielplatz ist nachts beleuchtet"
"de": "Dieser Spielplatz ist nachts beleuchtet",
"ru": "Эта детская площадка освещается ночью"
}
},
{
@ -172,7 +175,8 @@
"nl": "Deze speeltuin is 's nachts niet verlicht",
"en": "This playground is not lit at night",
"it": "Questo parco giochi non è illuminato di notte",
"de": "Dieser Spielplatz ist nachts nicht beleuchtet"
"de": "Dieser Spielplatz ist nachts nicht beleuchtet",
"ru": "Эта детская площадка не освещается ночью"
}
}
]
@ -189,7 +193,8 @@
"nl": "Wat is de minimale leeftijd om op deze speeltuin te mogen?",
"en": "What is the minimum age required to access this playground?",
"it": "Qual è letà minima per accedere a questo parco giochi?",
"fr": "Quel est l'âge minimal requis pour accéder à ce terrain de jeux ?"
"fr": "Quel est l'âge minimal requis pour accéder à ce terrain de jeux ?",
"ru": "С какого возраста доступна эта детская площадка?"
},
"freeform": {
"key": "min_age",
@ -201,7 +206,8 @@
"nl": "Toegankelijk tot {max_age}",
"en": "Accessible to kids of at most {max_age}",
"it": "Accessibile ai bambini di età inferiore a {max_age}",
"fr": "Accessible aux enfants de {max_age} au maximum"
"fr": "Accessible aux enfants de {max_age} au maximum",
"ru": "Доступно детям до {max_age}"
},
"question": {
"nl": "Wat is de maximaal toegestane leeftijd voor deze speeltuin?",
@ -340,7 +346,8 @@
"en": "Is this playground accessible to wheelchair users?",
"fr": "Ce terrain de jeux est-il accessible aux personnes en fauteuil roulant ?",
"de": "Ist dieser Spielplatz für Rollstuhlfahrer zugänglich?",
"it": "Il campetto è accessibile a persone in sedia a rotelle?"
"it": "Il campetto è accessibile a persone in sedia a rotelle?",
"ru": "Доступна ли детская площадка пользователям кресел-колясок?"
},
"mappings": [
{
@ -350,7 +357,8 @@
"en": "Completely accessible for wheelchair users",
"fr": "Entièrement accessible aux personnes en fauteuil roulant",
"de": "Vollständig zugänglich für Rollstuhlfahrer",
"it": "Completamente accessibile in sedia a rotelle"
"it": "Completamente accessibile in sedia a rotelle",
"ru": "Полностью доступна пользователям кресел-колясок"
}
},
{
@ -360,7 +368,8 @@
"en": "Limited accessibility for wheelchair users",
"fr": "Accessibilité limitée pour les personnes en fauteuil roulant",
"de": "Eingeschränkte Zugänglichkeit für Rollstuhlfahrer",
"it": "Accesso limitato in sedia a rotelle"
"it": "Accesso limitato in sedia a rotelle",
"ru": "Частично доступна пользователям кресел-колясок"
}
},
{
@ -370,7 +379,8 @@
"en": "Not accessible for wheelchair users",
"fr": "Non accessible aux personnes en fauteuil roulant",
"de": "Nicht zugänglich für Rollstuhlfahrer",
"it": "Non accessibile in sedia a rotelle"
"it": "Non accessibile in sedia a rotelle",
"ru": "Недоступна пользователям кресел-колясок"
}
}
]
@ -385,7 +395,8 @@
"nl": "Op welke uren is deze speeltuin toegankelijk?",
"en": "When is this playground accessible?",
"fr": "Quand ce terrain de jeux est-il accessible ?",
"it": "Quando si può accedere a questo campetto?"
"it": "Quando si può accedere a questo campetto?",
"ru": "Когда открыта эта игровая площадка?"
},
"mappings": [
{
@ -394,7 +405,8 @@
"nl": "Van zonsopgang tot zonsondergang",
"en": "Accessible from sunrise till sunset",
"fr": "Accessible du lever au coucher du soleil",
"it": "Si può accedere dall'alba al tramonto"
"it": "Si può accedere dall'alba al tramonto",
"ru": "Открыто от рассвета до заката"
}
},
{

View file

@ -13,7 +13,8 @@
"nl": "Een straatkastje met boeken voor iedereen",
"de": "Ein Bücherschrank am Straßenrand mit Büchern, für jedermann zugänglich",
"fr": "Une armoire ou une boite contenant des livres en libre accès",
"it": "Una vetrinetta ai bordi della strada contenente libri, aperta al pubblico"
"it": "Una vetrinetta ai bordi della strada contenente libri, aperta al pubblico",
"ru": "Уличный шкаф с книгами, доступными для всех"
},
"source": {
"osmTags": "amenity=public_bookcase"
@ -94,7 +95,7 @@
"nl": "Wat is de naam van dit boekenuilkastje?",
"de": "Wie heißt dieser öffentliche Bücherschrank?",
"fr": "Quel est le nom de cette microbibliothèque ?",
"ru": "Как называется общественный книжный шкаф?",
"ru": "Как называется этот общественный книжный шкаф?",
"it": "Come si chiama questa microbiblioteca pubblica?"
},
"freeform": {
@ -125,7 +126,8 @@
"nl": "Er passen {capacity} boeken",
"de": "{capacity} Bücher passen in diesen Bücherschrank",
"fr": "{capacity} livres peuvent entrer dans cette microbibliothèque",
"it": "Questa microbiblioteca può contenere fino a {capacity} libri"
"it": "Questa microbiblioteca può contenere fino a {capacity} libri",
"ru": "{capacity} книг помещается в этот книжный шкаф"
},
"question": {
"en": "How many books fit into this public bookcase?",
@ -147,7 +149,8 @@
"nl": "Voor welke doelgroep zijn de meeste boeken in dit boekenruilkastje?",
"de": "Welche Art von Büchern sind in diesem öffentlichen Bücherschrank zu finden?",
"fr": "Quel type de livres peut-on dans cette microbibliothèque ?",
"it": "Che tipo di libri si possono trovare in questa microbiblioteca?"
"it": "Che tipo di libri si possono trovare in questa microbiblioteca?",
"ru": "Какие книги можно найти в этом общественном книжном шкафу?"
},
"mappings": [
{
@ -179,7 +182,8 @@
"nl": "Boeken voor zowel kinderen als volwassenen",
"de": "Sowohl Bücher für Kinder als auch für Erwachsene",
"fr": "Livres pour enfants et adultes également",
"it": "Sia libri per l'infanzia, sia per l'età adulta"
"it": "Sia libri per l'infanzia, sia per l'età adulta",
"ru": "Книги и для детей, и для взрослых"
}
}
]
@ -232,7 +236,8 @@
"nl": "Is dit boekenruilkastje publiek toegankelijk?",
"de": "Ist dieser öffentliche Bücherschrank frei zugänglich?",
"fr": "Cette microbibliothèque est-elle librement accèssible ?",
"it": "Questa microbiblioteca è ad accesso libero?"
"it": "Questa microbiblioteca è ad accesso libero?",
"ru": "Имеется ли свободный доступ к этому общественному книжному шкафу?"
},
"condition": "indoor=yes",
"mappings": [
@ -242,7 +247,8 @@
"nl": "Publiek toegankelijk",
"de": "Öffentlich zugänglich",
"fr": "Accèssible au public",
"it": "È ad accesso libero"
"it": "È ad accesso libero",
"ru": "Свободный доступ"
},
"if": "access=yes"
},
@ -374,14 +380,16 @@
"nl": "Op welke dag werd dit boekenruilkastje geinstalleerd?",
"de": "Wann wurde dieser öffentliche Bücherschrank installiert?",
"fr": "Quand a été installée cette microbibliothèque ?",
"it": "Quando è stata inaugurata questa microbiblioteca?"
"it": "Quando è stata inaugurata questa microbiblioteca?",
"ru": "Когда был установлен этот общественный книжный шкаф?"
},
"render": {
"en": "Installed on {start_date}",
"nl": "Geplaatst op {start_date}",
"de": "Installiert am {start_date}",
"fr": "Installée le {start_date}",
"it": "È stata inaugurata il {start_date}"
"it": "È stata inaugurata il {start_date}",
"ru": "Установлен {start_date}"
},
"freeform": {
"key": "start_date",
@ -402,7 +410,8 @@
"nl": "Is er een website over dit boekenruilkastje?",
"de": "Gibt es eine Website mit weiteren Informationen über diesen öffentlichen Bücherschrank?",
"fr": "Y a-t-il un site web avec plus d'informations sur cette microbibliothèque ?",
"it": "C'è un sito web con maggiori informazioni su questa microbiblioteca?"
"it": "C'è un sito web con maggiori informazioni su questa microbiblioteca?",
"ru": "Есть ли веб-сайт с более подробной информацией об этом общественном книжном шкафе?"
},
"freeform": {
"key": "website",

View file

@ -32,7 +32,8 @@
"nl": "Een sportterrein",
"fr": "Un terrain de sport",
"en": "A sport pitch",
"it": "Un campo sportivo"
"it": "Un campo sportivo",
"ru": "Спортивная площадка"
},
"tagRenderings": [
"images",
@ -64,7 +65,8 @@
"nl": "Hier kan men basketbal spelen",
"fr": "Ici, on joue au basketball",
"en": "Basketball is played here",
"it": "Qui si gioca a basket"
"it": "Qui si gioca a basket",
"ru": "Здесь можно играть в баскетбол"
}
},
{
@ -77,7 +79,8 @@
"nl": "Hier kan men voetbal spelen",
"fr": "Ici, on joue au football",
"en": "Soccer is played here",
"it": "Qui si gioca a calcio"
"it": "Qui si gioca a calcio",
"ru": "Здесь можно играть в футбол"
}
},
{
@ -104,7 +107,8 @@
"nl": "Hier kan men tennis spelen",
"fr": "Ici, on joue au tennis",
"en": "Tennis is played here",
"it": "Qui si gioca a tennis"
"it": "Qui si gioca a tennis",
"ru": "Здесь можно играть в теннис"
}
},
{
@ -117,7 +121,8 @@
"nl": "Hier kan men korfbal spelen",
"fr": "Ici, on joue au korfball",
"en": "Korfball is played here",
"it": "Qui si gioca a korfball"
"it": "Qui si gioca a korfball",
"ru": "Здесь можно играть в корфбол"
}
},
{
@ -130,7 +135,8 @@
"nl": "Hier kan men basketbal beoefenen",
"fr": "Ici, on joue au basketball",
"en": "Basketball is played here",
"it": "Qui si gioca a basket"
"it": "Qui si gioca a basket",
"ru": "Здесь можно играть в баскетбол"
},
"hideInAnswer": true
}
@ -141,7 +147,8 @@
"nl": "Wat is de ondergrond van dit sportveld?",
"fr": "De quelle surface est fait ce terrain de sport ?",
"en": "Which is the surface of this sport pitch?",
"it": "Qual è la superficie di questo campo sportivo?"
"it": "Qual è la superficie di questo campo sportivo?",
"ru": "Какое покрытие на этой спортивной площадке?"
},
"render": {
"nl": "De ondergrond is <b>{surface}</b>",
@ -211,7 +218,8 @@
"nl": "Is dit sportterrein publiek toegankelijk?",
"fr": "Est-ce que ce terrain de sport est accessible au public ?",
"en": "Is this sport pitch publicly accessible?",
"it": "Questo campo sportivo è aperto al pubblico?"
"it": "Questo campo sportivo è aperto al pubblico?",
"ru": "Есть ли свободный доступ к этой спортивной площадке?"
},
"mappings": [
{
@ -220,7 +228,8 @@
"nl": "Publiek toegankelijk",
"fr": "Accessible au public",
"en": "Public access",
"it": "Aperto al pubblico"
"it": "Aperto al pubblico",
"ru": "Свободный доступ"
}
},
{
@ -229,7 +238,8 @@
"nl": "Beperkt toegankelijk (enkel na reservatie, tijdens bepaalde uren, ...)",
"fr": "Accès limité (par exemple uniquement sur réservation, à certains horaires…)",
"en": "Limited access (e.g. only with an appointment, during certain hours, ...)",
"it": "Accesso limitato (p.es. solo con prenotazione, in certi orari, ...)"
"it": "Accesso limitato (p.es. solo con prenotazione, in certi orari, ...)",
"ru": "Ограниченный доступ (напр., только по записи, в определённые часы, ...)"
}
},
{
@ -238,7 +248,8 @@
"nl": "Enkel toegankelijk voor leden van de bijhorende sportclub",
"fr": "Accessible uniquement aux membres du club",
"en": "Only accessible for members of the club",
"it": "Accesso limitato ai membri dell'associazione"
"it": "Accesso limitato ai membri dell'associazione",
"ru": "Доступ только членам клуба"
}
},
{
@ -257,7 +268,8 @@
"nl": "Moet men reserveren om gebruik te maken van dit sportveld?",
"fr": "Doit-on réserver pour utiliser ce terrain de sport ?",
"en": "Does one have to make an appointment to use this sport pitch?",
"it": "È necessario prenotarsi per usare questo campo sportivo?"
"it": "È necessario prenotarsi per usare questo campo sportivo?",
"ru": "Нужна ли предварительная запись для доступа на эту спортивную площадку?"
},
"condition": {
"and": [
@ -282,7 +294,8 @@
"nl": "Reserveren is sterk aangeraden om gebruik te maken van dit sportterrein",
"fr": "Il est recommendé de réserver pour utiliser ce terrain de sport",
"en": "Making an appointment is recommended when using this sport pitch",
"it": "La prenotazione è consigliata per usare questo campo sportivo"
"it": "La prenotazione è consigliata per usare questo campo sportivo",
"ru": "Желательна предварительная запись для доступа на эту спортивную площадку"
}
},
{
@ -291,7 +304,8 @@
"nl": "Reserveren is mogelijk, maar geen voorwaarde",
"fr": "Il est possible de réserver, mais ce n'est pas nécéssaire pour utiliser ce terrain de sport",
"en": "Making an appointment is possible, but not necessary to use this sport pitch",
"it": "La prenotazione è consentita, ma non è obbligatoria per usare questo campo sportivo"
"it": "La prenotazione è consentita, ma non è obbligatoria per usare questo campo sportivo",
"ru": "Предварительная запись для доступа на эту спортивную площадку возможна, но не обязательна"
}
},
{
@ -300,7 +314,8 @@
"nl": "Reserveren is niet mogelijk",
"fr": "On ne peut pas réserver",
"en": "Making an appointment is not possible",
"it": "Non è possibile prenotare"
"it": "Non è possibile prenotare",
"ru": "Невозможна предварительная запись"
}
}
]
@ -336,7 +351,8 @@
"nl": "Wanneer is dit sportveld toegankelijk?",
"fr": "Quand ce terrain est-il accessible ?",
"en": "When is this pitch accessible?",
"it": "Quando è aperto questo campo sportivo?"
"it": "Quando è aperto questo campo sportivo?",
"ru": "В какое время доступна эта площадка?"
},
"render": "Openingsuren: {opening_hours_table()}",
"freeform": {
@ -446,7 +462,8 @@
"nl": "Ping-pong tafel",
"fr": "Table de ping-pong",
"en": "Tabletennis table",
"it": "Tavolo da tennistavolo"
"it": "Tavolo da tennistavolo",
"ru": "Стол для настольного тенниса"
},
"tags": [
"leisure=pitch",

View file

@ -39,7 +39,8 @@
"en": "What kind of camera is this?",
"nl": "Wat voor soort camera is dit?",
"fr": "Quel genre de caméra est-ce ?",
"it": "Di che tipo di videocamera si tratta?"
"it": "Di che tipo di videocamera si tratta?",
"ru": "Какая это камера?"
},
"mappings": [
{
@ -65,7 +66,8 @@
"en": "A dome camera (which can turn)",
"nl": "Een dome (bolvormige camera die kan draaien)",
"fr": "Une caméra dôme (qui peut tourner)",
"it": "Una videocamera a cupola (che può ruotare)"
"it": "Una videocamera a cupola (che può ruotare)",
"ru": "Камера с поворотным механизмом"
}
},
{
@ -230,7 +232,8 @@
"en": "This camera is located outdoors",
"nl": "Deze camera bevindt zich buiten",
"fr": "Cette caméra est située à l'extérieur",
"it": "Questa videocamera si trova all'aperto"
"it": "Questa videocamera si trova all'aperto",
"ru": "Эта камера расположена снаружи"
}
},
{
@ -239,7 +242,8 @@
"en": "This camera is probably located outdoors",
"nl": "Deze camera bevindt zich waarschijnlijk buiten",
"fr": "Cette caméra est probablement située à l'extérieur",
"it": "Questa videocamera si trova probabilmente all'esterno"
"it": "Questa videocamera si trova probabilmente all'esterno",
"ru": "Возможно, эта камера расположена снаружи"
},
"hideInAnswer": true
}
@ -374,7 +378,8 @@
"en": "How is this camera placed?",
"nl": "Hoe is deze camera geplaatst?",
"fr": "Comment cette caméra est-elle placée ?",
"it": "Com'è posizionata questa telecamera?"
"it": "Com'è posizionata questa telecamera?",
"ru": "Как расположена эта камера?"
},
"render": {
"en": "Mounting method: {mount}",

View file

@ -57,7 +57,8 @@
"de": "Eine öffentlich zugängliche Toilette",
"fr": "Des toilettes",
"nl": "Een publieke toilet",
"it": "Servizi igienici aperti al pubblico"
"it": "Servizi igienici aperti al pubblico",
"ru": "Туалет или комната отдыха со свободным доступом"
}
},
{
@ -66,7 +67,8 @@
"de": "Toiletten mit rollstuhlgerechter Toilette",
"fr": "Toilettes accessible aux personnes à mobilité réduite",
"nl": "Een rolstoeltoegankelijke toilet",
"it": "Servizi igienici accessibili per persone in sedia a rotelle"
"it": "Servizi igienici accessibili per persone in sedia a rotelle",
"ru": "Туалет с доступом для пользователей кресел-колясок"
},
"tags": [
"amenity=toilets",
@ -89,7 +91,8 @@
"de": "Sind diese Toiletten öffentlich zugänglich?",
"fr": "Ces toilettes sont-elles accessibles au public ?",
"nl": "Zijn deze toiletten publiek toegankelijk?",
"it": "Questi servizi igienici sono aperti al pubblico?"
"it": "Questi servizi igienici sono aperti al pubblico?",
"ru": "Есть ли свободный доступ к этим туалетам?"
},
"render": {
"en": "Access is {access}",
@ -112,7 +115,8 @@
"de": "Öffentlicher Zugang",
"fr": "Accès publique",
"nl": "Publiek toegankelijk",
"it": "Accesso pubblico"
"it": "Accesso pubblico",
"ru": "Свободный доступ"
}
},
{
@ -186,14 +190,16 @@
"de": "Wie viel muss man für diese Toiletten bezahlen?",
"fr": "Quel est le prix d'accès de ces toilettes ?",
"nl": "Hoeveel moet men betalen om deze toiletten te gebruiken?",
"it": "Quanto costa l'accesso a questi servizi igienici?"
"it": "Quanto costa l'accesso a questi servizi igienici?",
"ru": "Сколько стоит посещение туалета?"
},
"render": {
"en": "The fee is {charge}",
"de": "Die Gebühr beträgt {charge}",
"fr": "Le prix est {charge}",
"nl": "De toiletten gebruiken kost {charge}",
"it": "La tariffa è {charge}"
"it": "La tariffa è {charge}",
"ru": "Стоимость {charge}"
},
"condition": "fee=yes",
"freeform": {
@ -227,7 +233,8 @@
"de": "Kein Zugang für Rollstuhlfahrer",
"fr": "Non accessible aux personnes à mobilité réduite",
"nl": "Niet toegankelijk voor rolstoelgebruikers",
"it": "Non accessibile in sedia a rotelle"
"it": "Non accessibile in sedia a rotelle",
"ru": "Недоступно пользователям кресел-колясок"
}
}
]
@ -238,7 +245,8 @@
"de": "Welche Art von Toiletten sind das?",
"fr": "De quel type sont ces toilettes ?",
"nl": "Welke toiletten zijn dit?",
"it": "Di che tipo di servizi igienici si tratta?"
"it": "Di che tipo di servizi igienici si tratta?",
"ru": "Какие это туалеты?"
},
"mappings": [
{

View file

@ -230,7 +230,8 @@
"question": {
"nl": "Is deze boom groenblijvend of bladverliezend?",
"en": "Is this tree evergreen or deciduous?",
"it": "È un sempreverde o caduco?"
"it": "È un sempreverde o caduco?",
"ru": "Это дерево вечнозелёное или листопадное?"
},
"mappings": [
{
@ -242,7 +243,8 @@
"then": {
"nl": "Bladverliezend: de boom is een periode van het jaar kaal.",
"en": "Deciduous: the tree loses its leaves for some time of the year.",
"it": "Caduco: lalbero perde le sue foglie per un periodo dellanno."
"it": "Caduco: lalbero perde le sue foglie per un periodo dellanno.",
"ru": "Листопадное: у дерева опадают листья в определённое время года."
}
},
{
@ -255,7 +257,8 @@
"nl": "Groenblijvend.",
"en": "Evergreen.",
"it": "Sempreverde.",
"fr": "À feuilles persistantes."
"fr": "À feuilles persistantes.",
"ru": "Вечнозелёное."
}
}
],
@ -278,7 +281,8 @@
"nl": "Heeft de boom een naam?",
"en": "Does the tree have a name?",
"it": "Lalbero ha un nome?",
"fr": "L'arbre a-t-il un nom ?"
"fr": "L'arbre a-t-il un nom ?",
"ru": "Есть ли у этого дерева название?"
},
"freeform": {
"key": "name",
@ -298,7 +302,8 @@
"nl": "De boom heeft geen naam.",
"en": "The tree does not have a name.",
"it": "Lalbero non ha un nome.",
"fr": "L'arbre n'a pas de nom."
"fr": "L'arbre n'a pas de nom.",
"ru": "У этого дерева нет названия."
}
}
],
@ -399,7 +404,8 @@
"render": {
"nl": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed-ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>",
"en": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>",
"it": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>"
"it": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>",
"ru": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>"
},
"question": {
"nl": "Wat is het ID uitgegeven door Onroerend Erfgoed Vlaanderen?",
@ -421,7 +427,8 @@
"render": {
"nl": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>",
"en": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>",
"it": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>"
"it": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>",
"ru": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>"
},
"question": {
"nl": "Wat is het Wikidata-ID van deze boom?",
@ -484,7 +491,8 @@
"nl": "Loofboom",
"en": "Broadleaved tree",
"it": "Albero latifoglia",
"fr": "Arbre feuillu"
"fr": "Arbre feuillu",
"ru": "Лиственное дерево"
},
"description": {
"nl": "Een boom van een soort die blaadjes heeft, bijvoorbeeld eik of populier.",
@ -501,12 +509,14 @@
"title": {
"nl": "Naaldboom",
"en": "Needleleaved tree",
"it": "Albero aghifoglia"
"it": "Albero aghifoglia",
"ru": "Хвойное дерево"
},
"description": {
"nl": "Een boom van een soort met naalden, bijvoorbeeld den of spar.",
"en": "A tree of a species with needles, such as pine or spruce.",
"it": "Un albero di una specie con aghi come il pino o labete."
"it": "Un albero di una specie con aghi come il pino o labete.",
"ru": "Дерево с хвоей (иглами), например, сосна или ель."
}
},
{
@ -524,7 +534,8 @@
"nl": "Wanneer je niet zeker bent of het nu een loof- of naaldboom is.",
"en": "If you're not sure whether it's a broadleaved or needleleaved tree.",
"it": "Qualora non si sia sicuri se si tratta di un albero latifoglia o aghifoglia.",
"fr": "Si vous n'êtes pas sûr(e) de savoir s'il s'agit d'un arbre à feuilles larges ou à aiguilles."
"fr": "Si vous n'êtes pas sûr(e) de savoir s'il s'agit d'un arbre à feuilles larges ou à aiguilles.",
"ru": "Если вы не уверены в том, лиственное это дерево или хвойное."
}
}
]

View file

@ -6,7 +6,8 @@
"ru": "Зарядные станции",
"ja": "充電ステーション",
"zh_Hant": "充電站",
"it": "Stazioni di ricarica"
"it": "Stazioni di ricarica",
"nl": "Oplaadpunten"
},
"shortDescription": {
"en": "A worldwide map of charging stations",
@ -29,6 +30,7 @@
"ja",
"zh_Hant",
"it",
"nl",
"nb_NO"
],
"maintainer": "",
@ -48,7 +50,8 @@
"ja": "充電ステーション",
"zh_Hant": "充電站",
"nb_NO": "Ladestasjoner",
"it": "Stazioni di ricarica"
"it": "Stazioni di ricarica",
"nl": "Oplaadpunten"
},
"minzoom": 10,
"source": {
@ -65,7 +68,8 @@
"ja": "充電ステーション",
"zh_Hant": "充電站",
"nb_NO": "Ladestasjon",
"it": "Stazione di ricarica"
"it": "Stazione di ricarica",
"nl": "Oplaadpunt"
}
},
"description": {
@ -74,7 +78,8 @@
"ja": "充電ステーション",
"zh_Hant": "充電站",
"nb_NO": "En ladestasjon",
"it": "Una stazione di ricarica"
"it": "Una stazione di ricarica",
"nl": "Een oplaadpunt"
},
"tagRenderings": [
"images",

View file

@ -23,6 +23,7 @@
"ja",
"zh_Hant",
"ru",
"nl",
"ca",
"id"
],
@ -41,7 +42,8 @@
"en": "Shop",
"fr": "Magasin",
"ru": "Магазин",
"ja": "店"
"ja": "店",
"nl": "Winkel"
},
"minzoom": 16,
"source": {
@ -56,7 +58,8 @@
"en": "Shop",
"fr": "Magasin",
"ru": "Магазин",
"ja": "店"
"ja": "店",
"nl": "Winkel"
},
"mappings": [
{
@ -90,7 +93,8 @@
"description": {
"en": "A shop",
"fr": "Un magasin",
"ja": "ショップ"
"ja": "ショップ",
"nl": "Een winkel"
},
"tagRenderings": [
"images",
@ -99,7 +103,8 @@
"en": "What is the name of this shop?",
"fr": "Qu'est-ce que le nom de ce magasin?",
"ru": "Как называется магазин?",
"ja": "このお店の名前は何ですか?"
"ja": "このお店の名前は何ですか?",
"nl": "Wat is de naam van deze winkel?"
},
"render": "This shop is called <i>{name}</i>",
"freeform": {
@ -143,7 +148,8 @@
"en": "Supermarket",
"fr": "Supermarché",
"ru": "Супермаркет",
"ja": "スーパーマーケット"
"ja": "スーパーマーケット",
"nl": "Supermarkt"
}
},
{
@ -169,7 +175,8 @@
"en": "Hairdresser",
"fr": "Coiffeur",
"ru": "Парикмахерская",
"ja": "理容師"
"ja": "理容師",
"nl": "Kapper"
}
},
{
@ -181,7 +188,8 @@
"then": {
"en": "Bakery",
"fr": "Boulangerie",
"ja": "ベーカリー"
"ja": "ベーカリー",
"nl": "Bakkerij"
}
},
{
@ -223,7 +231,8 @@
"question": {
"en": "What is the phone number?",
"fr": "Quel est le numéro de téléphone ?",
"ja": "電話番号は何番ですか?"
"ja": "電話番号は何番ですか?",
"nl": "Wat is het telefoonnummer?"
},
"freeform": {
"key": "phone",
@ -242,7 +251,8 @@
"question": {
"en": "What is the website of this shop?",
"fr": "Quel est le site internet de ce magasin ?",
"ja": "このお店のホームページは何ですか?"
"ja": "このお店のホームページは何ですか?",
"nl": "Wat is de website van deze winkel?"
},
"freeform": {
"key": "website",
@ -277,7 +287,8 @@
"question": {
"en": "What are the opening hours of this shop?",
"fr": "Quels sont les horaires d'ouverture de ce magasin ?",
"ja": "この店の営業時間は何時から何時までですか?"
"ja": "この店の営業時間は何時から何時までですか?",
"nl": "Wat zijn de openingsuren van deze winkel?"
},
"freeform": {
"key": "opening_hours",
@ -316,13 +327,15 @@
"en": "Shop",
"fr": "Magasin",
"ru": "Магазин",
"ja": "店"
"ja": "店",
"nl": "Winkel"
},
"description": {
"en": "Add a new shop",
"fr": "Ajouter un nouveau magasin",
"ru": "Добавить новый магазин",
"ja": "新しい店を追加する"
"ja": "新しい店を追加する",
"nl": "Voeg een nieuwe winkel toe"
}
}
],

View file

@ -603,8 +603,11 @@
"title": {
"render": "Стол для пикника"
},
"description": "Слой, отображающий столы для пикника",
"tagRenderings": {
"0": {
"question": "Из чего изготовлен этот стол для пикника?",
"render": "Этот стол для пикника сделан из {material}",
"mappings": {
"0": {
"then": "Это деревянный стол для пикника"
@ -612,17 +615,14 @@
"1": {
"then": "Это бетонный стол для пикника"
}
},
"render": "Этот стол для пикника сделан из {material}",
"question": "Из чего изготовлен этот стол для пикника?"
}
}
},
"presets": {
"0": {
"title": "Стол для пикника"
}
},
"description": "Слой, отображающий столы для пикника"
}
},
"playground": {
"name": "Детские площадки",
@ -645,6 +645,9 @@
"1": {
"then": "Поверхность - <b>песок</b>"
},
"2": {
"then": "Покрытие из <b>щепы</b>"
},
"3": {
"then": "Поверхность - <b>брусчатка</b>"
},
@ -653,9 +656,17 @@
},
"5": {
"then": "Поверхность - <b>бетон</b>"
}
}
},
"2": {
"question": "Эта игровая площадка освещается ночью?",
"mappings": {
"0": {
"then": "Эта детская площадка освещается ночью"
},
"2": {
"then": "Покрытие из <b>щепы</b>"
"1": {
"then": "Эта детская площадка не освещается ночью"
}
}
},
@ -663,6 +674,9 @@
"render": "Доступно для детей старше {min_age} лет",
"question": "С какого возраста доступна эта детская площадка?"
},
"4": {
"render": "Доступно детям до {max_age}"
},
"6": {
"mappings": {
"4": {
@ -676,47 +690,33 @@
"8": {
"render": "<a href='tel:{phone}'>{phone}</a>"
},
"10": {
"mappings": {
"1": {
"then": "Всегда доступен"
},
"2": {
"then": "Всегда доступен"
},
"0": {
"then": "Открыто от рассвета до заката"
}
},
"question": "Когда открыта эта игровая площадка?"
},
"9": {
"question": "Доступна ли детская площадка пользователям кресел-колясок?",
"mappings": {
"2": {
"then": "Недоступна пользователям кресел-колясок"
"0": {
"then": "Полностью доступна пользователям кресел-колясок"
},
"1": {
"then": "Частично доступна пользователям кресел-колясок"
},
"0": {
"then": "Полностью доступна пользователям кресел-колясок"
"2": {
"then": "Недоступна пользователям кресел-колясок"
}
},
"question": "Доступна ли детская площадка пользователям кресел-колясок?"
}
},
"4": {
"render": "Доступно детям до {max_age}"
},
"2": {
"10": {
"question": "Когда открыта эта игровая площадка?",
"mappings": {
"1": {
"then": "Эта детская площадка не освещается ночью"
},
"0": {
"then": "Эта детская площадка освещается ночью"
"then": "Открыто от рассвета до заката"
},
"1": {
"then": "Всегда доступен"
},
"2": {
"then": "Всегда доступен"
}
},
"question": "Эта игровая площадка освещается ночью?"
}
}
},
"presets": {
@ -727,6 +727,7 @@
},
"public_bookcase": {
"name": "Книжные шкафы",
"description": "Уличный шкаф с книгами, доступными для всех",
"title": {
"render": "Книжный шкаф",
"mappings": {
@ -751,10 +752,11 @@
}
},
"3": {
"question": "Сколько книг помещается в этом общественном книжном шкафу?",
"render": "{capacity} книг помещается в этот книжный шкаф"
"render": "{capacity} книг помещается в этот книжный шкаф",
"question": "Сколько книг помещается в этом общественном книжном шкафу?"
},
"4": {
"question": "Какие книги можно найти в этом общественном книжном шкафу?",
"mappings": {
"0": {
"then": "В основном детские книги"
@ -765,27 +767,25 @@
"2": {
"then": "Книги и для детей, и для взрослых"
}
},
"question": "Какие книги можно найти в этом общественном книжном шкафу?"
},
"11": {
"render": "Более подробная информация <a href='{website}' target='_blank'>на сайте</a>",
"question": "Есть ли веб-сайт с более подробной информацией об этом общественном книжном шкафе?"
},
"10": {
"render": "Установлен {start_date}",
"question": "Когда был установлен этот общественный книжный шкаф?"
}
},
"6": {
"question": "Имеется ли свободный доступ к этому общественному книжному шкафу?",
"mappings": {
"0": {
"then": "Свободный доступ"
}
},
"question": "Имеется ли свободный доступ к этому общественному книжному шкафу?"
}
},
"10": {
"question": "Когда был установлен этот общественный книжный шкаф?",
"render": "Установлен {start_date}"
},
"11": {
"render": "Более подробная информация <a href='{website}' target='_blank'>на сайте</a>",
"question": "Есть ли веб-сайт с более подробной информацией об этом общественном книжном шкафе?"
}
},
"description": "Уличный шкаф с книгами, доступными для всех"
}
},
"slow_roads": {
"tagRenderings": {
@ -819,30 +819,32 @@
"title": {
"render": "Спортивная площадка"
},
"description": "Спортивная площадка",
"tagRenderings": {
"1": {
"mappings": {
"2": {
"then": "Это стол для пинг-понга"
},
"5": {
"0": {
"then": "Здесь можно играть в баскетбол"
},
"4": {
"then": "Здесь можно играть в корфбол"
},
"3": {
"then": "Здесь можно играть в теннис"
},
"1": {
"then": "Здесь можно играть в футбол"
},
"0": {
"2": {
"then": "Это стол для пинг-понга"
},
"3": {
"then": "Здесь можно играть в теннис"
},
"4": {
"then": "Здесь можно играть в корфбол"
},
"5": {
"then": "Здесь можно играть в баскетбол"
}
}
},
"2": {
"question": "Какое покрытие на этой спортивной площадке?",
"render": "Поверхность - <b>{surface}</b>",
"mappings": {
"0": {
@ -860,55 +862,53 @@
"4": {
"then": "Поверхность - <b>бетон</b>"
}
},
"question": "Какое покрытие на этой спортивной площадке?"
},
"7": {
"mappings": {
"1": {
"then": "Всегда доступен"
}
},
"question": "В какое время доступна эта площадка?"
},
"4": {
"mappings": {
"1": {
"then": "Желательна предварительная запись для доступа на эту спортивную площадку"
},
"3": {
"then": "Невозможна предварительная запись"
},
"2": {
"then": "Предварительная запись для доступа на эту спортивную площадку возможна, но не обязательна"
}
},
"question": "Нужна ли предварительная запись для доступа на эту спортивную площадку?"
}
},
"3": {
"question": "Есть ли свободный доступ к этой спортивной площадке?",
"mappings": {
"2": {
"then": "Доступ только членам клуба"
"0": {
"then": "Свободный доступ"
},
"1": {
"then": "Ограниченный доступ (напр., только по записи, в определённые часы, ...)"
},
"0": {
"then": "Свободный доступ"
"2": {
"then": "Доступ только членам клуба"
}
},
"question": "Есть ли свободный доступ к этой спортивной площадке?"
}
},
"4": {
"question": "Нужна ли предварительная запись для доступа на эту спортивную площадку?",
"mappings": {
"1": {
"then": "Желательна предварительная запись для доступа на эту спортивную площадку"
},
"2": {
"then": "Предварительная запись для доступа на эту спортивную площадку возможна, но не обязательна"
},
"3": {
"then": "Невозможна предварительная запись"
}
}
},
"7": {
"question": "В какое время доступна эта площадка?",
"mappings": {
"1": {
"then": "Всегда доступен"
}
}
}
},
"presets": {
"1": {
"title": "Спортивная площадка"
},
"0": {
"title": "Стол для настольного тенниса"
},
"1": {
"title": "Спортивная площадка"
}
},
"description": "Спортивная площадка"
}
},
"surveillance_camera": {
"name": "Камеры наблюдения",
@ -917,28 +917,28 @@
},
"tagRenderings": {
"1": {
"question": "Какая это камера?",
"mappings": {
"2": {
"then": "Панорамная камера"
},
"1": {
"then": "Камера с поворотным механизмом"
},
"2": {
"then": "Панорамная камера"
}
},
"question": "Какая это камера?"
},
"8": {
"question": "Как расположена эта камера?"
}
},
"5": {
"mappings": {
"2": {
"then": "Возможно, эта камера расположена снаружи"
},
"1": {
"then": "Эта камера расположена снаружи"
},
"2": {
"then": "Возможно, эта камера расположена снаружи"
}
}
},
"8": {
"question": "Как расположена эта камера?"
}
}
},
@ -958,15 +958,15 @@
},
"tagRenderings": {
"1": {
"question": "Есть ли свободный доступ к этим туалетам?",
"mappings": {
"2": {
"then": "Недоступно"
},
"0": {
"then": "Свободный доступ"
},
"2": {
"then": "Недоступно"
}
},
"question": "Есть ли свободный доступ к этим туалетам?"
}
},
"2": {
"mappings": {
@ -975,8 +975,9 @@
}
}
},
"5": {
"question": "Какие это туалеты?"
"3": {
"question": "Сколько стоит посещение туалета?",
"render": "Стоимость {charge}"
},
"4": {
"mappings": {
@ -985,9 +986,8 @@
}
}
},
"3": {
"render": "Стоимость {charge}",
"question": "Сколько стоит посещение туалета?"
"5": {
"question": "Какие это туалеты?"
}
}
},
@ -1010,44 +1010,44 @@
}
}
},
"4": {
"question": "Это дерево вечнозелёное или листопадное?",
"mappings": {
"0": {
"then": "Листопадное: у дерева опадают листья в определённое время года."
},
"1": {
"then": "Вечнозелёное."
}
}
},
"5": {
"render": "Название: {name}",
"question": "Есть ли у этого дерева название?",
"mappings": {
"0": {
"then": "У этого дерева нет названия."
}
},
"question": "Есть ли у этого дерева название?"
},
"8": {
"render": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>"
}
},
"7": {
"render": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Onroerend Erfgoed ID: <a href=\"https://id.erfgoed.net/erfgoedobjecten/{ref:OnroerendErfgoed}\">{ref:OnroerendErfgoed}</a>"
},
"4": {
"mappings": {
"1": {
"then": "Вечнозелёное."
},
"0": {
"then": "Листопадное: у дерева опадают листья в определённое время года."
}
},
"question": "Это дерево вечнозелёное или листопадное?"
"8": {
"render": "<img src=\"./assets/svg/wikidata.svg\" style=\"width:1em;height:0.56em;vertical-align:middle\" alt=\"\"/> Wikidata: <a href=\"http://www.wikidata.org/entity/{wikidata}\">{wikidata}</a>"
}
},
"presets": {
"0": {
"title": "Лиственное дерево"
},
"1": {
"title": "Хвойное дерево",
"description": "Дерево с хвоей (иглами), например, сосна или ель."
},
"2": {
"title": "Дерево",
"description": "Если вы не уверены в том, лиственное это дерево или хвойное."
},
"1": {
"description": "Дерево с хвоей (иглами), например, сосна или ель.",
"title": "Хвойное дерево"
},
"0": {
"title": "Лиственное дерево"
}
}
},

View file

@ -278,6 +278,18 @@
}
}
},
"charging_stations": {
"title": "Oplaadpunten",
"layers": {
"0": {
"name": "Oplaadpunten",
"title": {
"render": "Oplaadpunt"
},
"description": "Een oplaadpunt"
}
}
},
"climbing": {
"title": "Open Klimkaart",
"description": "Op deze kaart vind je verschillende klimgelegenheden, zoals klimzalen, bolderzalen en klimmen in de natuur",
@ -924,6 +936,50 @@
"shortDescription": "Een kaart met speeltuinen",
"description": "Op deze kaart vind je speeltuinen en kan je zelf meer informatie en foto's toevoegen"
},
"shops": {
"layers": {
"0": {
"name": "Winkel",
"title": {
"render": "Winkel"
},
"description": "Een winkel",
"tagRenderings": {
"1": {
"question": "Wat is de naam van deze winkel?"
},
"2": {
"mappings": {
"1": {
"then": "Supermarkt"
},
"3": {
"then": "Kapper"
},
"4": {
"then": "Bakkerij"
}
}
},
"3": {
"question": "Wat is het telefoonnummer?"
},
"4": {
"question": "Wat is de website van deze winkel?"
},
"6": {
"question": "Wat zijn de openingsuren van deze winkel?"
}
},
"presets": {
"0": {
"title": "Winkel",
"description": "Voeg een nieuwe winkel toe"
}
}
}
}
},
"speelplekken": {
"title": "Welkom bij de groendoener!",
"shortDescription": "Speelplekken in de Antwerpse Zuidrand",
@ -1042,61 +1098,5 @@
}
}
}
},
"charging_stations": {
"layers": {
"0": {
"description": "Een oplaadpunt",
"title": {
"render": "Oplaadpunt"
},
"name": "Oplaadpunten"
}
},
"title": "Oplaadpunten"
},
"shops": {
"layers": {
"0": {
"tagRenderings": {
"4": {
"question": "Wat is de website van deze winkel?"
},
"3": {
"question": "Wat is het telefoonnummer?"
},
"2": {
"mappings": {
"4": {
"then": "Bakkerij"
},
"3": {
"then": "Kapper"
},
"1": {
"then": "Supermarkt"
}
}
},
"1": {
"question": "Wat is de naam van deze winkel?"
},
"6": {
"question": "Wat zijn de openingsuren van deze winkel?"
}
},
"description": "Een winkel",
"title": {
"render": "Winkel"
},
"name": "Winkel",
"presets": {
"0": {
"title": "Winkel",
"description": "Voeg een nieuwe winkel toe"
}
}
}
}
}
}