forked from MapComplete/MapComplete
		
	Merge pull request #424 from pietervdvn/develop-extra-feature
Location following feature
This commit is contained in:
		
						commit
						7a06ec1bd5
					
				
					 12 changed files with 592 additions and 491 deletions
				
			
		|  | @ -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"); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -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 è l’età 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": "Открыто от рассвета до заката" | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|  |  | |||
|  | @ -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", | ||||
|  |  | |||
|  | @ -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", | ||||
|  |  | |||
|  | @ -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}", | ||||
|  |  | |||
|  | @ -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": [ | ||||
|         { | ||||
|  |  | |||
|  | @ -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: l’albero perde le sue foglie per un periodo dell’anno." | ||||
|             "it": "Caduco: l’albero perde le sue foglie per un periodo dell’anno.", | ||||
|             "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": "L’albero 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": "L’albero 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 l’abete." | ||||
|         "it": "Un albero di una specie con aghi come il pino o l’abete.", | ||||
|         "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": "Если вы не уверены в том, лиственное это дерево или хвойное." | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
|  |  | |||
|  | @ -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", | ||||
|  |  | |||
|  | @ -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" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|  |  | |||
|  | @ -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": "Лиственное дерево" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  |  | |||
|  | @ -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" | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue