forked from MapComplete/MapComplete
Merge branch 'develop' into theme/street_lighting
This commit is contained in:
commit
521a08a1a1
159 changed files with 7683 additions and 6530 deletions
2
Docs/Misc/gen.sh
Executable file
2
Docs/Misc/gen.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
|
||||
dot -Tps geolocation_button.gv -Tsvg -O
|
22
Docs/Misc/geolocation_button.gv
Normal file
22
Docs/Misc/geolocation_button.gv
Normal file
|
@ -0,0 +1,22 @@
|
|||
digraph G {
|
||||
init [shape=box]
|
||||
denied
|
||||
init -> denied [label="geolocation permanently denied"]
|
||||
init -> getting_location [label="previously granted flag set"]
|
||||
init -> idle [label="previously granted flag unset"]
|
||||
idle
|
||||
idle -> request_permission [label="on click"]
|
||||
request_permission
|
||||
request_permission -> getting_location [label="granted (sets flag)"]
|
||||
request_permission -> idle [label="not granted"]
|
||||
request_permission -> denied [label="permanently denied"]
|
||||
getting_location
|
||||
location_found
|
||||
getting_location -> location_found [label="location found"]
|
||||
location_found -> open_lock [label="on click (zooms to location)"]
|
||||
open_lock
|
||||
open_lock -> location_found [label="after 3 sec"]
|
||||
closed_lock
|
||||
open_lock -> closed_lock [label="on click (locks zoom to location)"]
|
||||
closed_lock -> location_found [label="on click"]
|
||||
}
|
145
Docs/Misc/geolocation_button.gv.svg
Normal file
145
Docs/Misc/geolocation_button.gv.svg
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="664pt" height="566pt"
|
||||
viewBox="0.00 0.00 664.25 566.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 562)">
|
||||
<title>G</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-562 660.25,-562 660.25,4 -4,4"/>
|
||||
<!-- init -->
|
||||
<g id="node1" class="node">
|
||||
<title>init</title>
|
||||
<polygon fill="none" stroke="black" points="242.25,-558 188.25,-558 188.25,-522 242.25,-522 242.25,-558"/>
|
||||
<text text-anchor="middle" x="215.25" y="-536.3" font-family="Times,serif" font-size="14.00">init</text>
|
||||
</g>
|
||||
<!-- denied -->
|
||||
<g id="node2" class="node">
|
||||
<title>denied</title>
|
||||
<ellipse fill="none" stroke="black" cx="42.25" cy="-279" rx="42.49" ry="18"/>
|
||||
<text text-anchor="middle" x="42.25" y="-275.3" font-family="Times,serif" font-size="14.00">denied</text>
|
||||
</g>
|
||||
<!-- init->denied -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>init->denied</title>
|
||||
<path fill="none" stroke="black" d="M188.23,-531.67C143.21,-517.82 54.16,-483.1 17.25,-417 -2.35,-381.91 14.04,-334.64 27.95,-305.79"/>
|
||||
<polygon fill="black" stroke="black" points="31.12,-307.26 32.51,-296.76 24.88,-304.1 31.12,-307.26"/>
|
||||
<text text-anchor="middle" x="132.25" y="-405.8" font-family="Times,serif" font-size="14.00">geolocation permanently denied</text>
|
||||
</g>
|
||||
<!-- getting_location -->
|
||||
<g id="node3" class="node">
|
||||
<title>getting_location</title>
|
||||
<ellipse fill="none" stroke="black" cx="366.25" cy="-279" rx="85.29" ry="18"/>
|
||||
<text text-anchor="middle" x="366.25" y="-275.3" font-family="Times,serif" font-size="14.00">getting_location</text>
|
||||
</g>
|
||||
<!-- init->getting_location -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>init->getting_location</title>
|
||||
<path fill="none" stroke="black" d="M242.41,-538.69C294.16,-537.46 403.84,-531.59 427.25,-504 481.59,-439.95 469.34,-387.69 427.25,-315 424.07,-309.52 419.68,-304.83 414.7,-300.82"/>
|
||||
<polygon fill="black" stroke="black" points="416.68,-297.93 406.47,-295.09 412.67,-303.68 416.68,-297.93"/>
|
||||
<text text-anchor="middle" x="559.75" y="-405.8" font-family="Times,serif" font-size="14.00">previously granted flag set</text>
|
||||
</g>
|
||||
<!-- idle -->
|
||||
<g id="node4" class="node">
|
||||
<title>idle</title>
|
||||
<ellipse fill="none" stroke="black" cx="255.25" cy="-453" rx="27.9" ry="18"/>
|
||||
<text text-anchor="middle" x="255.25" y="-449.3" font-family="Times,serif" font-size="14.00">idle</text>
|
||||
</g>
|
||||
<!-- init->idle -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>init->idle</title>
|
||||
<path fill="none" stroke="black" d="M212.27,-521.58C211.37,-511.6 211.62,-499.1 216.25,-489 218.98,-483.03 223.28,-477.64 228.03,-472.99"/>
|
||||
<polygon fill="black" stroke="black" points="230.48,-475.49 235.73,-466.29 225.89,-470.21 230.48,-475.49"/>
|
||||
<text text-anchor="middle" x="321.75" y="-492.8" font-family="Times,serif" font-size="14.00">previously granted flag unset</text>
|
||||
</g>
|
||||
<!-- location_found -->
|
||||
<g id="node6" class="node">
|
||||
<title>location_found</title>
|
||||
<ellipse fill="none" stroke="black" cx="366.25" cy="-192" rx="77.99" ry="18"/>
|
||||
<text text-anchor="middle" x="366.25" y="-188.3" font-family="Times,serif" font-size="14.00">location_found</text>
|
||||
</g>
|
||||
<!-- getting_location->location_found -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>getting_location->location_found</title>
|
||||
<path fill="none" stroke="black" d="M366.25,-260.8C366.25,-249.16 366.25,-233.55 366.25,-220.24"/>
|
||||
<polygon fill="black" stroke="black" points="369.75,-220.18 366.25,-210.18 362.75,-220.18 369.75,-220.18"/>
|
||||
<text text-anchor="middle" x="417.25" y="-231.8" font-family="Times,serif" font-size="14.00">location found</text>
|
||||
</g>
|
||||
<!-- request_permission -->
|
||||
<g id="node5" class="node">
|
||||
<title>request_permission</title>
|
||||
<ellipse fill="none" stroke="black" cx="264.25" cy="-366" rx="102.08" ry="18"/>
|
||||
<text text-anchor="middle" x="264.25" y="-362.3" font-family="Times,serif" font-size="14.00">request_permission</text>
|
||||
</g>
|
||||
<!-- idle->request_permission -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>idle->request_permission</title>
|
||||
<path fill="none" stroke="black" d="M282.79,-448.82C302.7,-444.93 328.29,-436.26 341.25,-417 349.95,-404.06 340.76,-393.72 326.08,-385.86"/>
|
||||
<polygon fill="black" stroke="black" points="327.44,-382.63 316.9,-381.53 324.45,-388.96 327.44,-382.63"/>
|
||||
<text text-anchor="middle" x="371.75" y="-405.8" font-family="Times,serif" font-size="14.00">on click</text>
|
||||
</g>
|
||||
<!-- request_permission->denied -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>request_permission->denied</title>
|
||||
<path fill="none" stroke="black" d="M202.76,-351.6C180.78,-345.99 156.06,-338.72 134.25,-330 113.26,-321.61 90.96,-309.57 73.57,-299.42"/>
|
||||
<polygon fill="black" stroke="black" points="75.34,-296.4 64.96,-294.3 71.77,-302.42 75.34,-296.4"/>
|
||||
<text text-anchor="middle" x="206.25" y="-318.8" font-family="Times,serif" font-size="14.00">permanently denied</text>
|
||||
</g>
|
||||
<!-- request_permission->getting_location -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>request_permission->getting_location</title>
|
||||
<path fill="none" stroke="black" d="M271.38,-348C276.49,-337.43 284.24,-324.16 294.25,-315 300.73,-309.07 308.39,-303.93 316.27,-299.56"/>
|
||||
<polygon fill="black" stroke="black" points="317.92,-302.64 325.2,-294.94 314.71,-296.43 317.92,-302.64"/>
|
||||
<text text-anchor="middle" x="360.75" y="-318.8" font-family="Times,serif" font-size="14.00">granted (sets flag)</text>
|
||||
</g>
|
||||
<!-- request_permission->idle -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>request_permission->idle</title>
|
||||
<path fill="none" stroke="black" d="M257.1,-384.15C255.12,-389.74 253.24,-396.04 252.25,-402 251.02,-409.35 250.95,-417.37 251.4,-424.8"/>
|
||||
<polygon fill="black" stroke="black" points="247.92,-425.14 252.32,-434.78 254.89,-424.5 247.92,-425.14"/>
|
||||
<text text-anchor="middle" x="294.75" y="-405.8" font-family="Times,serif" font-size="14.00">not granted</text>
|
||||
</g>
|
||||
<!-- open_lock -->
|
||||
<g id="node7" class="node">
|
||||
<title>open_lock</title>
|
||||
<ellipse fill="none" stroke="black" cx="333.25" cy="-105" rx="55.79" ry="18"/>
|
||||
<text text-anchor="middle" x="333.25" y="-101.3" font-family="Times,serif" font-size="14.00">open_lock</text>
|
||||
</g>
|
||||
<!-- location_found->open_lock -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>location_found->open_lock</title>
|
||||
<path fill="none" stroke="black" d="M359.57,-173.8C354.98,-161.97 348.79,-146.03 343.56,-132.58"/>
|
||||
<polygon fill="black" stroke="black" points="346.68,-130.94 339.8,-122.89 340.16,-133.47 346.68,-130.94"/>
|
||||
<text text-anchor="middle" x="448.25" y="-144.8" font-family="Times,serif" font-size="14.00">on click (zooms to location)</text>
|
||||
</g>
|
||||
<!-- open_lock->location_found -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>open_lock->location_found</title>
|
||||
<path fill="none" stroke="black" d="M295.44,-118.33C275.01,-127.12 256.04,-140.15 267.25,-156 273.92,-165.44 283.37,-172.35 293.8,-177.41"/>
|
||||
<polygon fill="black" stroke="black" points="292.6,-180.7 303.17,-181.39 295.34,-174.26 292.6,-180.7"/>
|
||||
<text text-anchor="middle" x="305.25" y="-144.8" font-family="Times,serif" font-size="14.00">after 3 sec</text>
|
||||
</g>
|
||||
<!-- closed_lock -->
|
||||
<g id="node8" class="node">
|
||||
<title>closed_lock</title>
|
||||
<ellipse fill="none" stroke="black" cx="454.25" cy="-18" rx="63.09" ry="18"/>
|
||||
<text text-anchor="middle" x="454.25" y="-14.3" font-family="Times,serif" font-size="14.00">closed_lock</text>
|
||||
</g>
|
||||
<!-- open_lock->closed_lock -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>open_lock->closed_lock</title>
|
||||
<path fill="none" stroke="black" d="M328.89,-87.05C327.23,-76.5 327.17,-63.24 334.25,-54 346.04,-38.59 364.24,-29.68 382.92,-24.6"/>
|
||||
<polygon fill="black" stroke="black" points="383.78,-28 392.71,-22.28 382.17,-21.18 383.78,-28"/>
|
||||
<text text-anchor="middle" x="447.75" y="-57.8" font-family="Times,serif" font-size="14.00">on click (locks zoom to location)</text>
|
||||
</g>
|
||||
<!-- closed_lock->location_found -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>closed_lock->location_found</title>
|
||||
<path fill="none" stroke="black" d="M513.08,-24.74C531.5,-29.64 549.95,-38.41 561.25,-54 588.04,-90.95 580.67,-122.9 549.25,-156 535.31,-170.68 491.24,-179.37 449.85,-184.42"/>
|
||||
<polygon fill="black" stroke="black" points="449.22,-180.97 439.68,-185.6 450.02,-187.93 449.22,-180.97"/>
|
||||
<text text-anchor="middle" x="604.75" y="-101.3" font-family="Times,serif" font-size="14.00">on click</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.4 KiB |
|
@ -23,11 +23,11 @@ export default class AvailableBaseLayers {
|
|||
private static implementation: AvailableBaseLayersObj
|
||||
|
||||
static AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
|
||||
return AvailableBaseLayers.implementation.AvailableLayersAt(location);
|
||||
return AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? new UIEventSource<BaseLayer[]>([]);
|
||||
}
|
||||
|
||||
static SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
|
||||
return AvailableBaseLayers.implementation.SelectBestLayerAccordingTo(location, preferedCategory);
|
||||
return AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo(location, preferedCategory) ?? new UIEventSource<BaseLayer>(undefined);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
|
|||
// Note: if layer.geometry is null, there is global coverage for this layer
|
||||
layers.push({
|
||||
id: props.id,
|
||||
max_zoom: props.max_zoom ?? 25,
|
||||
max_zoom: props.max_zoom ?? 19,
|
||||
min_zoom: props.min_zoom ?? 1,
|
||||
name: props.name,
|
||||
layer: leafletLayer,
|
||||
|
|
|
@ -2,6 +2,7 @@ import {UIEventSource} from "../UIEventSource";
|
|||
import BaseLayer from "../../Models/BaseLayer";
|
||||
import AvailableBaseLayers from "./AvailableBaseLayers";
|
||||
import Loc from "../../Models/Loc";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
/**
|
||||
* Sets the current background layer to a layer that is actually available
|
||||
|
@ -12,6 +13,11 @@ export default class BackgroundLayerResetter {
|
|||
location: UIEventSource<Loc>,
|
||||
availableLayers: UIEventSource<BaseLayer[]>,
|
||||
defaultLayerId: string = undefined) {
|
||||
|
||||
if(Utils.runningFromConsole){
|
||||
return
|
||||
}
|
||||
|
||||
defaultLayerId = defaultLayerId ?? AvailableBaseLayers.osmCarto.id;
|
||||
|
||||
// Change the baselayer back to OSM if we go out of the current range of the layer
|
||||
|
|
|
@ -29,7 +29,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
|
||||
|
||||
private readonly retries: UIEventSource<number> = new UIEventSource<number>(0);
|
||||
|
||||
|
||||
private readonly state: {
|
||||
readonly locationControl: UIEventSource<Loc>,
|
||||
readonly layoutToUse: LayoutConfig,
|
||||
|
@ -39,6 +39,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
private readonly _isActive: UIEventSource<boolean>;
|
||||
private readonly onBboxLoaded: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void;
|
||||
|
||||
constructor(
|
||||
state: {
|
||||
readonly locationControl: UIEventSource<Loc>,
|
||||
|
@ -90,7 +91,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
const self = this;
|
||||
this.updateAsync(paddedZoomLevel).then(bboxDate => {
|
||||
if(bboxDate === undefined || self.onBboxLoaded === undefined){
|
||||
if (bboxDate === undefined || self.onBboxLoaded === undefined) {
|
||||
return;
|
||||
}
|
||||
const [bbox, date, layers] = bboxDate
|
||||
|
@ -109,41 +110,43 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.widenFactor)?.expandToTileBounds(padToZoomLevel);
|
||||
|
||||
if (bounds === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const self = this;
|
||||
|
||||
|
||||
const layersToDownload = []
|
||||
for (const layer of this.state.layoutToUse.layers) {
|
||||
|
||||
if (typeof (layer) === "string") {
|
||||
throw "A layer was not expanded!"
|
||||
}
|
||||
if(this.state.locationControl.data.zoom < layer.minzoom){
|
||||
continue;
|
||||
}
|
||||
if (layer.doNotDownload) {
|
||||
continue;
|
||||
}
|
||||
if (layer.source.geojsonSource !== undefined) {
|
||||
// Not our responsibility to download this layer!
|
||||
continue;
|
||||
}
|
||||
layersToDownload.push(layer)
|
||||
}
|
||||
|
||||
let data: any = undefined
|
||||
let date: Date = undefined
|
||||
const overpassUrls = self.state.overpassUrl.data
|
||||
let lastUsed = 0;
|
||||
|
||||
|
||||
|
||||
const layersToDownload = []
|
||||
for (const layer of this.state.layoutToUse.layers) {
|
||||
|
||||
if (typeof (layer) === "string") {
|
||||
throw "A layer was not expanded!"
|
||||
}
|
||||
if (this.state.locationControl.data.zoom < layer.minzoom) {
|
||||
continue;
|
||||
}
|
||||
if (layer.doNotDownload) {
|
||||
continue;
|
||||
}
|
||||
if (layer.source.geojsonSource !== undefined) {
|
||||
// Not our responsibility to download this layer!
|
||||
continue;
|
||||
}
|
||||
layersToDownload.push(layer)
|
||||
}
|
||||
|
||||
const self = this;
|
||||
const overpassUrls = self.state.overpassUrl.data
|
||||
let bounds : BBox
|
||||
do {
|
||||
try {
|
||||
|
||||
|
||||
bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.widenFactor)?.expandToTileBounds(padToZoomLevel);
|
||||
|
||||
if (bounds === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const overpass = this.GetFilter(overpassUrls[lastUsed], layersToDownload);
|
||||
|
||||
if (overpass === undefined) {
|
||||
|
@ -175,16 +178,21 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
} while (data === undefined);
|
||||
} while (data === undefined && this._isActive.data);
|
||||
|
||||
self.retries.setData(0);
|
||||
|
||||
try {
|
||||
if(data === undefined){
|
||||
return undefined
|
||||
}
|
||||
data.features.forEach(feature => SimpleMetaTagger.objectMetaInfo.applyMetaTagsOnFeature(feature, date, undefined));
|
||||
self.features.setData(data.features.map(f => ({feature: f, freshness: date})));
|
||||
return [bounds, date, layersToDownload];
|
||||
} catch (e) {
|
||||
console.error("Got the overpass response, but could not process it: ", e, e.stack)
|
||||
return undefined
|
||||
} finally {
|
||||
self.retries.setData(0);
|
||||
self.runningQuery.setData(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Changes} from "../Osm/Changes";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class PendingChangesUploader {
|
||||
|
||||
|
@ -30,6 +31,10 @@ export default class PendingChangesUploader {
|
|||
}
|
||||
});
|
||||
|
||||
if(Utils.runningFromConsole){
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener('mouseout', e => {
|
||||
// @ts-ignore
|
||||
if (!e.toElement && !e.relatedTarget) {
|
||||
|
|
|
@ -9,6 +9,13 @@ import {OsmConnection} from "../Osm/OsmConnection";
|
|||
|
||||
export default class SelectedElementTagsUpdater {
|
||||
|
||||
private static readonly metatags = new Set(["timestamp",
|
||||
"version",
|
||||
"changeset",
|
||||
"user",
|
||||
"uid",
|
||||
"id"] )
|
||||
|
||||
constructor(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
|
@ -18,15 +25,15 @@ export default class SelectedElementTagsUpdater {
|
|||
|
||||
|
||||
state.osmConnection.isLoggedIn.addCallbackAndRun(isLoggedIn => {
|
||||
if(isLoggedIn){
|
||||
if (isLoggedIn) {
|
||||
SelectedElementTagsUpdater.installCallback(state)
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private static installCallback(state: {
|
||||
|
||||
public static installCallback(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
|
@ -36,80 +43,99 @@ export default class SelectedElementTagsUpdater {
|
|||
|
||||
state.selectedElement.addCallbackAndRunD(s => {
|
||||
let id = s.properties?.id
|
||||
|
||||
|
||||
const backendUrl = state.osmConnection._oauth_config.url
|
||||
if(id.startsWith(backendUrl)){
|
||||
if (id.startsWith(backendUrl)) {
|
||||
id = id.substring(backendUrl.length)
|
||||
}
|
||||
|
||||
if(!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))){
|
||||
|
||||
if (!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))) {
|
||||
// This object is _not_ from OSM, so we skip it!
|
||||
return;
|
||||
}
|
||||
|
||||
if(id.indexOf("-") >= 0){
|
||||
|
||||
if (id.indexOf("-") >= 0) {
|
||||
// This is a new object
|
||||
return;
|
||||
}
|
||||
|
||||
OsmObject.DownloadPropertiesOf(id).then(tags => {
|
||||
SelectedElementTagsUpdater.applyUpdate(state, tags, id)
|
||||
}).catch(e => {
|
||||
console.error("Could not update tags of ", id, "due to", e)
|
||||
OsmObject.DownloadPropertiesOf(id).then(latestTags => {
|
||||
SelectedElementTagsUpdater.applyUpdate(state, latestTags, id)
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static applyUpdate(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
osmConnection: OsmConnection
|
||||
}, latestTags: any, id: string
|
||||
public static applyUpdate(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
osmConnection: OsmConnection
|
||||
}, latestTags: any, id: string
|
||||
) {
|
||||
const pendingChanges = state.changes.pendingChanges.data
|
||||
.filter(change => change.type +"/"+ change.id === id)
|
||||
.filter(change => change.tags !== undefined);
|
||||
|
||||
for (const pendingChange of pendingChanges) {
|
||||
const tagChanges = pendingChange.tags;
|
||||
for (const tagChange of tagChanges) {
|
||||
const key = tagChange.k
|
||||
const v = tagChange.v
|
||||
if (v === undefined || v === "") {
|
||||
delete latestTags[key]
|
||||
} else {
|
||||
latestTags[key] = v
|
||||
try {
|
||||
|
||||
const pendingChanges = state.changes.pendingChanges.data
|
||||
.filter(change => change.type + "/" + change.id === id)
|
||||
.filter(change => change.tags !== undefined);
|
||||
|
||||
for (const pendingChange of pendingChanges) {
|
||||
const tagChanges = pendingChange.tags;
|
||||
for (const tagChange of tagChanges) {
|
||||
const key = tagChange.k
|
||||
const v = tagChange.v
|
||||
if (v === undefined || v === "") {
|
||||
delete latestTags[key]
|
||||
} else {
|
||||
latestTags[key] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// With the changes applied, we merge them onto the upstream object
|
||||
let somethingChanged = false;
|
||||
const currentTagsSource = state.allElements.getEventSourceById(id);
|
||||
const currentTags = currentTagsSource.data
|
||||
for (const key in latestTags) {
|
||||
let osmValue = latestTags[key]
|
||||
|
||||
if(typeof osmValue === "number"){
|
||||
osmValue = ""+osmValue
|
||||
}
|
||||
|
||||
const localValue = currentTags[key]
|
||||
if (localValue !== osmValue) {
|
||||
console.log("Local value for ", key ,":", localValue, "upstream", osmValue)
|
||||
somethingChanged = true;
|
||||
currentTags[key] = osmValue
|
||||
}
|
||||
}
|
||||
if (somethingChanged) {
|
||||
console.log("Detected upstream changes to the object when opening it, updating...")
|
||||
currentTagsSource.ping()
|
||||
}else{
|
||||
console.debug("Fetched latest tags for ", id, "but detected no changes")
|
||||
}
|
||||
// With the changes applied, we merge them onto the upstream object
|
||||
let somethingChanged = false;
|
||||
const currentTagsSource = state.allElements.getEventSourceById(id);
|
||||
const currentTags = currentTagsSource.data
|
||||
for (const key in latestTags) {
|
||||
let osmValue = latestTags[key]
|
||||
|
||||
if (typeof osmValue === "number") {
|
||||
osmValue = "" + osmValue
|
||||
}
|
||||
|
||||
const localValue = currentTags[key]
|
||||
if (localValue !== osmValue) {
|
||||
console.log("Local value for ", key, ":", localValue, "upstream", osmValue)
|
||||
somethingChanged = true;
|
||||
currentTags[key] = osmValue
|
||||
}
|
||||
}
|
||||
|
||||
for (const currentKey in currentTags) {
|
||||
if (currentKey.startsWith("_")) {
|
||||
continue
|
||||
}
|
||||
if(this.metatags.has(currentKey)){
|
||||
continue
|
||||
}
|
||||
if (currentKey in latestTags) {
|
||||
continue
|
||||
}
|
||||
console.log("Removing key as deleted upstream", currentKey)
|
||||
delete currentTags[currentKey]
|
||||
somethingChanged = true
|
||||
}
|
||||
|
||||
|
||||
if (somethingChanged) {
|
||||
console.log("Detected upstream changes to the object when opening it, updating...")
|
||||
currentTagsSource.ping()
|
||||
} else {
|
||||
console.debug("Fetched latest tags for ", id, "but detected no changes")
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Updating the tags of selected element ", id, "failed due to", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,15 +3,20 @@ import {OsmObject} from "../Osm/OsmObject";
|
|||
import Loc from "../../Models/Loc";
|
||||
import {ElementStorage} from "../ElementStorage";
|
||||
import FeaturePipeline from "../FeatureSource/FeaturePipeline";
|
||||
import {GeoOperations} from "../GeoOperations";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
|
||||
/**
|
||||
* Makes sure the hash shows the selected element and vice-versa.
|
||||
*/
|
||||
export default class SelectedFeatureHandler {
|
||||
private static readonly _no_trigger_on = new Set(["welcome", "copyright", "layers", "new", "", undefined])
|
||||
hash: UIEventSource<string>;
|
||||
private static readonly _no_trigger_on = new Set(["welcome", "copyright", "layers", "new", "filter","", undefined])
|
||||
private readonly hash: UIEventSource<string>;
|
||||
private readonly state: {
|
||||
selectedElement: UIEventSource<any>
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
locationControl: UIEventSource<Loc>,
|
||||
layoutToUse: LayoutConfig
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
@ -19,7 +24,9 @@ export default class SelectedFeatureHandler {
|
|||
state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
featurePipeline: FeaturePipeline
|
||||
featurePipeline: FeaturePipeline,
|
||||
locationControl: UIEventSource<Loc>,
|
||||
layoutToUse: LayoutConfig
|
||||
}
|
||||
) {
|
||||
this.hash = hash;
|
||||
|
@ -27,30 +34,9 @@ export default class SelectedFeatureHandler {
|
|||
|
||||
|
||||
// If the hash changes, set the selected element correctly
|
||||
function setSelectedElementFromHash(h){
|
||||
if (h === undefined || h === "") {
|
||||
// Hash has been cleared - we clear the selected element
|
||||
state.selectedElement.setData(undefined);
|
||||
}else{
|
||||
// we search the element to select
|
||||
const feature = state.allElements.ContainingFeatures.get(h)
|
||||
if(feature === undefined){
|
||||
return;
|
||||
}
|
||||
const currentlySeleced = state.selectedElement.data
|
||||
if(currentlySeleced === undefined){
|
||||
state.selectedElement.setData(feature)
|
||||
return;
|
||||
}
|
||||
if(currentlySeleced.properties?.id === feature.properties.id){
|
||||
// We already have the right feature
|
||||
return;
|
||||
}
|
||||
state.selectedElement.setData(feature)
|
||||
}
|
||||
}
|
||||
|
||||
hash.addCallback(setSelectedElementFromHash)
|
||||
const self = this;
|
||||
hash.addCallback(() => self.setSelectedElementFromHash())
|
||||
|
||||
|
||||
// IF the selected element changes, set the hash correctly
|
||||
|
@ -66,41 +52,107 @@ export default class SelectedFeatureHandler {
|
|||
hash.setData(h)
|
||||
}
|
||||
})
|
||||
|
||||
state.featurePipeline.newDataLoadedSignal.addCallbackAndRunD(_ => {
|
||||
|
||||
state.featurePipeline?.newDataLoadedSignal?.addCallbackAndRunD(_ => {
|
||||
// New data was loaded. In initial startup, the hash might be set (via the URL) but might not be selected yet
|
||||
if(hash.data === undefined || SelectedFeatureHandler._no_trigger_on.has(hash.data)){
|
||||
if (hash.data === undefined || SelectedFeatureHandler._no_trigger_on.has(hash.data)) {
|
||||
// This is an invalid hash anyway
|
||||
return;
|
||||
}
|
||||
if(state.selectedElement.data !== undefined){
|
||||
if (state.selectedElement.data !== undefined) {
|
||||
// We already have something selected
|
||||
return;
|
||||
}
|
||||
setSelectedElementFromHash(hash.data)
|
||||
self.setSelectedElementFromHash()
|
||||
})
|
||||
|
||||
|
||||
this.initialLoad()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On startup: check if the hash is loaded and eventually zoom to it
|
||||
* @private
|
||||
*/
|
||||
private initialLoad() {
|
||||
const hash = this.hash.data
|
||||
if (hash === undefined || hash === "" || hash.indexOf("-") >= 0) {
|
||||
return;
|
||||
}
|
||||
if (SelectedFeatureHandler._no_trigger_on.has(hash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(hash.startsWith("node") || hash.startsWith("way") || hash.startsWith("relation"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OsmObject.DownloadObjectAsync(hash).then(obj => {
|
||||
|
||||
try {
|
||||
|
||||
console.log("Downloaded selected object from OSM-API for initial load: ", hash)
|
||||
const geojson = obj.asGeoJson()
|
||||
this.state.allElements.addOrGetElement(geojson)
|
||||
this.state.selectedElement.setData(geojson)
|
||||
this.zoomToSelectedFeature()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// If a feature is selected via the hash, zoom there
|
||||
public zoomToSelectedFeature(location: UIEventSource<Loc>) {
|
||||
const hash = this.hash.data;
|
||||
if (hash === undefined || SelectedFeatureHandler._no_trigger_on.has(hash)) {
|
||||
return; // No valid feature selected
|
||||
}
|
||||
// We should have a valid osm-ID and zoom to it... But we wrap it in try-catch to be sure
|
||||
try {
|
||||
|
||||
OsmObject.DownloadObject(hash).addCallbackAndRunD(element => {
|
||||
const centerpoint = element.centerpoint();
|
||||
console.log("Zooming to location for select point: ", centerpoint)
|
||||
location.data.lat = centerpoint[0]
|
||||
location.data.lon = centerpoint[1]
|
||||
location.ping();
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("Could not download OSM-object with id", hash, " - probably a weird hash")
|
||||
private setSelectedElementFromHash() {
|
||||
const state = this.state
|
||||
const h = this.hash.data
|
||||
if (h === undefined || h === "") {
|
||||
// Hash has been cleared - we clear the selected element
|
||||
state.selectedElement.setData(undefined);
|
||||
} else {
|
||||
// we search the element to select
|
||||
const feature = state.allElements.ContainingFeatures.get(h)
|
||||
if (feature === undefined) {
|
||||
return;
|
||||
}
|
||||
const currentlySeleced = state.selectedElement.data
|
||||
if (currentlySeleced === undefined) {
|
||||
state.selectedElement.setData(feature)
|
||||
return;
|
||||
}
|
||||
if (currentlySeleced.properties?.id === feature.properties.id) {
|
||||
// We already have the right feature
|
||||
return;
|
||||
}
|
||||
state.selectedElement.setData(feature)
|
||||
}
|
||||
}
|
||||
|
||||
// If a feature is selected via the hash, zoom there
|
||||
private zoomToSelectedFeature() {
|
||||
|
||||
const selected = this.state.selectedElement.data
|
||||
if (selected === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const centerpoint = GeoOperations.centerpointCoordinates(selected)
|
||||
const location = this.state.locationControl;
|
||||
location.data.lon = centerpoint[0]
|
||||
location.data.lat = centerpoint[1]
|
||||
|
||||
const minZoom = Math.max(14, ...(this.state.layoutToUse?.layers?.map(l => l.minzoomVisible) ?? []))
|
||||
if (location.data.zoom < minZoom) {
|
||||
location.data.zoom = minZoom
|
||||
}
|
||||
|
||||
location.ping();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer";
|
|||
import Combine from "../../UI/Base/Combine";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import {ElementStorage} from "../ElementStorage";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class TitleHandler {
|
||||
constructor(state : {
|
||||
|
@ -38,6 +39,9 @@ export default class TitleHandler {
|
|||
|
||||
|
||||
currentTitle.addCallbackAndRunD(title => {
|
||||
if(Utils.runningFromConsole){
|
||||
return
|
||||
}
|
||||
document.title = title
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import State from "../State";
|
|||
import BaseUIElement from "../UI/BaseUIElement";
|
||||
import List from "../UI/Base/List";
|
||||
import Title from "../UI/Base/Title";
|
||||
import {UIEventSourceTools} from "./UIEventSource";
|
||||
import AspectedRouting from "./Osm/aspectedRouting";
|
||||
import {BBox} from "./BBox";
|
||||
|
||||
export interface ExtraFuncParams {
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
* Technically, more an Actor then a featuresource, but it fits more neatly this ay
|
||||
*/
|
||||
import {FeatureSourceForLayer} from "../FeatureSource";
|
||||
import {Tiles} from "../../../Models/TileRange";
|
||||
|
||||
export default class SaveTileToLocalStorageActor {
|
||||
public static readonly storageKey: string = "cached-features";
|
||||
public static readonly formatVersion: string = "2"
|
||||
|
||||
constructor(source: FeatureSourceForLayer, tileIndex: number) {
|
||||
|
||||
|
||||
source.features.addCallbackAndRunD(features => {
|
||||
const key = `${SaveTileToLocalStorageActor.storageKey}-${source.layer.layerDef.id}-${tileIndex}`
|
||||
const now = new Date()
|
||||
|
@ -28,13 +29,30 @@ export default class SaveTileToLocalStorageActor {
|
|||
}
|
||||
|
||||
|
||||
public static MarkVisited(layerId: string, tileId: number, freshness: Date){
|
||||
public static MarkVisited(layerId: string, tileId: number, freshness: Date) {
|
||||
const key = `${SaveTileToLocalStorageActor.storageKey}-${layerId}-${tileId}`
|
||||
try{
|
||||
try {
|
||||
localStorage.setItem(key + "-time", JSON.stringify(freshness.getTime()))
|
||||
localStorage.setItem(key + "-format", SaveTileToLocalStorageActor.formatVersion)
|
||||
}catch(e){
|
||||
} catch (e) {
|
||||
console.error("Could not mark tile ", key, "as visited")
|
||||
}
|
||||
}
|
||||
|
||||
public static poison(layers: string[], lon: number, lat: number) {
|
||||
for (let z = 0; z < 25; z++) {
|
||||
|
||||
const {x, y} = Tiles.embedded_tile(lat, lon, z)
|
||||
const tileId = Tiles.tile_index(z, x, y)
|
||||
|
||||
for (const layerId of layers) {
|
||||
|
||||
const key = `${SaveTileToLocalStorageActor.storageKey}-${layerId}-${tileId}`
|
||||
localStorage.removeItem(key + "-time");
|
||||
localStorage.removeItem(key + "-format")
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -30,14 +30,14 @@ import TileFreshnessCalculator from "./TileFreshnessCalculator";
|
|||
|
||||
/**
|
||||
* The features pipeline ties together a myriad of various datasources:
|
||||
*
|
||||
*
|
||||
* - The Overpass-API
|
||||
* - The OSM-API
|
||||
* - Third-party geojson files, either sliced or directly.
|
||||
*
|
||||
*
|
||||
* In order to truly understand this class, please have a look at the following diagram: https://cdn-images-1.medium.com/fit/c/800/618/1*qTK1iCtyJUr4zOyw4IFD7A.jpeg
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
export default class FeaturePipeline {
|
||||
|
||||
|
@ -68,7 +68,7 @@ export default class FeaturePipeline {
|
|||
|
||||
private readonly freshnesses = new Map<string, TileFreshnessCalculator>();
|
||||
|
||||
private readonly oldestAllowedDate: Date = new Date(new Date().getTime() - 60 * 60 * 24 * 30 * 1000);
|
||||
private readonly oldestAllowedDate: Date;
|
||||
private readonly osmSourceZoomLevel
|
||||
|
||||
constructor(
|
||||
|
@ -90,10 +90,23 @@ export default class FeaturePipeline {
|
|||
this.state = state;
|
||||
|
||||
const self = this
|
||||
const expiryInSeconds = Math.min(...state.layoutToUse.layers.map(l => l.maxAgeOfCache))
|
||||
for (const layer of state.layoutToUse.layers) {
|
||||
TiledFromLocalStorageSource.cleanCacheForLayer(layer)
|
||||
}
|
||||
this.oldestAllowedDate = new Date(new Date().getTime() - expiryInSeconds);
|
||||
this.osmSourceZoomLevel = state.osmApiTileSize.data;
|
||||
// milliseconds
|
||||
const useOsmApi = state.locationControl.map(l => l.zoom > (state.overpassMaxZoom.data ?? 12))
|
||||
this.relationTracker = new RelationsTracker()
|
||||
|
||||
state.changes.allChanges.addCallbackAndRun(allChanges => {
|
||||
allChanges.filter(ch => ch.id < 0 && ch.changes !== undefined)
|
||||
.map(ch => ch.changes)
|
||||
.filter(coor => coor["lat"] !== undefined && coor["lon"] !== undefined)
|
||||
.forEach(coor => {
|
||||
SaveTileToLocalStorageActor.poison(state.layoutToUse.layers.map(l => l.id), coor["lon"], coor["lat"])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
this.sufficientlyZoomed = state.locationControl.map(location => {
|
||||
|
@ -220,7 +233,7 @@ export default class FeaturePipeline {
|
|||
maxZoomLevel: state.layoutToUse.clustering.maxZoom,
|
||||
registerTile: (tile) => {
|
||||
// We save the tile data for the given layer to local storage
|
||||
if(source.layer.layerDef.source.geojsonSource === undefined || source.layer.layerDef.source.isOsmCacheLayer == true){
|
||||
if (source.layer.layerDef.source.geojsonSource === undefined || source.layer.layerDef.source.isOsmCacheLayer == true) {
|
||||
new SaveTileToLocalStorageActor(tile, tile.tileIndex)
|
||||
}
|
||||
perLayerHierarchy.get(source.layer.layerDef.id).registerTile(new RememberingSource(tile))
|
||||
|
@ -257,7 +270,7 @@ export default class FeaturePipeline {
|
|||
this.runningQuery = updater.runningQuery.map(
|
||||
overpass => {
|
||||
console.log("FeaturePipeline: runningQuery state changed. Overpass", overpass ? "is querying," : "is idle,",
|
||||
"osmFeatureSource is", osmFeatureSource.isRunning ? "is running and needs "+neededTilesFromOsm.data?.length+" tiles (already got "+ osmFeatureSource.downloadedTiles.size +" tiles )" : "is idle")
|
||||
"osmFeatureSource is", osmFeatureSource.isRunning ? "is running and needs " + neededTilesFromOsm.data?.length + " tiles (already got " + osmFeatureSource.downloadedTiles.size + " tiles )" : "is idle")
|
||||
return overpass || osmFeatureSource.isRunning.data;
|
||||
}, [osmFeatureSource.isRunning]
|
||||
)
|
||||
|
@ -353,7 +366,7 @@ export default class FeaturePipeline {
|
|||
isActive: useOsmApi.map(b => !b && overpassIsActive.data, [overpassIsActive]),
|
||||
onBboxLoaded: (bbox, date, downloadedLayers, paddedToZoomLevel) => {
|
||||
Tiles.MapRange(bbox.containingTileRange(paddedToZoomLevel), (x, y) => {
|
||||
const tileIndex = Tiles.tile_index(paddedToZoomLevel, x, y)
|
||||
const tileIndex = Tiles.tile_index(paddedToZoomLevel, x, y)
|
||||
downloadedLayers.forEach(layer => {
|
||||
self.freshnesses.get(layer.id).addTileLoad(tileIndex, date)
|
||||
SaveTileToLocalStorageActor.MarkVisited(layer.id, tileIndex, date)
|
||||
|
@ -412,7 +425,7 @@ export default class FeaturePipeline {
|
|||
}
|
||||
|
||||
public GetFeaturesWithin(layerId: string, bbox: BBox): any[][] {
|
||||
if(layerId === "*"){
|
||||
if (layerId === "*") {
|
||||
return this.GetAllFeaturesWithin(bbox)
|
||||
}
|
||||
const requestedHierarchy = this.perLayerHierarchy.get(layerId)
|
||||
|
|
|
@ -5,6 +5,7 @@ import TileHierarchy from "./TileHierarchy";
|
|||
import SaveTileToLocalStorageActor from "../Actors/SaveTileToLocalStorageActor";
|
||||
import {Tiles} from "../../../Models/TileRange";
|
||||
import {BBox} from "../../BBox";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
export default class TiledFromLocalStorageSource implements TileHierarchy<FeatureSourceForLayer & Tiled> {
|
||||
public readonly loadedTiles: Map<number, FeatureSourceForLayer & Tiled> = new Map<number, FeatureSourceForLayer & Tiled>();
|
||||
|
@ -16,7 +17,7 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layerId + "-"
|
||||
const freshnesses = new Map<number, Date>()
|
||||
for (const key of Object.keys(localStorage)) {
|
||||
if(!(key.startsWith(prefix) && key.endsWith("-time"))){
|
||||
if (!(key.startsWith(prefix) && key.endsWith("-time"))) {
|
||||
continue
|
||||
}
|
||||
const index = Number(key.substring(prefix.length, key.length - "-time".length))
|
||||
|
@ -28,6 +29,28 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
return freshnesses
|
||||
}
|
||||
|
||||
|
||||
static cleanCacheForLayer(layer: LayerConfig) {
|
||||
const now = new Date()
|
||||
const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layer.id + "-"
|
||||
console.log("Cleaning tiles of ", prefix, "with max age",layer.maxAgeOfCache)
|
||||
for (const key of Object.keys(localStorage)) {
|
||||
if (!(key.startsWith(prefix) && key.endsWith("-time"))) {
|
||||
continue
|
||||
}
|
||||
const index = Number(key.substring(prefix.length, key.length - "-time".length))
|
||||
const time = Number(localStorage.getItem(key))
|
||||
const timeDiff = (now.getTime() - time) / 1000
|
||||
|
||||
if(timeDiff >= layer.maxAgeOfCache){
|
||||
const k = prefix+index;
|
||||
localStorage.removeItem(k)
|
||||
localStorage.removeItem(k+"-format")
|
||||
localStorage.removeItem(k+"-time")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(layer: FilteredLayer,
|
||||
handleFeatureSource: (src: FeatureSourceForLayer & Tiled, index: number) => void,
|
||||
state: {
|
||||
|
@ -36,7 +59,7 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
this.layer = layer;
|
||||
this.handleFeatureSource = handleFeatureSource;
|
||||
|
||||
|
||||
|
||||
this.undefinedTiles = new Set<number>()
|
||||
const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layer.layerDef.id + "-"
|
||||
const knownTiles: number[] = Object.keys(localStorage)
|
||||
|
@ -56,9 +79,9 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
if (version === undefined || version !== SaveTileToLocalStorageActor.formatVersion) {
|
||||
// Invalid version! Remove this tile from local storage
|
||||
localStorage.removeItem(prefix)
|
||||
localStorage.removeItem(prefix+"-time")
|
||||
localStorage.removeItem(prefix+"-format")
|
||||
this. undefinedTiles.add(index)
|
||||
localStorage.removeItem(prefix + "-time")
|
||||
localStorage.removeItem(prefix + "-format")
|
||||
this.undefinedTiles.add(index)
|
||||
console.log("Dropped old format tile", prefix)
|
||||
}
|
||||
}
|
||||
|
@ -66,19 +89,19 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
const self = this
|
||||
state.currentBounds.map(bounds => {
|
||||
|
||||
if(bounds === undefined){
|
||||
if (bounds === undefined) {
|
||||
return;
|
||||
}
|
||||
for (const knownTile of knownTiles) {
|
||||
|
||||
if(this.loadedTiles.has(knownTile)){
|
||||
|
||||
if (this.loadedTiles.has(knownTile)) {
|
||||
continue;
|
||||
}
|
||||
if(this.undefinedTiles.has(knownTile)){
|
||||
if (this.undefinedTiles.has(knownTile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!bounds.overlapsWith(BBox.fromTileIndex(knownTile))){
|
||||
|
||||
if (!bounds.overlapsWith(BBox.fromTileIndex(knownTile))) {
|
||||
continue;
|
||||
}
|
||||
self.loadTile(knownTile)
|
||||
|
@ -86,8 +109,8 @@ export default class TiledFromLocalStorageSource implements TileHierarchy<Featur
|
|||
})
|
||||
|
||||
}
|
||||
|
||||
private loadTile( neededIndex: number){
|
||||
|
||||
private loadTile(neededIndex: number) {
|
||||
try {
|
||||
const key = SaveTileToLocalStorageActor.storageKey + "-" + this.layer.layerDef.id + "-" + neededIndex
|
||||
const data = localStorage.getItem(key)
|
||||
|
|
|
@ -21,11 +21,13 @@ export default class AllImageProviders {
|
|||
)
|
||||
|
||||
]
|
||||
|
||||
public static defaultKeys = [].concat(AllImageProviders.ImageAttributionSource.map(provider => provider.defaultKeyPrefixes))
|
||||
|
||||
|
||||
private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>()
|
||||
|
||||
public static LoadImagesFor(tags: UIEventSource<any>, tagKey?: string): UIEventSource<ProvidedImage[]> {
|
||||
public static LoadImagesFor(tags: UIEventSource<any>, tagKey?: string[]): UIEventSource<ProvidedImage[]> {
|
||||
if (tags.data.id === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ export default class AllImageProviders {
|
|||
|
||||
let prefixes = imageProvider.defaultKeyPrefixes
|
||||
if(tagKey !== undefined){
|
||||
prefixes = [...prefixes, tagKey]
|
||||
prefixes = tagKey
|
||||
}
|
||||
|
||||
const singleSource = imageProvider.GetRelevantUrls(tags, {
|
||||
|
|
|
@ -27,7 +27,8 @@ export default class ImgurUploader {
|
|||
files,
|
||||
function (url) {
|
||||
console.log("File saved at", url);
|
||||
self.success.setData([...self.success.data, url]);
|
||||
self.success.data.push(url)
|
||||
self.success.ping();
|
||||
self._handleSuccessUrl(url);
|
||||
},
|
||||
function () {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import ImageProvider, {ProvidedImage} from "./ImageProvider";
|
||||
import BaseUIElement from "../../UI/BaseUIElement";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import Svg from "../../Svg";
|
||||
import {Utils} from "../../Utils";
|
||||
import {LicenseInfo} from "./LicenseInfo";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {fail} from "assert";
|
||||
|
||||
export class Mapillary extends ImageProvider {
|
||||
|
||||
|
@ -13,7 +11,7 @@ export class Mapillary extends ImageProvider {
|
|||
|
||||
public static readonly singleton = new Mapillary();
|
||||
private static readonly valuePrefix = "https://a.mapillary.com"
|
||||
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com","https://mapillary.com"]
|
||||
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com","https://mapillary.com","http://www.mapillary.com","https://www.mapillary.com"]
|
||||
|
||||
private static ExtractKeyFromURL(value: string, failIfNoMath = false): {
|
||||
key: string,
|
||||
|
|
|
@ -10,13 +10,9 @@ export interface RelationSplitInput {
|
|||
originalNodes: number[],
|
||||
allWaysNodesInOrder: number[][]
|
||||
}
|
||||
|
||||
/**
|
||||
* When a way is split and this way is part of a relation, the relation should be updated too to have the new segment if relevant.
|
||||
*/
|
||||
export default class RelationSplitHandler extends OsmChangeAction {
|
||||
private readonly _input: RelationSplitInput;
|
||||
private readonly _theme: string;
|
||||
abstract class AbstractRelationSplitHandler extends OsmChangeAction {
|
||||
protected readonly _input: RelationSplitInput;
|
||||
protected readonly _theme: string;
|
||||
|
||||
constructor(input: RelationSplitInput, theme: string) {
|
||||
super()
|
||||
|
@ -24,35 +20,10 @@ export default class RelationSplitHandler extends OsmChangeAction {
|
|||
this._theme = theme;
|
||||
}
|
||||
|
||||
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
return new InPlaceReplacedmentRTSH(this._input, this._theme).CreateChangeDescriptions(changes)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple strategy to split relations:
|
||||
* -> Download the way members just before and just after the original way
|
||||
* -> Make sure they are still aligned
|
||||
*
|
||||
* Note that the feature might appear multiple times.
|
||||
*/
|
||||
export class InPlaceReplacedmentRTSH extends OsmChangeAction {
|
||||
private readonly _input: RelationSplitInput;
|
||||
private readonly _theme: string;
|
||||
|
||||
constructor(input: RelationSplitInput, theme: string) {
|
||||
super();
|
||||
this._input = input;
|
||||
this._theme = theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which node should border the member at the given index
|
||||
*/
|
||||
private async targetNodeAt(i: number, first: boolean) {
|
||||
protected async targetNodeAt(i: number, first: boolean) {
|
||||
const member = this._input.relation.members[i]
|
||||
if (member === undefined) {
|
||||
return undefined
|
||||
|
@ -74,6 +45,124 @@ export class InPlaceReplacedmentRTSH extends OsmChangeAction {
|
|||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a way is split and this way is part of a relation, the relation should be updated too to have the new segment if relevant.
|
||||
*/
|
||||
export default class RelationSplitHandler extends AbstractRelationSplitHandler {
|
||||
|
||||
constructor(input: RelationSplitInput, theme: string) {
|
||||
super(input, theme)
|
||||
}
|
||||
|
||||
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
if(this._input.relation.tags["type"] === "restriction"){
|
||||
// This is a turn restriction
|
||||
return new TurnRestrictionRSH(this._input, this._theme).CreateChangeDescriptions(changes)
|
||||
}
|
||||
return new InPlaceReplacedmentRTSH(this._input, this._theme).CreateChangeDescriptions(changes)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class TurnRestrictionRSH extends AbstractRelationSplitHandler {
|
||||
|
||||
constructor(input: RelationSplitInput, theme: string) {
|
||||
super(input, theme);
|
||||
}
|
||||
|
||||
public async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
|
||||
const relation = this._input.relation
|
||||
const members = relation.members
|
||||
|
||||
const selfMembers = members.filter(m => m.type === "way" && m.ref === this._input.originalWayId)
|
||||
|
||||
if(selfMembers.length > 1){
|
||||
console.warn("Detected a turn restriction where this way has multiple occurances. This is an error")
|
||||
}
|
||||
const selfMember = selfMembers[0]
|
||||
|
||||
if(selfMember.role === "via"){
|
||||
// A via way can be replaced in place
|
||||
return new InPlaceReplacedmentRTSH(this._input, this._theme).CreateChangeDescriptions(changes);
|
||||
}
|
||||
|
||||
|
||||
// We have to keep only the way with a common point with the rest of the relation
|
||||
// Let's figure out which member is neighbouring our way
|
||||
|
||||
let commonStartPoint : number = await this.targetNodeAt(members.indexOf(selfMember), true)
|
||||
let commonEndPoint : number = await this.targetNodeAt(members.indexOf(selfMember), false)
|
||||
|
||||
// In normal circumstances, only one of those should be defined
|
||||
let commonPoint = commonStartPoint ?? commonEndPoint
|
||||
|
||||
// Let's select the way to keep
|
||||
const idToKeep : {id: number} = this._input.allWaysNodesInOrder.map((nodes, i) => ({nodes: nodes, id: this._input.allWayIdsInOrder[i]}))
|
||||
.filter(nodesId => {
|
||||
const nds = nodesId.nodes
|
||||
return nds[0] == commonPoint || nds[nds.length - 1] == commonPoint
|
||||
})[0]
|
||||
|
||||
if(idToKeep === undefined){
|
||||
console.error("No common point found, this was a broken turn restriction!", relation.id)
|
||||
return []
|
||||
}
|
||||
|
||||
const originalWayId = this._input.originalWayId
|
||||
if(idToKeep.id === originalWayId){
|
||||
console.log("Turn_restriction fixer: the original ID can be kept, nothing to do")
|
||||
return []
|
||||
}
|
||||
|
||||
const newMembers : {
|
||||
ref:number,
|
||||
type:"way" | "node" | "relation",
|
||||
role:string
|
||||
} [] = relation.members.map(m => {
|
||||
if(m.type === "way" && m.ref === originalWayId){
|
||||
return {
|
||||
ref: idToKeep.id,
|
||||
type:"way",
|
||||
role: m.role
|
||||
}
|
||||
}
|
||||
return m
|
||||
})
|
||||
|
||||
|
||||
return [
|
||||
{
|
||||
type: "relation",
|
||||
id: relation.id,
|
||||
changes: {
|
||||
members: newMembers
|
||||
},
|
||||
meta: {
|
||||
theme: this._theme,
|
||||
changeType: "relation-fix:turn_restriction"
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple strategy to split relations:
|
||||
* -> Download the way members just before and just after the original way
|
||||
* -> Make sure they are still aligned
|
||||
*
|
||||
* Note that the feature might appear multiple times.
|
||||
*/
|
||||
export class InPlaceReplacedmentRTSH extends AbstractRelationSplitHandler {
|
||||
|
||||
constructor(input: RelationSplitInput, theme: string) {
|
||||
super(input, theme);
|
||||
}
|
||||
|
||||
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ export class Changes {
|
|||
console.log("Is already uploading... Abort")
|
||||
return;
|
||||
}
|
||||
console.log("Uploading changes due to: ", flushreason)
|
||||
this.isUploading.setData(true)
|
||||
|
||||
this.flushChangesAsync()
|
||||
|
@ -287,7 +288,7 @@ export class Changes {
|
|||
v = undefined;
|
||||
}
|
||||
|
||||
const oldV = obj.type[k]
|
||||
const oldV = obj.tags[k]
|
||||
if (oldV === v) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import Svg from "../../Svg";
|
|||
import Img from "../../UI/Base/Img";
|
||||
import {Utils} from "../../Utils";
|
||||
import {OsmObject} from "./OsmObject";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import {Changes} from "./Changes";
|
||||
|
||||
export default class UserDetails {
|
||||
|
@ -97,7 +96,6 @@ export class OsmConnection {
|
|||
self.AttemptLogin()
|
||||
}
|
||||
});
|
||||
this.isLoggedIn.addCallbackAndRunD(li => console.log("User is logged in!", li))
|
||||
this._dryRun = options.dryRun;
|
||||
|
||||
this.updateAuthObject();
|
||||
|
|
|
@ -263,7 +263,7 @@ export abstract class OsmObject {
|
|||
continue;
|
||||
}
|
||||
const v = this.tags[key];
|
||||
if (v !== "") {
|
||||
if (v !== "" && v !== undefined) {
|
||||
tags += ' <tag k="' + Utils.EncodeXmlValue(key) + '" v="' + Utils.EncodeXmlValue(this.tags[key]) + '"/>\n'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
|||
import {UIEventSource} from "../UIEventSource";
|
||||
import {QueryParameters} from "../Web/QueryParameters";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class FeatureSwitchState {
|
||||
|
||||
|
@ -137,37 +138,26 @@ export default class FeatureSwitchState {
|
|||
|
||||
|
||||
let testingDefaultValue = false;
|
||||
if (this.featureSwitchApiURL.data !== "osm-test" &&
|
||||
if (this.featureSwitchApiURL.data !== "osm-test" && !Utils.runningFromConsole &&
|
||||
(location.hostname === "localhost" || location.hostname === "127.0.0.1")) {
|
||||
testingDefaultValue = true
|
||||
}
|
||||
|
||||
|
||||
this.featureSwitchIsTesting = QueryParameters.GetQueryParameter(
|
||||
this.featureSwitchIsTesting = QueryParameters.GetBooleanQueryParameter(
|
||||
"test",
|
||||
""+testingDefaultValue,
|
||||
"If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org"
|
||||
).map(
|
||||
(str) => str === "true",
|
||||
[],
|
||||
(b) => "" + b
|
||||
);
|
||||
)
|
||||
|
||||
this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter(
|
||||
this.featureSwitchIsDebugging = QueryParameters.GetBooleanQueryParameter(
|
||||
"debug",
|
||||
"false",
|
||||
"If true, shows some extra debugging help such as all the available tags on every object"
|
||||
).map(
|
||||
(str) => str === "true",
|
||||
[],
|
||||
(b) => "" + b
|
||||
);
|
||||
)
|
||||
|
||||
this.featureSwitchFakeUser = QueryParameters.GetQueryParameter("fake-user", "false",
|
||||
this.featureSwitchFakeUser = QueryParameters.GetBooleanQueryParameter("fake-user", "false",
|
||||
"If true, 'dryrun' mode is activated and a fake user account is loaded")
|
||||
.map(str => str === "true", [], b => "" + b);
|
||||
|
||||
|
||||
|
||||
|
||||
this.overpassUrl = QueryParameters.GetQueryParameter("overpassUrl",
|
||||
|
|
|
@ -119,7 +119,7 @@ export default class MapState extends UserRelatedState {
|
|||
|
||||
this.overlayToggles = this.layoutToUse.tileLayerSources.filter(c => c.name !== undefined).map(c => ({
|
||||
config: c,
|
||||
isDisplayed: QueryParameters.GetQueryParameter("overlay-" + c.id, "" + c.defaultState, "Wether or not the overlay " + c.id + " is shown").map(str => str === "true", [], b => "" + b)
|
||||
isDisplayed: QueryParameters.GetBooleanQueryParameter("overlay-" + c.id, "" + c.defaultState, "Wether or not the overlay " + c.id + " is shown")
|
||||
}))
|
||||
this.filteredLayers = this.InitializeFilteredLayers()
|
||||
|
||||
|
@ -170,17 +170,12 @@ export default class MapState extends UserRelatedState {
|
|||
.map(value => value === "yes", [], enabled => {
|
||||
return enabled ? "yes" : "";
|
||||
})
|
||||
isDisplayed.addCallbackAndRun(d => console.log("IsDisplayed for layer", layer.id, "is currently", d))
|
||||
} else {
|
||||
isDisplayed = QueryParameters.GetQueryParameter(
|
||||
isDisplayed = QueryParameters.GetBooleanQueryParameter(
|
||||
"layer-" + layer.id,
|
||||
"true",
|
||||
"Wether or not layer " + layer.id + " is shown"
|
||||
).map<boolean>(
|
||||
(str) => str !== "false",
|
||||
[],
|
||||
(b) => b.toString()
|
||||
);
|
||||
)
|
||||
}
|
||||
const flayer = {
|
||||
isDisplayed: isDisplayed,
|
||||
|
|
|
@ -286,6 +286,9 @@ export class UIEventSource<T> {
|
|||
}
|
||||
|
||||
public stabilized(millisToStabilize): UIEventSource<T> {
|
||||
if(Utils.runningFromConsole){
|
||||
return this;
|
||||
}
|
||||
|
||||
const newSource = new UIEventSource<T>(this.data);
|
||||
|
||||
|
@ -334,21 +337,4 @@ export class UIEventSource<T> {
|
|||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class UIEventSourceTools {
|
||||
|
||||
private static readonly _download_cache = new Map<string, UIEventSource<any>>()
|
||||
|
||||
public static downloadJsonCached(url: string): UIEventSource<any> {
|
||||
const cached = UIEventSourceTools._download_cache.get(url)
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
const src = new UIEventSource<any>(undefined)
|
||||
UIEventSourceTools._download_cache.set(url, src)
|
||||
Utils.downloadJson(url).then(r => src.setData(r))
|
||||
return src;
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,10 @@ export class QueryParameters {
|
|||
return source;
|
||||
}
|
||||
|
||||
public static GetBooleanQueryParameter(key: string, deflt: string, documentation?: string): UIEventSource<boolean>{
|
||||
return QueryParameters.GetQueryParameter(key, deflt, documentation).map(str => str === "true", [], b => ""+b)
|
||||
}
|
||||
|
||||
public static GenerateQueryParameterDocs(): string {
|
||||
const docs = [QueryParameters.QueryParamDocsIntro];
|
||||
for (const key in QueryParameters.documentation) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Utils} from "../Utils";
|
|||
|
||||
export default class Constants {
|
||||
|
||||
public static vNumber = "0.11.0-rc-1";
|
||||
public static vNumber = "0.11.2";
|
||||
public static ImgurApiKey = '7070e7167f0a25a'
|
||||
public static readonly mapillary_client_token_v3 = 'TXhLaWthQ1d4RUg0czVxaTVoRjFJZzowNDczNjUzNmIyNTQyYzI2'
|
||||
public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85"
|
||||
|
|
|
@ -60,8 +60,13 @@ export interface LayerConfigJson {
|
|||
* NOTE: the previous format was 'overpassTags: AndOrTagConfigJson | string', which is interpreted as a shorthand for source: {osmTags: "key=value"}
|
||||
* While still supported, this is considered deprecated
|
||||
*/
|
||||
source: { osmTags: AndOrTagConfigJson | string, overpassScript?: string } |
|
||||
{ osmTags: AndOrTagConfigJson | string, geoJson: string, geoJsonZoomLevel?: number, isOsmCache?: boolean }
|
||||
source: ({ osmTags: AndOrTagConfigJson | string, overpassScript?: string } |
|
||||
{ osmTags: AndOrTagConfigJson | string, geoJson: string, geoJsonZoomLevel?: number, isOsmCache?: boolean }) & ({
|
||||
/**
|
||||
* The maximum amount of seconds that a tile is allowed to linger in the cache
|
||||
*/
|
||||
maxCacheAge?: number
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -174,26 +174,6 @@ export interface LayoutConfigJson {
|
|||
*/
|
||||
tileLayerSources?: TilesourceConfigJson[]
|
||||
|
||||
/**
|
||||
* The number of seconds that a feature is allowed to stay in the cache.
|
||||
* The caching flow is as following:
|
||||
*
|
||||
* 1. The application is opened the first time
|
||||
* 2. An overpass query is run
|
||||
* 3. The result is saved to local storage
|
||||
*
|
||||
* On the next opening:
|
||||
*
|
||||
* 1. The application is opened
|
||||
* 2. Data is loaded from cache and displayed
|
||||
* 3. An overpass query is run
|
||||
* 4. All data (both from overpass ánd local storage) are saved again to local storage (except when to old)
|
||||
*
|
||||
* Default value: 60 days
|
||||
*/
|
||||
cacheTimout?: number;
|
||||
|
||||
|
||||
/**
|
||||
* The layers to display.
|
||||
*
|
||||
|
|
|
@ -52,6 +52,10 @@ export default class LayerConfig {
|
|||
public readonly deletion: DeleteConfig | null;
|
||||
public readonly allowMove: MoveConfig | null
|
||||
public readonly allowSplit: boolean
|
||||
/**
|
||||
* In seconds
|
||||
*/
|
||||
public readonly maxAgeOfCache: number
|
||||
|
||||
presets: PresetConfig[];
|
||||
|
||||
|
@ -87,7 +91,9 @@ export default class LayerConfig {
|
|||
// @ts-ignore
|
||||
legacy = TagUtils.Tag(json["overpassTags"], context + ".overpasstags");
|
||||
}
|
||||
|
||||
if (json.source !== undefined) {
|
||||
this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30
|
||||
if (legacy !== undefined) {
|
||||
throw (
|
||||
context +
|
||||
|
@ -126,7 +132,7 @@ export default class LayerConfig {
|
|||
osmTags: legacy,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.calculatedTags = undefined;
|
||||
if (json.calculatedTags !== undefined) {
|
||||
if (!official) {
|
||||
|
|
|
@ -49,10 +49,7 @@ export default class LayoutConfig {
|
|||
public readonly enableIframePopout: boolean;
|
||||
|
||||
public readonly customCss?: string;
|
||||
/*
|
||||
How long is the cache valid, in seconds?
|
||||
*/
|
||||
public readonly cacheTimeout?: number;
|
||||
|
||||
public readonly overpassUrl: string[];
|
||||
public readonly overpassTimeout: number;
|
||||
public readonly overpassMaxZoom: number
|
||||
|
@ -170,7 +167,6 @@ export default class LayoutConfig {
|
|||
this.enablePdfDownload = json.enablePdfDownload ?? false;
|
||||
this.enableIframePopout = json.enableIframePopout ?? true
|
||||
this.customCss = json.customCss;
|
||||
this.cacheTimeout = json.cacheTimout ?? (60 * 24 * 60 * 60)
|
||||
this.overpassUrl = Constants.defaultOverpassUrls
|
||||
if(json.overpassUrl !== undefined){
|
||||
if(typeof json.overpassUrl === "string"){
|
||||
|
|
|
@ -62,6 +62,9 @@ export default class TagRenderingConfig {
|
|||
this.render = Translations.T(json.render, context + ".render");
|
||||
this.question = Translations.T(json.question, context + ".question");
|
||||
this.roaming = json.roaming ?? false;
|
||||
if(this.roaming){
|
||||
console.warn("Deprecation notice: roaming renderings will be scrapped.", this.id, context)
|
||||
}
|
||||
const condition = TagUtils.Tag(json.condition ?? {"and": []}, `${context}.condition`);
|
||||
if (this.roaming && conditionIfRoaming !== undefined) {
|
||||
this.condition = new And([condition, conditionIfRoaming]);
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import {FixedUiElement} from "./FixedUiElement";
|
||||
|
||||
export default class Ornament extends FixedUiElement {
|
||||
|
||||
constructor() {
|
||||
super("");
|
||||
this.SetClass("pt-3 pb-3 flex justify-center box-border")
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import {UIElement} from "../UIElement";
|
||||
import Svg from "../../Svg";
|
||||
import Combine from "./Combine";
|
||||
import Ornament from "./Ornament";
|
||||
import {FixedUiElement} from "./FixedUiElement";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Hash from "../../Logic/Web/Hash";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Img from "./Img";
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -18,34 +18,43 @@ import BaseUIElement from "../BaseUIElement";
|
|||
*/
|
||||
export default class ScrollableFullScreen extends UIElement {
|
||||
private static readonly empty = new FixedUiElement("");
|
||||
private static readonly _actor = ScrollableFullScreen.InitActor();
|
||||
private static _currentlyOpen: ScrollableFullScreen;
|
||||
public isShown: UIEventSource<boolean>;
|
||||
private _component: BaseUIElement;
|
||||
private _fullscreencomponent: BaseUIElement;
|
||||
private _hashToSet: string;
|
||||
|
||||
constructor(title: ((mode: string) => BaseUIElement), content: ((mode: string) => BaseUIElement),
|
||||
hashToSet: string,
|
||||
hashToShow: string,
|
||||
isShown: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
||||
) {
|
||||
super();
|
||||
this.isShown = isShown;
|
||||
this._hashToSet = hashToSet;
|
||||
|
||||
if (hashToShow === undefined) {
|
||||
throw "HashToShow should be defined as it is vital for the 'back' key functionality"
|
||||
}
|
||||
|
||||
this._component = this.BuildComponent(title("desktop"), content("desktop"), isShown)
|
||||
.SetClass("hidden md:block");
|
||||
this._fullscreencomponent = this.BuildComponent(title("mobile"), content("mobile"), isShown);
|
||||
this._fullscreencomponent = this.BuildComponent(title("mobile"), content("mobile").SetClass("pb-20"), isShown);
|
||||
|
||||
|
||||
|
||||
const self = this;
|
||||
isShown.addCallback(isShown => {
|
||||
if (isShown) {
|
||||
self.Activate();
|
||||
Hash.hash.setData(hashToShow)
|
||||
} else {
|
||||
ScrollableFullScreen.clear();
|
||||
}
|
||||
})
|
||||
|
||||
Hash.hash.addCallback(hash => {
|
||||
if (hash === hashToShow) {
|
||||
return
|
||||
}
|
||||
isShown.setData(false)
|
||||
})
|
||||
}
|
||||
|
||||
private static clear() {
|
||||
|
@ -56,15 +65,6 @@ export default class ScrollableFullScreen extends UIElement {
|
|||
Hash.hash.setData(undefined);
|
||||
}
|
||||
|
||||
private static InitActor() {
|
||||
Hash.hash.addCallback(hash => {
|
||||
if (hash === undefined || hash === "") {
|
||||
ScrollableFullScreen.clear()
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
InnerRender(): BaseUIElement {
|
||||
return this._component;
|
||||
}
|
||||
|
@ -72,9 +72,6 @@ export default class ScrollableFullScreen extends UIElement {
|
|||
Activate(): void {
|
||||
this.isShown.setData(true)
|
||||
this._fullscreencomponent.AttachTo("fullscreen");
|
||||
if (this._hashToSet != undefined) {
|
||||
Hash.hash.setData(this._hashToSet)
|
||||
}
|
||||
const fs = document.getElementById("fullscreen");
|
||||
ScrollableFullScreen._currentlyOpen = this;
|
||||
fs.classList.remove("hidden")
|
||||
|
@ -83,25 +80,26 @@ export default class ScrollableFullScreen extends UIElement {
|
|||
private BuildComponent(title: BaseUIElement, content: BaseUIElement, isShown: UIEventSource<boolean>) {
|
||||
const returnToTheMap =
|
||||
new Combine([
|
||||
Svg.back_svg().SetClass("block md:hidden"),
|
||||
Svg.close_svg().SetClass("hidden md:block")
|
||||
])
|
||||
.onClick(() => {
|
||||
isShown.setData(false)
|
||||
}).SetClass("mb-2 bg-blue-50 rounded-full w-12 h-12 p-1.5 flex-shrink-0")
|
||||
new Img(Svg.back.replace(/#000000/g, "#cccccc"), true)
|
||||
.SetClass("block md:hidden w-12 h-12 p-2"),
|
||||
new Img(Svg.close.replace(/#000000/g, "#cccccc"), true)
|
||||
.SetClass("hidden md:block w-12 h-12 p-3")
|
||||
]).SetClass("rounded-full p-0 flex-shrink-0 self-center")
|
||||
|
||||
title.SetClass("block text-l sm:text-xl md:text-2xl w-full font-bold p-2 pl-4 max-h-20vh overflow-y-auto")
|
||||
const ornament = new Combine([new Ornament().SetStyle("height:5em;")])
|
||||
.SetClass("md:hidden h-5")
|
||||
returnToTheMap.onClick(() => {
|
||||
isShown.setData(false)
|
||||
})
|
||||
|
||||
title.SetClass("block text-l sm:text-xl md:text-2xl w-full font-bold p-0 max-h-20vh overflow-y-auto")
|
||||
return new Combine([
|
||||
new Combine([
|
||||
new Combine([returnToTheMap, title])
|
||||
.SetClass("border-b-2 border-black shadow md:shadow-none bg-white p-2 pb-0 md:p-0 flex flex-shrink-0"),
|
||||
new Combine([content, ornament])
|
||||
.SetClass("border-b-1 border-black shadow bg-white flex flex-shrink-0 pt-1 pb-1 md:pt-0 md:pb-0"),
|
||||
new Combine([content])
|
||||
.SetClass("block p-2 md:pt-4 w-full h-full overflow-y-auto md:max-h-65vh"),
|
||||
// We add an ornament which takes around 5em. This is in order to make sure the Web UI doesn't hide
|
||||
]).SetClass("flex flex-col h-full relative bg-white")
|
||||
]).SetClass("fixed top-0 left-0 right-0 h-screen w-screen md:max-h-65vh md:w-auto md:relative z-above-controls");
|
||||
]).SetClass("fixed top-0 left-0 right-0 h-screen w-screen md:max-h-65vh md:w-auto md:relative z-above-controls md:rounded-xl overflow-hidden");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,11 @@ import {DownloadPanel} from "./DownloadPanel";
|
|||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
import Svg from "../../Svg";
|
||||
import ExportPDF from "../ExportPDF";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
|
||||
export default class AllDownloads extends ScrollableFullScreen {
|
||||
|
||||
constructor(isShown: UIEventSource<boolean>) {
|
||||
super(AllDownloads.GenTitle, AllDownloads.GeneratePanel, "layers", isShown);
|
||||
super(AllDownloads.GenTitle, AllDownloads.GeneratePanel, "downloads", isShown);
|
||||
}
|
||||
|
||||
private static GenTitle(): BaseUIElement {
|
||||
|
|
|
@ -40,20 +40,16 @@ export default class FilterView extends VariableUiElement {
|
|||
const iconUnselected = new Combine([Svg.checkbox_empty]).SetStyle(
|
||||
iconStyle
|
||||
);
|
||||
const name: Translation = config.config.name.Clone();
|
||||
const name: Translation = config.config.name;
|
||||
|
||||
const styledNameChecked = name
|
||||
.Clone()
|
||||
.SetStyle("font-size:large;padding-left:1.25rem");
|
||||
const styledNameChecked = name.Clone().SetStyle("font-size:large;padding-left:1.25rem");
|
||||
|
||||
const styledNameUnChecked = name
|
||||
.Clone()
|
||||
.SetStyle("font-size:large;padding-left:1.25rem");
|
||||
const styledNameUnChecked = name.Clone().SetStyle("font-size:large;padding-left:1.25rem");
|
||||
|
||||
const zoomStatus =
|
||||
new Toggle(
|
||||
undefined,
|
||||
Translations.t.general.layerSelection.zoomInToSeeThisLayer.Clone()
|
||||
Translations.t.general.layerSelection.zoomInToSeeThisLayer
|
||||
.SetClass("alert")
|
||||
.SetStyle("display: block ruby;width:min-content;"),
|
||||
State.state.locationControl.map(location => location.zoom >= config.config.minzoom)
|
||||
|
@ -97,20 +93,16 @@ export default class FilterView extends VariableUiElement {
|
|||
|
||||
const name: Translation = Translations.WT(
|
||||
filteredLayer.layerDef.name
|
||||
)?.Clone();
|
||||
);
|
||||
|
||||
const styledNameChecked = name
|
||||
.Clone()
|
||||
.SetStyle("font-size:large;padding-left:1.25rem");
|
||||
const styledNameChecked = name.Clone().SetStyle("font-size:large;padding-left:1.25rem");
|
||||
|
||||
const styledNameUnChecked = name
|
||||
.Clone()
|
||||
.SetStyle("font-size:large;padding-left:1.25rem");
|
||||
const styledNameUnChecked = name.Clone().SetStyle("font-size:large;padding-left:1.25rem");
|
||||
|
||||
const zoomStatus =
|
||||
new Toggle(
|
||||
undefined,
|
||||
Translations.t.general.layerSelection.zoomInToSeeThisLayer.Clone()
|
||||
Translations.t.general.layerSelection.zoomInToSeeThisLayer
|
||||
.SetClass("alert")
|
||||
.SetStyle("display: block ruby;width:min-content;"),
|
||||
State.state.locationControl.map(location => location.zoom >= filteredLayer.layerDef.minzoom)
|
||||
|
|
|
@ -30,7 +30,8 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
|
|||
super(
|
||||
() => layoutToUse.title.Clone(),
|
||||
() => FullWelcomePaneWithTabs.GenerateContents(state, currentTab, isShown),
|
||||
undefined, isShown
|
||||
"welcome",
|
||||
isShown
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
|
|||
{header: `<img src='${state.layoutToUse.icon}'>`, content: welcome},
|
||||
{
|
||||
header: Svg.osm_logo_img,
|
||||
content: Translations.t.general.openStreetMapIntro.Clone().SetClass("link-underline")
|
||||
content: Translations.t.general.openStreetMapIntro.SetClass("link-underline")
|
||||
},
|
||||
|
||||
]
|
||||
|
@ -63,7 +64,7 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
|
|||
header: Svg.add_img,
|
||||
content:
|
||||
new Combine([
|
||||
Translations.t.general.morescreen.intro.Clone(),
|
||||
Translations.t.general.morescreen.intro,
|
||||
new MoreScreen(state)
|
||||
]).SetClass("flex flex-col")
|
||||
});
|
||||
|
@ -85,7 +86,7 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
|
|||
|
||||
tabsWithAboutMc.push({
|
||||
header: Svg.help,
|
||||
content: new Combine([Translations.t.general.aboutMapcomplete.Clone()
|
||||
content: new Combine([Translations.t.general.aboutMapcomplete
|
||||
.Subs({"osmcha_link": Utils.OsmChaLinkFor(7)}), "<br/>Version " + Constants.vNumber])
|
||||
.SetClass("link-underline")
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@ export default class LeftControls extends Combine {
|
|||
featureSwitchEnableExport: UIEventSource<boolean>,
|
||||
featureSwitchExportAsPdf: UIEventSource<boolean>,
|
||||
filteredLayers: UIEventSource<FilteredLayer[]>,
|
||||
featureSwitchFilter: UIEventSource<boolean>,
|
||||
selectedElement: UIEventSource<any>
|
||||
featureSwitchFilter: UIEventSource<boolean>
|
||||
},
|
||||
guiState: {
|
||||
downloadControlIsOpened: UIEventSource<boolean>,
|
||||
filterViewIsOpened: UIEventSource<boolean>,
|
||||
copyrightViewIsOpened: UIEventSource<boolean>
|
||||
}) {
|
||||
|
||||
const toggledCopyright = new ScrollableFullScreen(
|
||||
|
@ -41,7 +41,8 @@ export default class LeftControls extends Combine {
|
|||
state.layoutToUse,
|
||||
new ContributorCount(state).Contributors
|
||||
),
|
||||
undefined
|
||||
"copyright",
|
||||
guiState.copyrightViewIsOpened
|
||||
);
|
||||
|
||||
const copyrightButton = new Toggle(
|
||||
|
@ -49,8 +50,7 @@ export default class LeftControls extends Combine {
|
|||
new MapControlButton(Svg.copyright_svg())
|
||||
.onClick(() => toggledCopyright.isShown.setData(true)),
|
||||
toggledCopyright.isShown
|
||||
)
|
||||
.SetClass("p-0.5");
|
||||
).SetClass("p-0.5");
|
||||
|
||||
const toggledDownload = new Toggle(
|
||||
new AllDownloads(
|
||||
|
@ -73,11 +73,11 @@ export default class LeftControls extends Combine {
|
|||
() => Translations.t.general.layerSelection.title.Clone(),
|
||||
() =>
|
||||
new FilterView(state.filteredLayers, state.overlayToggles).SetClass(
|
||||
"block p-1 rounded-full"
|
||||
"block p-1"
|
||||
),
|
||||
undefined,
|
||||
"filters",
|
||||
guiState.filterViewIsOpened
|
||||
),
|
||||
).SetClass("rounded-lg"),
|
||||
new MapControlButton(Svg.filter_svg())
|
||||
.onClick(() => guiState.filterViewIsOpened.setData(true)),
|
||||
guiState.filterViewIsOpened
|
||||
|
@ -90,18 +90,6 @@ export default class LeftControls extends Combine {
|
|||
);
|
||||
|
||||
|
||||
state.locationControl.addCallback(() => {
|
||||
// Close the layer selection when the map is moved
|
||||
toggledDownload.isEnabled.setData(false);
|
||||
copyrightButton.isEnabled.setData(false);
|
||||
toggledFilter.isEnabled.setData(false);
|
||||
});
|
||||
|
||||
state.selectedElement.addCallbackAndRunD((_) => {
|
||||
toggledDownload.isEnabled.setData(false);
|
||||
copyrightButton.isEnabled.setData(false);
|
||||
toggledFilter.isEnabled.setData(false);
|
||||
});
|
||||
super([filterButton,
|
||||
downloadButtonn,
|
||||
copyrightButton])
|
||||
|
|
|
@ -6,8 +6,6 @@ import {SubtleButton} from "../Base/SubtleButton";
|
|||
import Translations from "../i18n/Translations";
|
||||
import * as personal from "../../assets/themes/personal/personal.json"
|
||||
import Constants from "../../Models/Constants";
|
||||
import LanguagePicker from "../LanguagePicker";
|
||||
import IndexText from "./IndexText";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
|
@ -201,14 +199,13 @@ export default class MoreScreen extends Combine {
|
|||
}) ?? new UIEventSource<string>(`${linkPrefix}${linkSuffix}`)
|
||||
|
||||
|
||||
let description = Translations.WT(layout.shortDescription).Clone();
|
||||
return new SubtleButton(layout.icon,
|
||||
new Combine([
|
||||
`<dt class='text-lg leading-6 font-medium text-gray-900 group-hover:text-blue-800'>`,
|
||||
Translations.WT(layout.title).Clone(),
|
||||
Translations.WT(layout.title),
|
||||
`</dt>`,
|
||||
`<dd class='mt-1 text-base text-gray-500 group-hover:text-blue-900 overflow-ellipsis'>`,
|
||||
description.Clone().SetClass("subtle") ?? "",
|
||||
Translations.WT(layout.shortDescription)?.SetClass("subtle") ?? "",
|
||||
`</dd>`,
|
||||
]), {url: linkText, newTab: false});
|
||||
}
|
||||
|
|
|
@ -113,9 +113,9 @@ export default class SimpleAddUI extends Toggle {
|
|||
new Toggle(
|
||||
new Toggle(
|
||||
new Toggle(
|
||||
addUi,
|
||||
Translations.t.general.add.stillLoading.Clone().SetClass("alert"),
|
||||
state.featurePipeline.somethingLoaded
|
||||
addUi,
|
||||
state.featurePipeline.runningQuery
|
||||
),
|
||||
Translations.t.general.add.zoomInFurther.Clone().SetClass("alert"),
|
||||
state.locationControl.map(loc => loc.zoom >= Constants.userJourney.minZoomLevelToAddNewPoints)
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import Translations from "../i18n/Translations";
|
||||
|
||||
/**
|
||||
* Shows that 'images are uploading', 'all images are uploaded' as relevant...
|
||||
*/
|
||||
export default class UploadFlowStateUI extends VariableUiElement {
|
||||
|
||||
|
||||
constructor(queue: UIEventSource<string[]>, failed: UIEventSource<string[]>, success: UIEventSource<string[]>) {
|
||||
const t = Translations.t.image;
|
||||
|
||||
super(
|
||||
queue.map(queue => {
|
||||
const failedReasons = failed.data
|
||||
const successCount = success.data.length
|
||||
const pendingCount = queue.length - successCount - failedReasons.length;
|
||||
|
||||
let stateMessages: BaseUIElement[] = []
|
||||
|
||||
if (pendingCount == 1) {
|
||||
stateMessages.push(t.uploadingPicture.Clone().SetClass("alert"))
|
||||
}
|
||||
if (pendingCount > 1) {
|
||||
stateMessages.push(t.uploadingMultiple.Subs({count: "" + pendingCount}).SetClass("alert"))
|
||||
}
|
||||
if (failedReasons.length > 0) {
|
||||
stateMessages.push(t.uploadFailed.Clone().SetClass("alert"))
|
||||
}
|
||||
if (successCount > 0 && pendingCount == 0) {
|
||||
stateMessages.push(t.uploadDone.SetClass("thanks"))
|
||||
}
|
||||
|
||||
stateMessages.forEach(msg => msg.SetStyle("display: block ruby"))
|
||||
|
||||
return stateMessages
|
||||
}, [failed, success])
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
155
UI/DefaultGUI.ts
155
UI/DefaultGUI.ts
|
@ -23,46 +23,74 @@ import ScrollableFullScreen from "./Base/ScrollableFullScreen";
|
|||
import Translations from "./i18n/Translations";
|
||||
import SimpleAddUI from "./BigComponents/SimpleAddUI";
|
||||
import StrayClickHandler from "../Logic/Actors/StrayClickHandler";
|
||||
import Lazy from "./Base/Lazy";
|
||||
|
||||
export class DefaultGuiState {
|
||||
public readonly welcomeMessageIsOpened;
|
||||
public readonly welcomeMessageIsOpened : UIEventSource<boolean>;
|
||||
public readonly downloadControlIsOpened: UIEventSource<boolean>;
|
||||
public readonly filterViewIsOpened: UIEventSource<boolean>;
|
||||
public readonly welcomeMessageOpenedTab
|
||||
public readonly copyrightViewIsOpened: UIEventSource<boolean>;
|
||||
public readonly welcomeMessageOpenedTab: UIEventSource<number>
|
||||
public readonly allFullScreenStates: UIEventSource<boolean>[] = []
|
||||
|
||||
constructor() {
|
||||
this.filterViewIsOpened = QueryParameters.GetQueryParameter(
|
||||
"filter-toggle",
|
||||
"false",
|
||||
"Whether or not the filter view is shown"
|
||||
).map<boolean>(
|
||||
(str) => str !== "false",
|
||||
[],
|
||||
(b) => "" + b
|
||||
);
|
||||
this.welcomeMessageIsOpened = new UIEventSource<boolean>(Hash.hash.data === undefined ||
|
||||
Hash.hash.data === "" ||
|
||||
Hash.hash.data == "welcome");
|
||||
|
||||
this.welcomeMessageOpenedTab = QueryParameters.GetQueryParameter(
|
||||
|
||||
|
||||
this.welcomeMessageOpenedTab = UIEventSource.asFloat(QueryParameters.GetQueryParameter(
|
||||
"tab",
|
||||
"0",
|
||||
`The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`
|
||||
).map<number>(
|
||||
(str) => (isNaN(Number(str)) ? 0 : Number(str)),
|
||||
[],
|
||||
(n) => "" + n
|
||||
);
|
||||
this.downloadControlIsOpened =
|
||||
QueryParameters.GetQueryParameter(
|
||||
));
|
||||
this.welcomeMessageIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||
"welcome-control-toggle",
|
||||
"false",
|
||||
"Whether or not the welcome panel is shown"
|
||||
)
|
||||
this.downloadControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||
"download-control-toggle",
|
||||
"false",
|
||||
"Whether or not the download panel is shown"
|
||||
).map<boolean>(
|
||||
(str) => str !== "false",
|
||||
[],
|
||||
(b) => "" + b
|
||||
);
|
||||
)
|
||||
this.filterViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||
"filter-toggle",
|
||||
"false",
|
||||
"Whether or not the filter view is shown"
|
||||
)
|
||||
this.copyrightViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||
"copyright-toggle",
|
||||
"false",
|
||||
"Whether or not the copyright view is shown"
|
||||
)
|
||||
if(Hash.hash.data === "download"){
|
||||
this.downloadControlIsOpened.setData(true)
|
||||
}
|
||||
if(Hash.hash.data === "filter"){
|
||||
this.filterViewIsOpened.setData(true)
|
||||
}
|
||||
if(Hash.hash.data === "copyright"){
|
||||
this.copyrightViewIsOpened.setData(true)
|
||||
}
|
||||
if(Hash.hash.data === "" || Hash.hash.data === undefined || Hash.hash.data === "welcome"){
|
||||
this.welcomeMessageIsOpened.setData(true)
|
||||
}
|
||||
|
||||
this.allFullScreenStates.push(this.downloadControlIsOpened, this.filterViewIsOpened, this.copyrightViewIsOpened, this.welcomeMessageIsOpened)
|
||||
|
||||
for (let i = 0; i < this.allFullScreenStates.length; i++){
|
||||
const fullScreenState = this.allFullScreenStates[i];
|
||||
for (let j = 0; j < this.allFullScreenStates.length; j++){
|
||||
if(i == j){
|
||||
continue
|
||||
}
|
||||
const otherState = this.allFullScreenStates[j];
|
||||
fullScreenState.addCallbackAndRunD(isOpened => {
|
||||
if(isOpened){
|
||||
otherState.setData(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -81,12 +109,22 @@ export default class DefaultGUI {
|
|||
constructor(state: FeaturePipelineState, guiState: DefaultGuiState) {
|
||||
this.state = state;
|
||||
this._guiState = guiState;
|
||||
const self = this;
|
||||
|
||||
if (state.layoutToUse.customCss !== undefined) {
|
||||
Utils.LoadCustomCss(state.layoutToUse.customCss);
|
||||
}
|
||||
|
||||
|
||||
this.SetupUIElements();
|
||||
this.SetupMap()
|
||||
|
||||
}
|
||||
|
||||
|
||||
private SetupMap(){
|
||||
const state = this.state;
|
||||
const guiState = this._guiState;
|
||||
|
||||
// Attach the map
|
||||
state.mainMapObject.SetClass("w-full h-full")
|
||||
.AttachTo("leafletDiv")
|
||||
|
@ -96,8 +134,28 @@ export default class DefaultGUI {
|
|||
state
|
||||
)
|
||||
|
||||
this.InitWelcomeMessage();
|
||||
|
||||
new ShowDataLayer({
|
||||
leafletMap: state.leafletMap,
|
||||
layerToShow: AllKnownLayers.sharedLayers.get("home_location"),
|
||||
features: state.homeLocation,
|
||||
enablePopups: false,
|
||||
})
|
||||
|
||||
state.leafletMap.addCallbackAndRunD(_ => {
|
||||
// Lets assume that all showDataLayers are initialized at this point
|
||||
state.selectedElement.ping()
|
||||
State.state.locationControl.ping();
|
||||
return true;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private SetupUIElements(){
|
||||
const state = this.state;
|
||||
const guiState = this._guiState;
|
||||
|
||||
const self =this
|
||||
Toggle.If(state.featureSwitchUserbadge,
|
||||
() => new UserBadge(state)
|
||||
).AttachTo("userbadge")
|
||||
|
@ -119,36 +177,37 @@ export default class DefaultGUI {
|
|||
|
||||
}
|
||||
|
||||
new Toggle(self.InitWelcomeMessage(),
|
||||
Toggle.If(state.featureSwitchIframePopoutEnabled, iframePopout),
|
||||
new Toggle(new Lazy(() => self.InitWelcomeMessage()),
|
||||
Toggle.If(state.featureSwitchIframePopoutEnabled, iframePopout),
|
||||
state.featureSwitchWelcomeMessage
|
||||
).AttachTo("messagesbox");
|
||||
|
||||
|
||||
new LeftControls(state, guiState).AttachTo("bottom-left");
|
||||
new RightControls(state).AttachTo("bottom-right");
|
||||
State.state.locationControl.ping();
|
||||
|
||||
new CenterMessageBox(state).AttachTo("centermessage");
|
||||
document
|
||||
.getElementById("centermessage")
|
||||
.classList.add("pointer-events-none");
|
||||
|
||||
|
||||
new ShowDataLayer({
|
||||
leafletMap: state.leafletMap,
|
||||
layerToShow: AllKnownLayers.sharedLayers.get("home_location"),
|
||||
features: state.homeLocation,
|
||||
enablePopups: false,
|
||||
})
|
||||
|
||||
state.leafletMap.addCallbackAndRunD(_ => {
|
||||
// Lets assume that all showDataLayers are initialized at this point
|
||||
state.selectedElement.ping()
|
||||
return true;
|
||||
})
|
||||
|
||||
// We have to ping the welcomeMessageIsOpened and other isOpened-stuff to activate the FullScreenMessage if needed
|
||||
for (const state of guiState.allFullScreenStates) {
|
||||
if(state.data){
|
||||
state.ping()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* At last, if the map moves or an element is selected, we close all the panels just as well
|
||||
*/
|
||||
|
||||
state.selectedElement.addCallbackAndRunD((_) => {
|
||||
guiState.allFullScreenStates.forEach(s => s.setData(false))
|
||||
});
|
||||
}
|
||||
|
||||
private InitWelcomeMessage() {
|
||||
private InitWelcomeMessage() : BaseUIElement{
|
||||
const isOpened = this._guiState.welcomeMessageIsOpened
|
||||
const fullOptions = new FullWelcomePaneWithTabs(isOpened, this._guiState.welcomeMessageOpenedTab, this.state);
|
||||
|
||||
|
@ -180,7 +239,7 @@ export default class DefaultGUI {
|
|||
|
||||
public setupClickDialogOnMap(filterViewIsOpened: UIEventSource<boolean>, state: FeaturePipelineState) {
|
||||
|
||||
function setup(){
|
||||
function setup() {
|
||||
let presetCount = 0;
|
||||
for (const layer of state.layoutToUse.layers) {
|
||||
for (const preset of layer.presets) {
|
||||
|
|
|
@ -9,7 +9,9 @@ import ImageProvider from "../../Logic/ImageProviders/ImageProvider";
|
|||
|
||||
export class ImageCarousel extends Toggle {
|
||||
|
||||
constructor(images: UIEventSource<{ key: string, url: string, provider: ImageProvider }[]>, tags: UIEventSource<any>) {
|
||||
constructor(images: UIEventSource<{ key: string, url: string, provider: ImageProvider }[]>,
|
||||
tags: UIEventSource<any>,
|
||||
keys: string[]) {
|
||||
const uiElements = images.map((imageURLS: { key: string, url: string, provider: ImageProvider }[]) => {
|
||||
const uiElements: BaseUIElement[] = [];
|
||||
for (const url of imageURLS) {
|
||||
|
|
|
@ -9,14 +9,23 @@ import LicensePicker from "../BigComponents/LicensePicker";
|
|||
import Toggle from "../Input/Toggle";
|
||||
import FileSelectorButton from "../Input/FileSelectorButton";
|
||||
import ImgurUploader from "../../Logic/ImageProviders/ImgurUploader";
|
||||
import UploadFlowStateUI from "../BigComponents/UploadFlowStateUI";
|
||||
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
|
||||
export class ImageUploadFlow extends Toggle {
|
||||
|
||||
|
||||
private static readonly uploadCountsPerId = new Map<string, UIEventSource<number>>()
|
||||
|
||||
constructor(tagsSource: UIEventSource<any>, imagePrefix: string = "image", text: string = undefined) {
|
||||
const perId = ImageUploadFlow.uploadCountsPerId
|
||||
const id = tagsSource.data.id
|
||||
if(!perId.has(id)){
|
||||
perId.set(id, new UIEventSource<number>(0))
|
||||
}
|
||||
const uploadedCount = perId.get(id)
|
||||
const uploader = new ImgurUploader(url => {
|
||||
// A file was uploaded - we add it to the tags of the object
|
||||
|
||||
|
@ -30,7 +39,9 @@ export class ImageUploadFlow extends Toggle {
|
|||
key = imagePrefix + ":" + freeIndex;
|
||||
}
|
||||
console.log("Adding image:" + key, url);
|
||||
Promise.resolve(State.state.changes
|
||||
uploadedCount.data ++
|
||||
uploadedCount.ping()
|
||||
Promise.resolve(State.state.changes
|
||||
.applyAction(new ChangeTagAction(
|
||||
tags.id, new Tag(key, url), tagsSource.data,
|
||||
{
|
||||
|
@ -40,10 +51,6 @@ export class ImageUploadFlow extends Toggle {
|
|||
)))
|
||||
})
|
||||
|
||||
uploader.queue.addCallbackD(q => console.log("Image upload queue is ", q))
|
||||
uploader.failed.addCallbackD(q => console.log("Image upload fail list is ", q))
|
||||
uploader.success.addCallbackD(q => console.log("Image upload success list is ", q))
|
||||
|
||||
const licensePicker = new LicensePicker()
|
||||
|
||||
const t = Translations.t.image;
|
||||
|
@ -105,10 +112,33 @@ export class ImageUploadFlow extends Toggle {
|
|||
})
|
||||
|
||||
|
||||
const uploadStateUi = new UploadFlowStateUI(uploader.queue, uploader.failed, uploader.success)
|
||||
|
||||
const uploadFlow: BaseUIElement = new Combine([
|
||||
uploadStateUi,
|
||||
new VariableUiElement(uploader.queue.map(q => q.length).map(l => {
|
||||
if(l == 0){
|
||||
return undefined;
|
||||
}
|
||||
if(l == 1){
|
||||
return t.uploadingPicture.Clone().SetClass("alert")
|
||||
}else{
|
||||
return t.uploadingMultiple.Subs({count: "" + l}).SetClass("alert")
|
||||
}
|
||||
})),
|
||||
new VariableUiElement(uploader.failed.map(q => q.length).map(l => {
|
||||
if(l==0){
|
||||
return undefined
|
||||
}
|
||||
return t.uploadFailed.Clone().SetClass("alert");
|
||||
})),
|
||||
new VariableUiElement(uploadedCount.map(l => {
|
||||
if(l == 0){
|
||||
return undefined;
|
||||
}
|
||||
if(l == 1){
|
||||
return t.uploadDone.Clone().SetClass("thanks");
|
||||
}
|
||||
return t.uploadMultipleDone.Subs({count: l}).SetClass("thanks")
|
||||
})),
|
||||
|
||||
fileSelector,
|
||||
Translations.t.image.respectPrivacy.Clone().SetStyle("font-size:small;"),
|
||||
licensePicker
|
||||
|
|
|
@ -27,7 +27,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
) {
|
||||
super(() => FeatureInfoBox.GenerateTitleBar(tags, layerConfig),
|
||||
() => FeatureInfoBox.GenerateContent(tags, layerConfig),
|
||||
undefined);
|
||||
tags.data.id);
|
||||
|
||||
if (layerConfig === undefined) {
|
||||
throw "Undefined layerconfig";
|
||||
|
@ -73,7 +73,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
editElements.push(questionBox);
|
||||
}
|
||||
|
||||
if(layerConfig.allowMove) {
|
||||
if (layerConfig.allowMove) {
|
||||
editElements.push(
|
||||
new VariableUiElement(tags.map(tags => tags.id).map(id => {
|
||||
const feature = State.state.allElements.ContainingFeatures.get(id)
|
||||
|
@ -149,8 +149,8 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
))
|
||||
renderings.push(editors)
|
||||
|
||||
return new Combine(renderings).SetClass("block")
|
||||
|
||||
return new Combine(renderings).SetClass("block")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,6 @@ import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction";
|
|||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import MoveConfig from "../../Models/ThemeConfig/MoveConfig";
|
||||
import {ElementStorage} from "../../Logic/ElementStorage";
|
||||
import ValidatedTextField from "../Input/ValidatedTextField";
|
||||
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
|
||||
|
||||
interface MoveReason {
|
||||
|
@ -47,7 +46,7 @@ export default class MoveWizard extends Toggle {
|
|||
|
||||
const t = Translations.t.move
|
||||
const loginButton = new Toggle(
|
||||
t.loginToMove.Clone().SetClass("btn").onClick(() => state.osmConnection.AttemptLogin()),
|
||||
t.loginToMove.SetClass("btn").onClick(() => state.osmConnection.AttemptLogin()),
|
||||
undefined,
|
||||
state.featureSwitchUserbadge
|
||||
)
|
||||
|
@ -55,8 +54,8 @@ export default class MoveWizard extends Toggle {
|
|||
const reasons: MoveReason[] = []
|
||||
if (options.enableRelocation) {
|
||||
reasons.push({
|
||||
text: t.reasons.reasonRelocation.Clone(),
|
||||
invitingText: t.inviteToMove.reasonRelocation.Clone(),
|
||||
text: t.reasons.reasonRelocation,
|
||||
invitingText: t.inviteToMove.reasonRelocation,
|
||||
icon: Svg.relocation_svg(),
|
||||
changesetCommentValue: "relocated",
|
||||
lockBounds: false,
|
||||
|
@ -67,7 +66,7 @@ export default class MoveWizard extends Toggle {
|
|||
}
|
||||
if(options.enableImproveAccuracy){
|
||||
reasons.push({
|
||||
text: t.reasons.reasonInaccurate.Clone(),
|
||||
text: t.reasons.reasonInaccurate,
|
||||
invitingText: t.inviteToMove.reasonInaccurate,
|
||||
icon: Svg.crosshair_svg(),
|
||||
changesetCommentValue: "improve_accuracy",
|
||||
|
@ -86,14 +85,14 @@ export default class MoveWizard extends Toggle {
|
|||
moveReason.setData(reason)
|
||||
moveButton = new SubtleButton(
|
||||
reason.icon.SetStyle("height: 1.5rem; width: auto;"),
|
||||
Translations.WT(reason.invitingText).Clone()
|
||||
Translations.WT(reason.invitingText)
|
||||
).onClick(() => {
|
||||
currentStep.setData("pick_location")
|
||||
})
|
||||
}else{
|
||||
moveButton = new SubtleButton(
|
||||
Svg.move_ui().SetStyle("height: 1.5rem; width: auto"),
|
||||
t.inviteToMove.generic.Clone()
|
||||
t.inviteToMove.generic
|
||||
).onClick(() => {
|
||||
currentStep.setData("reason")
|
||||
})
|
||||
|
@ -102,7 +101,7 @@ export default class MoveWizard extends Toggle {
|
|||
|
||||
const moveAgainButton = new SubtleButton(
|
||||
Svg.move_ui(),
|
||||
t.inviteToMoveAgain.Clone()
|
||||
t.inviteToMoveAgain
|
||||
).onClick(() => {
|
||||
currentStep.setData("reason")
|
||||
})
|
||||
|
@ -152,7 +151,7 @@ export default class MoveWizard extends Toggle {
|
|||
confirmMove.onClick(() => {
|
||||
const loc = locationInput.GetValue().data
|
||||
state.changes.applyAction(new ChangeLocationAction(featureToMove.properties.id, [loc.lon, loc.lat], {
|
||||
reason: Translations.WT(reason.text).textFor("en"),
|
||||
reason: reason.changesetCommentValue,
|
||||
theme: state.layoutToUse.id
|
||||
}))
|
||||
featureToMove.properties._lat = loc.lat
|
||||
|
@ -160,7 +159,7 @@ export default class MoveWizard extends Toggle {
|
|||
state.allElements.getEventSourceById(id).ping()
|
||||
currentStep.setData("moved")
|
||||
})
|
||||
const zoomInFurhter = t.zoomInFurther.Clone().SetClass("alert block m-6")
|
||||
const zoomInFurhter = t.zoomInFurther.SetClass("alert block m-6")
|
||||
return new Combine([
|
||||
locationInput,
|
||||
new Toggle(confirmMove, zoomInFurhter, locationInput.GetValue().map(l => l.zoom >= 19))
|
||||
|
@ -175,11 +174,11 @@ export default class MoveWizard extends Toggle {
|
|||
case "start":
|
||||
return moveButton;
|
||||
case "reason":
|
||||
return new Combine([t.whyMove.Clone().SetClass("text-lg font-bold"), selectReason, cancelButton]).SetClass(dialogClasses);
|
||||
return new Combine([t.whyMove.SetClass("text-lg font-bold"), selectReason, cancelButton]).SetClass(dialogClasses);
|
||||
case "pick_location":
|
||||
return new Combine([t.moveTitle.Clone().SetClass("text-lg font-bold"), new VariableUiElement(locationInput), cancelButton]).SetClass(dialogClasses)
|
||||
return new Combine([t.moveTitle.SetClass("text-lg font-bold"), new VariableUiElement(locationInput), cancelButton]).SetClass(dialogClasses)
|
||||
case "moved":
|
||||
return new Combine([t.pointIsMoved.Clone().SetClass("thanks"), moveAgainButton]).SetClass("flex flex-col");
|
||||
return new Combine([t.pointIsMoved.SetClass("thanks"), moveAgainButton]).SetClass("flex flex-col");
|
||||
|
||||
}
|
||||
|
||||
|
@ -196,20 +195,20 @@ export default class MoveWizard extends Toggle {
|
|||
|
||||
const moveDisallowedReason = new UIEventSource<BaseUIElement>(undefined)
|
||||
if (id.startsWith("way")) {
|
||||
moveDisallowedReason.setData(t.isWay.Clone())
|
||||
moveDisallowedReason.setData(t.isWay)
|
||||
} else if (id.startsWith("relation")) {
|
||||
moveDisallowedReason.setData(t.isRelation.Clone())
|
||||
} else {
|
||||
moveDisallowedReason.setData(t.isRelation)
|
||||
} else if(id.indexOf("-") < 0) {
|
||||
|
||||
OsmObject.DownloadReferencingWays(id).then(referencing => {
|
||||
if (referencing.length > 0) {
|
||||
console.log("Got a referencing way, move not allowed")
|
||||
moveDisallowedReason.setData(t.partOfAWay.Clone())
|
||||
moveDisallowedReason.setData(t.partOfAWay)
|
||||
}
|
||||
})
|
||||
OsmObject.DownloadReferencingRelations(id).then(partOf => {
|
||||
if(partOf.length > 0){
|
||||
moveDisallowedReason.setData(t.partOfRelation.Clone())
|
||||
if(partOf.length > 0){
|
||||
moveDisallowedReason.setData(t.partOfRelation)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -217,7 +216,7 @@ export default class MoveWizard extends Toggle {
|
|||
moveFlow,
|
||||
new Combine([
|
||||
Svg.move_not_allowed_svg().SetStyle("height: 2rem").SetClass("m-2"),
|
||||
new Combine([t.cannotBeMoved.Clone(),
|
||||
new Combine([t.cannotBeMoved,
|
||||
new VariableUiElement(moveDisallowedReason).SetClass("subtle")
|
||||
]).SetClass("flex flex-col")
|
||||
]).SetClass("flex m-2 p-2 rounded-lg bg-gray-200"),
|
||||
|
|
|
@ -27,6 +27,7 @@ import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
|
|||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import {Unit} from "../../Models/Unit";
|
||||
import VariableInputElement from "../Input/VariableInputElement";
|
||||
import Toggle from "../Input/Toggle";
|
||||
|
||||
/**
|
||||
* Shows the question element.
|
||||
|
@ -76,7 +77,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
|
||||
|
||||
const inputElement: InputElement<TagsFilter> =
|
||||
new VariableInputElement(applicableMappingsSrc.map(applicableMappings =>
|
||||
new VariableInputElement(applicableMappingsSrc.map(applicableMappings =>
|
||||
TagRenderingQuestion.GenerateInputElement(configuration, applicableMappings, applicableUnit, tags)
|
||||
))
|
||||
|
||||
|
@ -105,8 +106,11 @@ export default class TagRenderingQuestion extends Combine {
|
|||
.onClick(save)
|
||||
}
|
||||
|
||||
const saveButton = options.saveButtonConstr(inputElement.GetValue())
|
||||
|
||||
const saveButton = new Combine([
|
||||
options.saveButtonConstr(inputElement.GetValue()),
|
||||
new Toggle(Translations.t.general.testing, undefined, State.state.featureSwitchIsTesting).SetClass("alert")
|
||||
])
|
||||
|
||||
let bottomTags: BaseUIElement;
|
||||
if (options.bottomText !== undefined) {
|
||||
bottomTags = options.bottomText(inputElement.GetValue())
|
||||
|
@ -119,7 +123,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
return "";
|
||||
}
|
||||
if (tagsFilter === undefined) {
|
||||
return Translations.t.general.noTagsSelected.Clone().SetClass("subtle");
|
||||
return Translations.t.general.noTagsSelected.SetClass("subtle");
|
||||
}
|
||||
if (csCount < Constants.userJourney.tagsVisibleAndWikiLinked) {
|
||||
const tagsStr = tagsFilter.asHumanString(false, true, tags.data);
|
||||
|
@ -136,6 +140,8 @@ export default class TagRenderingQuestion extends Combine {
|
|||
options.cancelButton,
|
||||
saveButton,
|
||||
bottomTags])
|
||||
|
||||
|
||||
this.SetClass("question disable-links")
|
||||
}
|
||||
|
||||
|
@ -190,7 +196,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
applicableMappings.map((mapping, i) => {
|
||||
return {
|
||||
value: new And([mapping.if, ...allIfNotsExcept(i)]),
|
||||
shown: Translations.WT(mapping.then).Clone()
|
||||
shown: Translations.WT(mapping.then)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
@ -204,7 +210,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
|
||||
|
||||
if (inputEls.length == 0) {
|
||||
if(ff === undefined){
|
||||
if (ff === undefined) {
|
||||
throw "Error: could not generate a question: freeform and all mappings are undefined"
|
||||
}
|
||||
return ff;
|
||||
|
|
|
@ -83,15 +83,15 @@ export default class SpecialVisualizations {
|
|||
docs: "Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported: Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)",
|
||||
args: [{
|
||||
name: "image key/prefix (multiple values allowed if comma-seperated)",
|
||||
defaultValue: "image",
|
||||
defaultValue: AllImageProviders.defaultKeys.join(","),
|
||||
doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... "
|
||||
}],
|
||||
constr: (state: State, tags, args) => {
|
||||
let imagePrefixes = undefined;
|
||||
let imagePrefixes: string[] = undefined;
|
||||
if(args.length > 0){
|
||||
imagePrefixes = args;
|
||||
imagePrefixes = [].concat(...args.map(a => a.split(",")));
|
||||
}
|
||||
return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefixes), tags);
|
||||
return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefixes), tags, imagePrefixes);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -122,13 +122,13 @@ export default class WikidataPreviewBox extends VariableUiElement {
|
|||
|
||||
const els : BaseUIElement[] = []
|
||||
for (const extraProperty of WikidataPreviewBox.extraProperties) {
|
||||
let hasAllRequirements =true
|
||||
let hasAllRequirements = true
|
||||
for (const requirement of extraProperty.requires) {
|
||||
if(!wikidata.claims.has("P"+requirement.p)){
|
||||
if(!wikidata.claims?.has("P"+requirement.p)){
|
||||
hasAllRequirements = false;
|
||||
break
|
||||
}
|
||||
if(!wikidata.claims.get("P"+requirement.p).has("Q"+requirement.q)){
|
||||
if(!wikidata.claims?.get("P"+requirement.p).has("Q"+requirement.q)){
|
||||
hasAllRequirements = false;
|
||||
break
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import BaseUIElement from "../BaseUIElement";
|
|||
export default class Translations {
|
||||
|
||||
static t = AllTranslationAssets.t;
|
||||
private static wtcache = {}
|
||||
|
||||
constructor() {
|
||||
throw "Translations is static. If you want to intitialize a new translation, use the singular form"
|
||||
|
@ -45,15 +44,10 @@ export default class Translations {
|
|||
return undefined;
|
||||
}
|
||||
if (typeof (s) === "string") {
|
||||
if (Translations.wtcache[s]) {
|
||||
return Translations.wtcache[s];
|
||||
}
|
||||
const tr = new Translation({en: s});
|
||||
Translations.wtcache[s] = tr;
|
||||
return tr;
|
||||
return new Translation({en: s});
|
||||
}
|
||||
if (s instanceof Translation) {
|
||||
return s;
|
||||
return s.Clone() /* MUST CLONE HERE! */;
|
||||
}
|
||||
console.error("Trying to Translation.WT, but got ", s)
|
||||
throw "??? Not a valid translation"
|
||||
|
|
2
Utils.ts
2
Utils.ts
|
@ -330,7 +330,7 @@ export class Utils {
|
|||
return cached.promise
|
||||
}
|
||||
}
|
||||
const promise = Utils.downloadJson(url, headers)
|
||||
const promise = /*NO AWAIT as we work with the promise directly */Utils.downloadJson(url, headers)
|
||||
Utils._download_cache.set(url, {promise, timestamp: new Date().getTime()})
|
||||
return await promise
|
||||
}
|
||||
|
|
|
@ -79,16 +79,13 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg",
|
||||
"roaming": true
|
||||
},
|
||||
"badge": true
|
||||
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg"
|
||||
}
|
||||
}
|
||||
],
|
||||
"titleIcons": [
|
||||
{
|
||||
"render": "<img src='./assets/layers/bike_cleaning/bike_cleaning_icon.svg'/>",
|
||||
"roaming": true
|
||||
"render": "<img src='./assets/layers/bike_cleaning/bike_cleaning_icon.svg'/>"
|
||||
}
|
||||
],
|
||||
"tagRenderings": [
|
||||
|
@ -118,7 +115,6 @@
|
|||
"then": "The cleaning service has a fee"
|
||||
}
|
||||
],
|
||||
"roaming": true,
|
||||
"id": "bike_cleaning-service:bicycle:cleaning:charge"
|
||||
},
|
||||
{
|
||||
|
@ -146,7 +142,6 @@
|
|||
"then": "The cleaning service has a fee"
|
||||
}
|
||||
],
|
||||
"roaming": false,
|
||||
"id": "bike_cleaning-charge"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -129,8 +129,7 @@
|
|||
"titleIcons": [
|
||||
{
|
||||
"render": "<a href='https://fietsambassade.gent.be/' target='_blank'><img src='./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg'/></a>",
|
||||
"condition": "operator=De Fietsambassade Gent",
|
||||
"roaming": true
|
||||
"condition": "operator=De Fietsambassade Gent"
|
||||
},
|
||||
"defaults"
|
||||
],
|
||||
|
@ -616,16 +615,7 @@
|
|||
"level"
|
||||
],
|
||||
"icon": {
|
||||
"render": {
|
||||
"en": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"ru": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"it": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"fi": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"fr": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"pt_BR": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"de": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"pt": "./assets/layers/bike_repair_station/repair_station.svg"
|
||||
},
|
||||
"render": "./assets/layers/bike_repair_station/repair_station.svg",
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
|
|
|
@ -174,6 +174,10 @@
|
|||
"condition": "service:bicycle:diy=yes",
|
||||
"render": "<img src='./assets/layers/bike_shop/tools.svg'/>"
|
||||
},
|
||||
{
|
||||
"condition": "service:bicycle:cleaning=yes",
|
||||
"render": "<img src='./assets/layers/bike_cleaning/bike_cleaning_icon.svg'/>"
|
||||
},
|
||||
"defaults"
|
||||
],
|
||||
"description": {
|
||||
|
@ -659,6 +663,32 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": "How much does it cost to use the cleaning service?",
|
||||
"render": "Using the cleaning service costs {charge}",
|
||||
"freeform": {
|
||||
"key": "service:bicycle:cleaning:charge",
|
||||
"addExtraTags": [
|
||||
"service:bicycle:cleaning:fee=yes"
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "service:bicycle:cleaning:fee=no&service:bicycle:cleaning:charge=",
|
||||
"then": "The cleaning service is free to use"
|
||||
},
|
||||
{
|
||||
"if": "service:bicycle:cleaning:fee=no&",
|
||||
"then": "Free to use",
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "service:bicycle:cleaning:fee=yes",
|
||||
"then": "The cleaning service has a fee"
|
||||
}
|
||||
],
|
||||
"id": "bike_cleaning-service:bicycle:cleaning:charge"
|
||||
}
|
||||
],
|
||||
"presets": [
|
||||
|
@ -700,6 +730,17 @@
|
|||
"if": "service:bicycle:pump=yes",
|
||||
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg",
|
||||
"badge": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"service:bicycle:cleaning~*"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg"
|
||||
},
|
||||
"badge": true
|
||||
}
|
||||
],
|
||||
"width": {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,11 +2,7 @@
|
|||
"id": "charging_station",
|
||||
"name": {
|
||||
"en": "Charging stations",
|
||||
"it": "Stazioni di ricarica",
|
||||
"ja": "充電ステーション",
|
||||
"nb_NO": "Ladestasjoner",
|
||||
"ru": "Зарядные станции",
|
||||
"zh_Hant": "充電站"
|
||||
"nl": "Oplaadpunten"
|
||||
},
|
||||
"minzoom": 10,
|
||||
"source": {
|
||||
|
@ -22,27 +18,21 @@
|
|||
"title": {
|
||||
"render": {
|
||||
"en": "Charging station",
|
||||
"it": "Stazione di ricarica",
|
||||
"ja": "充電ステーション",
|
||||
"nb_NO": "Ladestasjon",
|
||||
"ru": "Зарядная станция",
|
||||
"zh_Hant": "充電站"
|
||||
"nl": "Oplaadpunten"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"en": "A charging station",
|
||||
"it": "Una stazione di ricarica",
|
||||
"ja": "充電ステーション",
|
||||
"nb_NO": "En ladestasjon",
|
||||
"ru": "Зарядная станция",
|
||||
"zh_Hant": "充電站"
|
||||
"nl": "Oplaadpunten"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"id": "Type",
|
||||
"#": "Allowed vehicle types",
|
||||
"question": {
|
||||
"en": "Which vehicles are allowed to charge here?"
|
||||
"en": "Which vehicles are allowed to charge here?",
|
||||
"nl": "Welke voertuigen kunnen hier opgeladen worden?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
|
@ -50,35 +40,40 @@
|
|||
"if": "bicycle=yes",
|
||||
"ifnot": "bicycle=no",
|
||||
"then": {
|
||||
"en": "<b>bicycles</b> can be charged here"
|
||||
"en": "<b>Bcycles</b> can be charged here",
|
||||
"nl": "<b>Fietsen</b> kunnen hier opgeladen worden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "motorcar=yes",
|
||||
"ifnot": "motorcar=no",
|
||||
"ifnot": "motorcar=no",
|
||||
"then": {
|
||||
"en": "<b>Cars</b> can be charged here"
|
||||
"en": "<b>Cars</b> can be charged here",
|
||||
"nl": "<b>Elektrische auto's</b> kunnen hier opgeladen worden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "scooter=yes",
|
||||
"ifnot": "scooter=no",
|
||||
"then": {
|
||||
"en": "<b>Scooters</b> can be charged here"
|
||||
"en": "<b>Scooters</b> can be charged here",
|
||||
"nl": "<b>Electrische scooters</b> (snorfiets of bromfiets) kunnen hier opgeladen worden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "hgv=yes",
|
||||
"ifnot": "hgv=no",
|
||||
"then": {
|
||||
"en": "<b>Heavy good vehicles</b> (such as trucks) can be charged here"
|
||||
"en": "<b>Heavy good vehicles</b> (such as trucks) can be charged here",
|
||||
"nl": "<b>Vrachtwagens</b> kunnen hier opgeladen worden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "bus=yes",
|
||||
"ifnot": "bus=no",
|
||||
"then": {
|
||||
"en": "<b>Buses</b> can be charged here"
|
||||
"en": "<b>Buses</b> can be charged here",
|
||||
"nl": "<b>Bussen</b> kunnen hier opgeladen worden"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -86,10 +81,12 @@
|
|||
{
|
||||
"id": "access",
|
||||
"question": {
|
||||
"en": "Who is allowed to use this charging station?"
|
||||
"en": "Who is allowed to use this charging station?",
|
||||
"nl": "Wie mag er dit oplaadpunt gebruiken?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Access is {access}"
|
||||
"en": "Access is {access}",
|
||||
"nl": "Toegang voor {access}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "access",
|
||||
|
@ -100,7 +97,10 @@
|
|||
"mappings": [
|
||||
{
|
||||
"if": "access=yes",
|
||||
"then": "Anyone can use this charging station (payment might be needed)"
|
||||
"then": {
|
||||
"en": "Anyone can use this charging station (payment might be needed)",
|
||||
"nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
|
@ -109,16 +109,25 @@
|
|||
"access=public"
|
||||
]
|
||||
},
|
||||
"then": "Anyone can use this charging station (payment might be needed)",
|
||||
"then": {
|
||||
"en": "Anyone can use this charging station (payment might be needed)",
|
||||
"nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "access=customers",
|
||||
"then": "Only customers of the place this station belongs to can use this charging station<br/><span class='subtle'>E.g. a charging station operated by hotel which is only usable by their guests</span> "
|
||||
"then": {
|
||||
"en": "Only customers of the place this station belongs to can use this charging station<br/><span class='subtle'>E.g. a charging station operated by hotel which is only usable by their guests</span>",
|
||||
"nl": "Enkel <b>klanten van de bijhorende plaats</b> mogen dit oplaadpunt gebruiken<br/><span class='subtle'>Bv. op de parking van een hotel en enkel toegankelijk voor klanten van dit hotel</span>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "access=private",
|
||||
"then": "Not accessible to the general public (e.g. only accessible to the owners, employees, ...)"
|
||||
"then": {
|
||||
"en": "Not accessible to the general public (e.g. only accessible to the owners, employees, ...)",
|
||||
"nl": "Niet toegankelijk voor het publiek <br/><span class='subtle'>Bv. enkel toegankelijk voor de eigenaar, medewerkers ,...</span> "
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -137,124 +146,8 @@
|
|||
"type": "pnat"
|
||||
}
|
||||
},
|
||||
{"id": "$$$"},
|
||||
{
|
||||
"id": "Authentication",
|
||||
"question": {
|
||||
"en": "What kind of authentication is available at the charging station?",
|
||||
"it": "Quali sono gli orari di apertura di questa stazione di ricarica?",
|
||||
"ja": "この充電ステーションはいつオープンしますか?",
|
||||
"nb_NO": "Når åpnet denne ladestasjonen?",
|
||||
"ru": "В какое время работает эта зарядная станция?",
|
||||
"zh_Hant": "何時是充電站開放使用的時間?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
{
|
||||
"if": "authentication:membership_card=yes",
|
||||
"ifnot": "authentication:membership_card=no",
|
||||
"then": {
|
||||
"en": "Authentication by a membership card"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:app=yes",
|
||||
"ifnot": "authentication:app=no",
|
||||
"then": {
|
||||
"en": "Authentication by an app"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:phone_call=yes",
|
||||
"ifnot": "authentication:phone_call=no",
|
||||
"then": {
|
||||
"en": "Authentication via phone call is available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:short_message=yes",
|
||||
"ifnot": "authentication:short_message=no",
|
||||
"then": {
|
||||
"en": "Authentication via phone call is available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:nfc=yes",
|
||||
"ifnot": "authentication:nfc=no",
|
||||
"then": {
|
||||
"en": "Authentication via NFC is available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:money_card=yes",
|
||||
"ifnot": "authentication:money_card=no",
|
||||
"then": {
|
||||
"en": "Authentication via Money Card is available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:debit_card=yes",
|
||||
"ifnot": "authentication:debit_card=no",
|
||||
"then": {
|
||||
"en": "Authentication via debit card is available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:none=yes",
|
||||
"ifnot": "authentication:none=no",
|
||||
"then": {
|
||||
"en": "Charging here is (also) possible without authentication"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Auth phone",
|
||||
"render": {
|
||||
"en": "Authenticate by calling or SMS'ing to <a href='tel:{authentication:phone_call:number}'>{authentication:phone_call:number}</a>",
|
||||
"it": "{network}",
|
||||
"ja": "{network}",
|
||||
"nb_NO": "{network}",
|
||||
"ru": "{network}",
|
||||
"zh_Hant": "{network}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What's the phone number for authentication call or SMS?",
|
||||
"it": "A quale rete appartiene questa stazione di ricarica?",
|
||||
"ja": "この充電ステーションの運営チェーンはどこですか?",
|
||||
"ru": "К какой сети относится эта станция?",
|
||||
"zh_Hant": "充電站所屬的網路是?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "authentication:phone_call:number",
|
||||
"type": "phone"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
"authentication:phone_call=yes",
|
||||
"authentication:short_message=yes"
|
||||
]
|
||||
},
|
||||
"it": {
|
||||
"0": {
|
||||
"then": "Non appartiene a una rete"
|
||||
}
|
||||
},
|
||||
"ja": {
|
||||
"0": {
|
||||
"then": "大規模な運営チェーンの一部ではない"
|
||||
}
|
||||
},
|
||||
"ru": {
|
||||
"0": {
|
||||
"then": "Не является частью более крупной сети"
|
||||
}
|
||||
},
|
||||
"zh_Hant": {
|
||||
"0": {
|
||||
"then": "不屬於大型網路"
|
||||
}
|
||||
}
|
||||
"id": "$$$"
|
||||
},
|
||||
{
|
||||
"id": "OH",
|
||||
|
@ -264,48 +157,107 @@
|
|||
"type": "opening_hours"
|
||||
},
|
||||
"question": {
|
||||
"en": "When is this charging station opened?"
|
||||
"en": "When is this charging station opened?",
|
||||
"nl": "Wanneer is dit oplaadpunt beschikbaar??"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "opening_hours=24/7",
|
||||
"then": {
|
||||
"en": "24/7 opened (including holidays)"
|
||||
"en": "24/7 opened (including holidays)",
|
||||
"nl": "24/7 open - ook tijdens vakanties"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fee/charge",
|
||||
"id": "fee",
|
||||
"question": {
|
||||
"en": "How much does one have to pay to use this charging station?",
|
||||
"nl": "Hoeveel kost het gebruik van dit oplaadpunt?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "charge",
|
||||
"addExtraTags": [
|
||||
"fee=yes"
|
||||
]
|
||||
},
|
||||
"render": {
|
||||
"en": "Using this charging station costs <b>{charge}</b>",
|
||||
"nl": "Dit oplaadpunt gebruiken kost <b>{charge}</b>"
|
||||
"en": "Does one have to pay to use this charging station?",
|
||||
"nl": "Moet men betalen om dit oplaadpunt te gebruiken?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"fee=no",
|
||||
"charge="
|
||||
"fee=no"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Gratis te gebruiken",
|
||||
"en": "Free to use"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"fee=no",
|
||||
"fee:conditional=",
|
||||
"charge=",
|
||||
"authentication:none=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Gratis te gebruiken (zonder aan te melden)",
|
||||
"en": "Free to use (without authenticating)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"fee=no",
|
||||
"fee:conditional=",
|
||||
"charge=",
|
||||
"authentication:none=no"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Gratis te gebruiken, maar aanmelden met een applicatie is verplicht",
|
||||
"en": "Free to use, but one has to authenticate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"fee=yes",
|
||||
"fee:conditional=no @ customers"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Betalend te gebruiken, maar gratis voor klanten van het bijhorende hotel/café/ziekenhuis/...",
|
||||
"en": "Paid use, but free for customers of the hotel/pub/hospital/... who operates the charging station"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"fee=yes",
|
||||
"fee:conditional="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Betalend",
|
||||
"en": "Paid use"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "charge",
|
||||
"question": {
|
||||
"en": "How much does one have to pay to use this charging station?",
|
||||
"nl": "Hoeveel moet men betalen om dit oplaadpunt te gebruiken?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Using this charging station costs <b>{charge}</b>",
|
||||
"nl": "Dit oplaadpunt gebruiken kost <b>{charge}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "charge"
|
||||
},
|
||||
"condition": "fee=yes"
|
||||
},
|
||||
{
|
||||
"id": "payment-options",
|
||||
"builtin": "payment-options",
|
||||
|
@ -336,6 +288,108 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Authentication",
|
||||
"#": "In some cases, charging is free but one has to be authenticated. We only ask for authentication if fee is no (or unset). By default one sees the questions for either the payment options or the authentication options, but normally not both",
|
||||
"question": {
|
||||
"en": "What kind of authentication is available at the charging station?",
|
||||
"nl": "Hoe kan men zich aanmelden aan dit oplaadstation?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
{
|
||||
"if": "authentication:membership_card=yes",
|
||||
"ifnot": "authentication:membership_card=no",
|
||||
"then": {
|
||||
"en": "Authentication by a membership card",
|
||||
"nl": "Aanmelden met een lidkaart is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:app=yes",
|
||||
"ifnot": "authentication:app=no",
|
||||
"then": {
|
||||
"en": "Authentication by an app",
|
||||
"nl": "Aanmelden via een applicatie is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:phone_call=yes",
|
||||
"ifnot": "authentication:phone_call=no",
|
||||
"then": {
|
||||
"en": "Authentication via phone call is available",
|
||||
"nl": "Aanmelden door te bellen naar een telefoonnummer is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:short_message=yes",
|
||||
"ifnot": "authentication:short_message=no",
|
||||
"then": {
|
||||
"en": "Authentication via SMS is available",
|
||||
"nl": "Aanmelden via SMS is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:nfc=yes",
|
||||
"ifnot": "authentication:nfc=no",
|
||||
"then": {
|
||||
"en": "Authentication via NFC is available",
|
||||
"nl": "Aanmelden via NFC is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:money_card=yes",
|
||||
"ifnot": "authentication:money_card=no",
|
||||
"then": {
|
||||
"en": "Authentication via Money Card is available",
|
||||
"nl": "Aanmelden met Money Card is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:debit_card=yes",
|
||||
"ifnot": "authentication:debit_card=no",
|
||||
"then": {
|
||||
"en": "Authentication via debit card is available",
|
||||
"nl": "Aanmelden met een betaalkaart is mogelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "authentication:none=yes",
|
||||
"ifnot": "authentication:none=no",
|
||||
"then": {
|
||||
"en": "Charging here is (also) possible without authentication",
|
||||
"nl": "Hier opladen is (ook) mogelijk zonder aan te melden"
|
||||
}
|
||||
}
|
||||
],
|
||||
"condition": {
|
||||
"or": [
|
||||
"fee=no",
|
||||
"fee="
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Auth phone",
|
||||
"render": {
|
||||
"en": "Authenticate by calling or SMS'ing to <a href='tel:{authentication:phone_call:number}'>{authentication:phone_call:number}</a>",
|
||||
"nl": "Aanmelden door te bellen of te SMS'en naar <a href='tel:{authentication:phone_call:number}'>{authentication:phone_call:number}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What's the phone number for authentication call or SMS?",
|
||||
"nl": "Wat is het telefoonnummer dat men moet bellen of SMS'en om zich aan te melden?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "authentication:phone_call:number",
|
||||
"type": "phone"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
"authentication:phone_call=yes",
|
||||
"authentication:short_message=yes"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "maxstay",
|
||||
"question": {
|
||||
|
@ -356,16 +410,21 @@
|
|||
"en": "No timelimit on leaving your vehicle here",
|
||||
"nl": "Geen maximum parkeertijd"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"condition": {
|
||||
"or": ["maxstay~*","motorcar=yes","hgv=yes","bus=yes"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Network",
|
||||
"render": {
|
||||
"en": "Part of the network <b>{network}</b>"
|
||||
"en": "Part of the network <b>{network}</b>",
|
||||
"nl": "Maakt deel uit van het <b>{network}</b>-netwerk"
|
||||
},
|
||||
"question": {
|
||||
"en": "Is this charging station part of a network?"
|
||||
"en": "Is this charging station part of a network?",
|
||||
"nl": "Is dit oplaadpunt deel van een groter netwerk?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "network"
|
||||
|
@ -374,13 +433,15 @@
|
|||
{
|
||||
"if": "no:network=yes",
|
||||
"then": {
|
||||
"en": "Not part of a bigger network"
|
||||
"en": "Not part of a bigger network",
|
||||
"nl": "Maakt geen deel uit van een groter netwerk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "network=none",
|
||||
"then": {
|
||||
"en": "Not part of a bigger network"
|
||||
"en": "Not part of a bigger network",
|
||||
"nl": "Maakt geen deel uit van een groter netwerk"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -401,10 +462,12 @@
|
|||
{
|
||||
"id": "Operator",
|
||||
"question": {
|
||||
"en": "Who is the operator of this charging station?"
|
||||
"en": "Who is the operator of this charging station?",
|
||||
"nl": "Wie beheert dit oplaadpunt?"
|
||||
},
|
||||
"render": {
|
||||
"en": "This charging station is operated by {operator}"
|
||||
"en": "This charging station is operated by {operator}",
|
||||
"nl": "Wordt beheerd door {operator}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
|
@ -417,7 +480,8 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "Actually, {operator} is the network"
|
||||
"en": "Actually, {operator} is the network",
|
||||
"nl": "Eigenlijk is {operator} het netwerk waarvan het deel uitmaakt"
|
||||
},
|
||||
"addExtraTags": [
|
||||
"operator="
|
||||
|
@ -429,10 +493,11 @@
|
|||
{
|
||||
"id": "phone",
|
||||
"question": {
|
||||
"en": "What number can one call if there is a problem with this charging station?"
|
||||
"en": "What number can one call if there is a problem with this charging station?",
|
||||
"nl": "Wat is het telefoonnummer van de beheerder van dit oplaadpunt?"
|
||||
},
|
||||
"render": {
|
||||
"en": "In case of problems, call <a href='tel:{phone}'>{phone}</a>"
|
||||
"en": "In case of problems, call <a href='tel:{phone}'>{phone}</a>", "nl": "Bij problemen, bel naar <a href='tel:{phone}'>{phone}</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "phone",
|
||||
|
@ -442,10 +507,12 @@
|
|||
{
|
||||
"id": "email",
|
||||
"question": {
|
||||
"en": "What is the email address of the operator?"
|
||||
"en": "What is the email address of the operator?",
|
||||
"nl": "Wat is het email-adres van de operator?"
|
||||
},
|
||||
"render": {
|
||||
"en": "In case of problems, send an email to <a href='mailto:{email}'>{email}</a>"
|
||||
"en": "In case of problems, send an email to <a href='mailto:{email}'>{email}</a>",
|
||||
"nl": "Bij problemen, email naar <a href='mailto:{email}'>{email}</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "email",
|
||||
|
@ -455,10 +522,12 @@
|
|||
{
|
||||
"id": "website",
|
||||
"question": {
|
||||
"en": "What is the website of the operator?"
|
||||
"en": "What is the website where one can find more information about this charging station?",
|
||||
"nl": "Wat is de website waar men meer info kan vinden over dit oplaadpunt?"
|
||||
},
|
||||
"render": {
|
||||
"en": "More info on <a href='{website}'>{website}</a>"
|
||||
"en": "More info on <a href='{website}'>{website}</a>",
|
||||
"nl": "Meer informatie op <a href='{website}'>{website}</a>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
|
@ -469,14 +538,18 @@
|
|||
{
|
||||
"id": "ref",
|
||||
"question": {
|
||||
"en": "What is the reference number of this charging station?"
|
||||
"en": "What is the reference number of this charging station?",
|
||||
"nl": "Wat is het referentienummer van dit oplaadstation?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Reference number is <b>{ref}</b>"
|
||||
"en": "Reference number is <b>{ref}</b>",
|
||||
"nl": "Het referentienummer van dit oplaadpunt is <b>{ref}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "ref"
|
||||
}
|
||||
},
|
||||
"#": "Only asked if part of a bigger network. Small operators typically don't have a reference number",
|
||||
"condition":"network!="
|
||||
},
|
||||
{
|
||||
"id": "Operational status",
|
||||
|
@ -486,7 +559,30 @@
|
|||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "operational_status=broken",
|
||||
"if": {
|
||||
"and": [
|
||||
"planned:amenity=",
|
||||
"construction:amenity=",
|
||||
"disused:amenity=",
|
||||
"operational_status=",
|
||||
"amenity=charging_station"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This charging station works",
|
||||
"nl": "Dit oplaadpunt werkt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"planned:amenity=",
|
||||
"construction:amenity=",
|
||||
"disused:amenity=",
|
||||
"operational_status=broken",
|
||||
"amenity=charging_station"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This charging station is broken",
|
||||
"nl": "Dit oplaadpunt is kapot"
|
||||
|
@ -496,6 +592,9 @@
|
|||
"if": {
|
||||
"and": [
|
||||
"planned:amenity=charging_station",
|
||||
"construction:amenity=",
|
||||
"disused:amenity=",
|
||||
"operational_status=",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
|
@ -505,9 +604,12 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"if":{
|
||||
"and": [
|
||||
"planned:amenity=",
|
||||
"construction:amenity=charging_station",
|
||||
"disused:amenity=",
|
||||
"operational_status=",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
|
@ -519,7 +621,10 @@
|
|||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"planned:amenity=",
|
||||
"construction:amenity=",
|
||||
"disused:amenity=charging_station",
|
||||
"operational_status=",
|
||||
"amenity="
|
||||
]
|
||||
},
|
||||
|
@ -527,37 +632,40 @@
|
|||
"en": "This charging station has beed permanently disabled and is not in use anymore but is still visible",
|
||||
"nl": "Dit oplaadpunt is niet meer in gebruik maar is wel nog aanwezig"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": ["amenity=charging_station","operational_status="]
|
||||
},
|
||||
"then": {
|
||||
"en": "This charging station works",
|
||||
"nl": "Dit oplaadpunt werkt"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Parking:fee",
|
||||
"question": {
|
||||
"en": "Does one have to pay a parking fee while charging?"
|
||||
"en": "Does one have to pay a parking fee while charging?",
|
||||
"nl": "Moet men parkeergeld betalen tijdens het opladen?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "parking:fee=no",
|
||||
"then": {
|
||||
"en": "No additional parking cost while charging"
|
||||
"en": "No additional parking cost while charging",
|
||||
"nl": "Geen extra parkeerkost tijdens het opladen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking:fee=yes",
|
||||
"then": {
|
||||
"en": "An additional parking fee should be paid while charging"
|
||||
"en": "An additional parking fee should be paid while charging",
|
||||
"nl": "Tijdens het opladen moet er parkeergeld betaald worden"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"condition": {
|
||||
"or": [
|
||||
"motor_vehicle=yes",
|
||||
"hgv=yes",
|
||||
"bus=yes",
|
||||
"bicycle=no",
|
||||
"bicycle="
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"icon": {
|
||||
|
@ -624,12 +732,56 @@
|
|||
"render": "#00f"
|
||||
},
|
||||
"presets": [
|
||||
{
|
||||
"tags": [
|
||||
"amenity=charging_station",
|
||||
"motorcar=no",
|
||||
"bicycle=yes",
|
||||
"socket:typee=1"
|
||||
],
|
||||
"title": {
|
||||
"en": "electrical outlet to charge e-bikes",
|
||||
"nl": "laadpunt met gewone stekker(s) <img src='./assets/layers/charging_station/TypeE.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (bedoeld om electrische fietsen op te laden)"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tags": [
|
||||
"amenity=charging_station",
|
||||
"motorcar=no",
|
||||
"bicycle=yes"
|
||||
],
|
||||
"title": {
|
||||
"en": "charging station for e-bikes",
|
||||
"nl": "oplaadpunt voor elektrische fietsen"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tags": [
|
||||
"amenity=charging_station",
|
||||
"motorcar=yes",
|
||||
"bicycle=no"
|
||||
],
|
||||
"title": {
|
||||
"en": "charging station for cars",
|
||||
"nl": "oplaadstation voor elektrische auto's"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tags": [
|
||||
"amenity=charging_station"
|
||||
],
|
||||
"title": {
|
||||
"en": "Charging station"
|
||||
"en": "charging station",
|
||||
"nl": "oplaadstation"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
|
@ -673,7 +825,8 @@
|
|||
"options": [
|
||||
{
|
||||
"question": {
|
||||
"en": "Only working charging stations"
|
||||
"en": "Only working charging stations",
|
||||
"nl": "Enkel werkende oplaadpunten"
|
||||
},
|
||||
"osmTags": {
|
||||
"and": [
|
||||
|
@ -742,12 +895,25 @@
|
|||
"en": " days",
|
||||
"nl": " day"
|
||||
},
|
||||
"humanSingular":{
|
||||
"humanSingular": {
|
||||
"en": " day",
|
||||
"nl": " dag"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"allowMove": {
|
||||
"enableRelocation": false,
|
||||
"enableImproveAccuracy": true
|
||||
},
|
||||
"deletion": {
|
||||
"softDeletionTags": {
|
||||
"and": [
|
||||
"amenity=",
|
||||
"disused:amenity=charging_station"
|
||||
]
|
||||
},
|
||||
"neededChangesets": 10
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ function run(file, protojson) {
|
|||
|
||||
const overview_question_answers = []
|
||||
const questions: (TagRenderingConfigJson & { "id": string })[] = []
|
||||
const technicalQuestions: (TagRenderingConfigJson & { "id": string })[] = []
|
||||
const filterOptions: { question: any, osmTags?: string } [] = [
|
||||
{
|
||||
question: {
|
||||
|
@ -149,7 +150,7 @@ function run(file, protojson) {
|
|||
}
|
||||
})
|
||||
|
||||
questions.push({
|
||||
technicalQuestions.push({
|
||||
"id": "voltage-" + i,
|
||||
question: {
|
||||
en: `What voltage do the plugs with ${descrWithImage_en} offer?`,
|
||||
|
@ -178,7 +179,7 @@ function run(file, protojson) {
|
|||
})
|
||||
|
||||
|
||||
questions.push({
|
||||
technicalQuestions.push({
|
||||
"id": "current-" + i,
|
||||
question: {
|
||||
en: `What current do the plugs with ${descrWithImage_en} offer?`,
|
||||
|
@ -207,7 +208,7 @@ function run(file, protojson) {
|
|||
})
|
||||
|
||||
|
||||
questions.push({
|
||||
technicalQuestions.push({
|
||||
"id": "power-output-" + i,
|
||||
question: {
|
||||
en: `What power output does a single plug of type ${descrWithImage_en} offer?`,
|
||||
|
@ -247,7 +248,8 @@ function run(file, protojson) {
|
|||
const toggles = {
|
||||
"id": "Available_charging_stations (generated)",
|
||||
"question": {
|
||||
"en": "Which charging stations are available here?"
|
||||
"en": "Which charging connections are available here?",
|
||||
"nl": "Welke aansluitingen zijn hier beschikbaar?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": overview_question_answers
|
||||
|
@ -257,7 +259,7 @@ function run(file, protojson) {
|
|||
const stringified = questions.map(q => JSON.stringify(q, null, " "))
|
||||
let protoString = readFileSync(protojson, "utf8")
|
||||
|
||||
protoString = protoString.replace("{\"id\": \"$$$\"}", stringified.join(",\n"))
|
||||
protoString = protoString.replace(/{[ \t\n]*"id"[ \t\n]*:[ \t\n]*"\$\$\$"[ \t\n]*}/, stringified.join(",\n"))
|
||||
const proto = <LayerConfigJson>JSON.parse(protoString)
|
||||
proto.tagRenderings.forEach(tr => {
|
||||
if (typeof tr === "string") {
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
},
|
||||
"description": {
|
||||
"en": "Crossings for pedestrians and cyclists",
|
||||
"nl": "Oversteekplaatsen voor voetgangers en fietsers"
|
||||
"nl": "Oversteekplaatsen voor voetgangers en fietsers",
|
||||
"de": "Übergänge für Fußgänger und Radfahrer"
|
||||
},
|
||||
"source": {
|
||||
"osmTags": {
|
||||
|
@ -21,7 +22,8 @@
|
|||
"title": {
|
||||
"render": {
|
||||
"en": "Crossing",
|
||||
"nl": "Oversteekplaats"
|
||||
"nl": "Oversteekplaats",
|
||||
"de": "Kreuzung"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -29,14 +31,16 @@
|
|||
"then": {
|
||||
"en": "Traffic signal",
|
||||
"nl": "Verkeerslicht",
|
||||
"ru": "Светофор"
|
||||
"ru": "Светофор",
|
||||
"de": "Ampel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "crossing=traffic_signals",
|
||||
"then": {
|
||||
"en": "Crossing with traffic signals",
|
||||
"nl": "Oversteektplaats met verkeerslichten"
|
||||
"nl": "Oversteektplaats met verkeerslichten",
|
||||
"de": "Kreuzung mit Ampeln"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -60,14 +64,16 @@
|
|||
{
|
||||
"title": {
|
||||
"en": "Crossing",
|
||||
"nl": "Oversteekplaats"
|
||||
"nl": "Oversteekplaats",
|
||||
"de": "Kreuzung"
|
||||
},
|
||||
"tags": [
|
||||
"highway=crossing"
|
||||
],
|
||||
"description": {
|
||||
"en": "Crossing for pedestrians and/or cyclists",
|
||||
"nl": "Oversteekplaats voor voetgangers en/of fietsers"
|
||||
"nl": "Oversteekplaats voor voetgangers en/of fietsers",
|
||||
"de": "Kreuzung für Fußgänger und/oder Radfahrer"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": [
|
||||
|
@ -81,14 +87,16 @@
|
|||
"title": {
|
||||
"en": "Traffic signal",
|
||||
"nl": "Verkeerslicht",
|
||||
"ru": "Светофор"
|
||||
"ru": "Светофор",
|
||||
"de": "Ampel"
|
||||
},
|
||||
"tags": [
|
||||
"highway=traffic_signals"
|
||||
],
|
||||
"description": {
|
||||
"en": "Traffic signal on a road",
|
||||
"nl": "Verkeerslicht op een weg"
|
||||
"nl": "Verkeerslicht op een weg",
|
||||
"de": "Ampel an einer Straße"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": [
|
||||
|
@ -104,7 +112,8 @@
|
|||
"id": "crossing-type",
|
||||
"question": {
|
||||
"en": "What kind of crossing is this?",
|
||||
"nl": "Wat voor oversteekplaats is dit?"
|
||||
"nl": "Wat voor oversteekplaats is dit?",
|
||||
"de": "Was ist das für eine Kreuzung?"
|
||||
},
|
||||
"condition": "highway=crossing",
|
||||
"mappings": [
|
||||
|
@ -112,21 +121,24 @@
|
|||
"if": "crossing=uncontrolled",
|
||||
"then": {
|
||||
"en": "Crossing, without traffic lights",
|
||||
"nl": "Oversteekplaats, zonder verkeerslichten"
|
||||
"nl": "Oversteekplaats, zonder verkeerslichten",
|
||||
"de": "Kreuzungen ohne Ampeln"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "crossing=traffic_signals",
|
||||
"then": {
|
||||
"en": "Crossing with traffic signals",
|
||||
"nl": "Oversteekplaats met verkeerslichten"
|
||||
"nl": "Oversteekplaats met verkeerslichten",
|
||||
"de": "Kreuzungen mit Ampeln"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "crossing=zebra",
|
||||
"then": {
|
||||
"en": "Zebra crossing",
|
||||
"nl": "Zebrapad"
|
||||
"nl": "Zebrapad",
|
||||
"de": "Zebrastreifen"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -136,7 +148,8 @@
|
|||
"id": "crossing-is-zebra",
|
||||
"question": {
|
||||
"en": "Is this is a zebra crossing?",
|
||||
"nl": "Is dit een zebrapad?"
|
||||
"nl": "Is dit een zebrapad?",
|
||||
"de": "Ist das ein Zebrastreifen?"
|
||||
},
|
||||
"condition": "crossing=uncontrolled",
|
||||
"mappings": [
|
||||
|
@ -144,14 +157,16 @@
|
|||
"if": "crossing_ref=zebra",
|
||||
"then": {
|
||||
"en": "This is a zebra crossing",
|
||||
"nl": "Dit is een zebrapad"
|
||||
"nl": "Dit is een zebrapad",
|
||||
"de": "Dies ist ein Zebrastreifen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "crossing_ref=",
|
||||
"then": {
|
||||
"en": "This is not a zebra crossing",
|
||||
"nl": "Dit is geen zebrapad"
|
||||
"nl": "Dit is geen zebrapad",
|
||||
"de": "Dies ist kein Zebrastreifen"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -160,7 +175,8 @@
|
|||
"id": "crossing-bicycle-allowed",
|
||||
"question": {
|
||||
"en": "Is this crossing also for bicycles?",
|
||||
"nl": "Is deze oversteekplaats ook voor fietsers"
|
||||
"nl": "Is deze oversteekplaats ook voor fietsers",
|
||||
"de": "Können Radfahrer diese Kreuzung nutzen?"
|
||||
},
|
||||
"condition": "highway=crossing",
|
||||
"mappings": [
|
||||
|
@ -168,14 +184,16 @@
|
|||
"if": "bicycle=yes",
|
||||
"then": {
|
||||
"en": "A cyclist can use this crossing",
|
||||
"nl": "Een fietser kan deze oversteekplaats gebruiken"
|
||||
"nl": "Een fietser kan deze oversteekplaats gebruiken",
|
||||
"de": "Radfahrer können diese Kreuzung nutzen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "bicycle=no",
|
||||
"then": {
|
||||
"en": "A cyclist can not use this crossing",
|
||||
"nl": "Een fietser kan deze oversteekplaats niet gebruiken"
|
||||
"nl": "Een fietser kan deze oversteekplaats niet gebruiken",
|
||||
"de": "Radfahrer können diese Kreuzung nicht nutzen"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -184,7 +202,8 @@
|
|||
"id": "crossing-has-island",
|
||||
"question": {
|
||||
"en": "Does this crossing have an island in the middle?",
|
||||
"nl": "Heeft deze oversteekplaats een verkeerseiland in het midden?"
|
||||
"nl": "Heeft deze oversteekplaats een verkeerseiland in het midden?",
|
||||
"de": "Gibt es an diesem Übergang eine Verkehrsinsel?"
|
||||
},
|
||||
"condition": "highway=crossing",
|
||||
"mappings": [
|
||||
|
@ -192,14 +211,16 @@
|
|||
"if": "crossing:island=yes",
|
||||
"then": {
|
||||
"en": "This crossing has an island in the middle",
|
||||
"nl": "Deze oversteekplaats heeft een verkeerseiland in het midden"
|
||||
"nl": "Deze oversteekplaats heeft een verkeerseiland in het midden",
|
||||
"de": "Der Übergang hat eine Verkehrsinsel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "crossing:island=no",
|
||||
"then": {
|
||||
"en": "This crossing does not have an island in the middle",
|
||||
"nl": "Deze oversteekplaats heeft geen verkeerseiland in het midden"
|
||||
"nl": "Deze oversteekplaats heeft geen verkeerseiland in het midden",
|
||||
"de": "Diese Ampel hat eine Taste, um ein grünes Signal anzufordern"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -208,7 +229,8 @@
|
|||
"id": "crossing-tactile",
|
||||
"question": {
|
||||
"en": "Does this crossing have tactile paving?",
|
||||
"nl": "Heeft deze oversteekplaats een geleidelijn?"
|
||||
"nl": "Heeft deze oversteekplaats een geleidelijn?",
|
||||
"de": "Gibt es an dieser Kreuzung ein Blindenleitsystem?"
|
||||
},
|
||||
"condition": "highway=crossing",
|
||||
"mappings": [
|
||||
|
@ -216,14 +238,16 @@
|
|||
"if": "tactile_paving=yes",
|
||||
"then": {
|
||||
"en": "This crossing has tactile paving",
|
||||
"nl": "Deze oversteekplaats heeft een geleidelijn"
|
||||
"nl": "Deze oversteekplaats heeft een geleidelijn",
|
||||
"de": "An dieser Kreuzung gibt es ein Blindenleitsystem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "tactile_paving=no",
|
||||
"then": {
|
||||
"en": "This crossing does not have tactile paving",
|
||||
"nl": "Deze oversteekplaats heeft geen geleidelijn"
|
||||
"nl": "Deze oversteekplaats heeft geen geleidelijn",
|
||||
"de": "Diese Kreuzung hat kein Blindenleitsystem"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -240,7 +264,8 @@
|
|||
"id": "crossing-button",
|
||||
"question": {
|
||||
"en": "Does this traffic light have a button to request green light?",
|
||||
"nl": "Heeft dit verkeerslicht een knop voor groen licht?"
|
||||
"nl": "Heeft dit verkeerslicht een knop voor groen licht?",
|
||||
"de": "Hat diese Ampel eine Taste, um ein grünes Signal anzufordern?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -260,7 +285,8 @@
|
|||
"if": "button_operated=no",
|
||||
"then": {
|
||||
"en": "This traffic light does not have a button to request green light",
|
||||
"nl": "Dit verkeerlicht heeft geen knop voor groen licht"
|
||||
"nl": "Dit verkeerlicht heeft geen knop voor groen licht",
|
||||
"de": "Diese Ampel hat keine Taste, um ein grünes Signal anzufordern."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -269,7 +295,8 @@
|
|||
"id": "crossing-right-turn-through-red",
|
||||
"question": {
|
||||
"en": "Can a cyclist turn right when the light is red?",
|
||||
"nl": "Mag een fietser rechtsaf slaan als het licht rood is?"
|
||||
"nl": "Mag een fietser rechtsaf slaan als het licht rood is?",
|
||||
"de": "Kann ein Radfahrer bei roter Ampel rechts abbiegen?"
|
||||
},
|
||||
"condition": "highway=traffic_signals",
|
||||
"mappings": [
|
||||
|
@ -277,7 +304,8 @@
|
|||
"if": "red_turn:right:bicycle=yes",
|
||||
"then": {
|
||||
"en": "A cyclist can turn right if the light is red <img src='./assets/layers/crossings/Belgian_road_sign_B22.svg' style='width: 3em'>",
|
||||
"nl": "Een fietser mag wel rechtsaf slaan als het licht rood is <img src='./assets/layers/crossings/Belgian_road_sign_B22.svg' style='width: 3em'>"
|
||||
"nl": "Een fietser mag wel rechtsaf slaan als het licht rood is <img src='./assets/layers/crossings/Belgian_road_sign_B22.svg' style='width: 3em'>",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel rechts abbiegen <img src='./assets/layers/crossings/Belgian_road_sign_B22.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be"
|
||||
},
|
||||
|
@ -285,7 +313,8 @@
|
|||
"if": "red_turn:right:bicycle=yes",
|
||||
"then": {
|
||||
"en": "A cyclist can turn right if the light is red",
|
||||
"nl": "Een fietser mag wel rechtsaf slaan als het licht rood is"
|
||||
"nl": "Een fietser mag wel rechtsaf slaan als het licht rood is",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel rechts abbiegen"
|
||||
},
|
||||
"hideInAnswer": "_country=be"
|
||||
},
|
||||
|
@ -293,7 +322,8 @@
|
|||
"if": "red_turn:right:bicycle=no",
|
||||
"then": {
|
||||
"en": "A cyclist can not turn right if the light is red",
|
||||
"nl": "Een fietser mag niet rechtsaf slaan als het licht rood is"
|
||||
"nl": "Een fietser mag niet rechtsaf slaan als het licht rood is",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel nicht rechts abbiegen"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -302,7 +332,8 @@
|
|||
"id": "crossing-continue-through-red",
|
||||
"question": {
|
||||
"en": "Can a cyclist go straight on when the light is red?",
|
||||
"nl": "Mag een fietser rechtdoor gaan als het licht rood is?"
|
||||
"nl": "Mag een fietser rechtdoor gaan als het licht rood is?",
|
||||
"de": "Kann ein Radfahrer bei roter Ampel geradeaus fahren?"
|
||||
},
|
||||
"condition": "highway=traffic_signals",
|
||||
"mappings": [
|
||||
|
@ -310,7 +341,8 @@
|
|||
"if": "red_turn:straight:bicycle=yes",
|
||||
"then": {
|
||||
"en": "A cyclist can go straight on if the light is red <img src='./assets/layers/crossings/Belgian_road_sign_B23.svg' style='width: 3em'>",
|
||||
"nl": "Een fietser mag wel rechtdoor gaan als het licht rood is <img src='./assets/layers/crossings/Belgian_road_sign_B23.svg' style='width: 3em'>"
|
||||
"nl": "Een fietser mag wel rechtdoor gaan als het licht rood is <img src='./assets/layers/crossings/Belgian_road_sign_B23.svg' style='width: 3em'>",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel geradeaus fahren <img src='./assets/layers/crossings/Belgian_road_sign_B23.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be"
|
||||
},
|
||||
|
@ -318,7 +350,8 @@
|
|||
"if": "red_turn:straight:bicycle=yes",
|
||||
"then": {
|
||||
"en": "A cyclist can go straight on if the light is red",
|
||||
"nl": "Een fietser mag wel rechtdoor gaan als het licht rood is"
|
||||
"nl": "Een fietser mag wel rechtdoor gaan als het licht rood is",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel geradeaus fahren"
|
||||
},
|
||||
"hideInAnswer": "_country=be"
|
||||
},
|
||||
|
@ -326,7 +359,8 @@
|
|||
"if": "red_turn:straight:bicycle=no",
|
||||
"then": {
|
||||
"en": "A cyclist can not go straight on if the light is red",
|
||||
"nl": "Een fietser mag niet rechtdoor gaan als het licht rood is"
|
||||
"nl": "Een fietser mag niet rechtdoor gaan als het licht rood is",
|
||||
"de": "Ein Radfahrer kann bei roter Ampel nicht geradeaus fahren"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"id": "cycleways_and_roads",
|
||||
"name": {
|
||||
"en": "Cycleways and roads",
|
||||
"nl": "Fietspaden, straten en wegen"
|
||||
"nl": "Fietspaden, straten en wegen",
|
||||
"de": "Radwege und Straßen"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
|
@ -60,14 +61,16 @@
|
|||
"if": "cycleway=lane",
|
||||
"then": {
|
||||
"nl": "Fietsstrook",
|
||||
"en": "Bike lane"
|
||||
"en": "Bike lane",
|
||||
"de": "Fahrradspur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway=track",
|
||||
"then": {
|
||||
"en": "Cycleway next to the road",
|
||||
"nl": "Fietsweg naast de weg"
|
||||
"nl": "Fietsweg naast de weg",
|
||||
"de": "Radweg neben der Straße"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -85,7 +88,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "What kind of cycleway is here?",
|
||||
"nl": "Wat voor fietspad is hier?"
|
||||
"nl": "Wat voor fietspad is hier?",
|
||||
"de": "Was für ein Radweg ist hier?"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
|
@ -98,35 +102,40 @@
|
|||
"if": "cycleway=shared_lane",
|
||||
"then": {
|
||||
"en": "There is a shared lane",
|
||||
"nl": "Er is een fietssuggestiestrook"
|
||||
"nl": "Er is een fietssuggestiestrook",
|
||||
"de": "Es gibt eine geteilte Fahrspur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway=lane",
|
||||
"then": {
|
||||
"en": "There is a lane next to the road (separated with paint)",
|
||||
"nl": "Er is een fietspad aangrenzend aan de weg (gescheiden met verf)"
|
||||
"nl": "Er is een fietspad aangrenzend aan de weg (gescheiden met verf)",
|
||||
"de": "Es gibt eine Spur neben der Straße (getrennt durch eine Straßenmarkierung)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway=track",
|
||||
"then": {
|
||||
"en": "There is a track, but no cycleway drawn separately from this road on the map.",
|
||||
"nl": "Er is een fietspad (los van de weg), maar geen fietspad afzonderlijk getekend naast deze weg."
|
||||
"nl": "Er is een fietspad (los van de weg), maar geen fietspad afzonderlijk getekend naast deze weg.",
|
||||
"de": "Es gibt einen Weg, aber keinen Radweg, der auf der Karte getrennt von dieser Straße eingezeichnet ist."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway=separate",
|
||||
"then": {
|
||||
"en": "There is a separately drawn cycleway",
|
||||
"nl": "Er is een apart getekend fietspad."
|
||||
"nl": "Er is een apart getekend fietspad.",
|
||||
"de": "Hier ist ein getrennter Radweg vorhanden"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway=no",
|
||||
"then": {
|
||||
"en": "There is no cycleway",
|
||||
"nl": "Er is geen fietspad aanwezig"
|
||||
"nl": "Er is geen fietspad aanwezig",
|
||||
"de": "Es gibt keinen Radweg"
|
||||
},
|
||||
"hideInAnswer": "cycleway=opposite"
|
||||
},
|
||||
|
@ -134,7 +143,8 @@
|
|||
"if": "cycleway=no",
|
||||
"then": {
|
||||
"en": "There is no cycleway",
|
||||
"nl": "Er is geen fietspad aanwezig"
|
||||
"nl": "Er is geen fietspad aanwezig",
|
||||
"de": "Es gibt keinen Radweg"
|
||||
},
|
||||
"hideInAnswer": "cycleway!=opposite",
|
||||
"addExtraTags": [
|
||||
|
@ -148,28 +158,32 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Is this street lit?",
|
||||
"nl": "Is deze weg verlicht?"
|
||||
"nl": "Is deze weg verlicht?",
|
||||
"de": "Ist diese Straße beleuchtet?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "lit=yes",
|
||||
"then": {
|
||||
"en": "This street is lit",
|
||||
"nl": "Deze weg is verlicht"
|
||||
"nl": "Deze weg is verlicht",
|
||||
"de": "Diese Straße ist beleuchtet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "lit=no",
|
||||
"then": {
|
||||
"en": "This road is not lit",
|
||||
"nl": "Deze weg is niet verlicht"
|
||||
"nl": "Deze weg is niet verlicht",
|
||||
"de": "Diese Straße ist nicht beleuchtet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "lit=sunset-sunrise",
|
||||
"then": {
|
||||
"en": "This road is lit at night",
|
||||
"nl": "Deze weg is 's nachts verlicht"
|
||||
"nl": "Deze weg is 's nachts verlicht",
|
||||
"de": "Diese Straße ist nachts beleuchtet"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -177,7 +191,8 @@
|
|||
"if": "lit=24/7",
|
||||
"then": {
|
||||
"en": "This road is lit 24/7",
|
||||
"nl": "Deze weg is 24/7 verlicht"
|
||||
"nl": "Deze weg is 24/7 verlicht",
|
||||
"de": "Diese Straße ist durchgehend beleuchtet"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -186,7 +201,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Is this a cyclestreet?",
|
||||
"nl": "Is dit een fietsstraat?"
|
||||
"nl": "Is dit een fietsstraat?",
|
||||
"de": "Ist das eine Fahrradstraße"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
|
@ -199,7 +215,8 @@
|
|||
"if": "cyclestreet=yes",
|
||||
"then": {
|
||||
"en": "This is a cyclestreet, and a 30km/h zone.",
|
||||
"nl": "Dit is een fietsstraat, en dus een 30km/h zone"
|
||||
"nl": "Dit is een fietsstraat, en dus een 30km/h zone",
|
||||
"de": "Dies ist eine Fahrradstraße in einer 30km/h Zone."
|
||||
},
|
||||
"addExtraTags": [
|
||||
"overtaking:motor_vehicle=no",
|
||||
|
@ -211,7 +228,8 @@
|
|||
"if": "cyclestreet=yes",
|
||||
"then": {
|
||||
"en": "This is a cyclestreet",
|
||||
"nl": "Dit is een fietsstraat"
|
||||
"nl": "Dit is een fietsstraat",
|
||||
"de": "Dies ist eine Fahrradstraße"
|
||||
},
|
||||
"hideInAnswer": "_country=be"
|
||||
},
|
||||
|
@ -219,7 +237,8 @@
|
|||
"if": "cyclestreet=",
|
||||
"then": {
|
||||
"en": "This is not a cyclestreet.",
|
||||
"nl": "Dit is geen fietsstraat"
|
||||
"nl": "Dit is geen fietsstraat",
|
||||
"de": "Dies ist keine Fahrradstraße."
|
||||
},
|
||||
"addExtraTags": [
|
||||
"overtaking:motor_vehicle="
|
||||
|
@ -231,7 +250,8 @@
|
|||
{
|
||||
"render": {
|
||||
"en": "The maximum speed on this road is {maxspeed} km/h",
|
||||
"nl": "De maximumsnelheid op deze weg is {maxspeed} km/u"
|
||||
"nl": "De maximumsnelheid op deze weg is {maxspeed} km/u",
|
||||
"de": "Die Höchstgeschwindigkeit auf dieser Straße beträgt {maxspeed} km/h"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "maxspeed",
|
||||
|
@ -248,48 +268,55 @@
|
|||
"if": "maxspeed=20",
|
||||
"then": {
|
||||
"en": "The maximum speed is 20 km/h",
|
||||
"nl": "De maximumsnelheid is 20 km/u"
|
||||
"nl": "De maximumsnelheid is 20 km/u",
|
||||
"de": "Die Höchstgeschwindigkeit ist 20 km/h"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "maxspeed=30",
|
||||
"then": {
|
||||
"en": "The maximum speed is 30 km/h",
|
||||
"nl": "De maximumsnelheid is 30 km/u"
|
||||
"nl": "De maximumsnelheid is 30 km/u",
|
||||
"de": "Die Höchstgeschwindigkeit ist 30 km/h"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "maxspeed=50",
|
||||
"then": {
|
||||
"en": "The maximum speed is 50 km/h",
|
||||
"nl": "De maximumsnelheid is 50 km/u"
|
||||
"nl": "De maximumsnelheid is 50 km/u",
|
||||
"de": "Die Höchstgeschwindigkeit ist 50 km/h"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "maxspeed=70",
|
||||
"then": {
|
||||
"en": "The maximum speed is 70 km/h",
|
||||
"nl": "De maximumsnelheid is 70 km/u"
|
||||
"nl": "De maximumsnelheid is 70 km/u",
|
||||
"de": "Die Höchstgeschwindigkeit ist 70 km/h"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "maxspeed=90",
|
||||
"then": {
|
||||
"en": "The maximum speed is 90 km/h",
|
||||
"nl": "De maximumsnelheid is 90 km/u"
|
||||
"nl": "De maximumsnelheid is 90 km/u",
|
||||
"de": "Die Höchstgeschwindigkeit ist 90 km/h"
|
||||
}
|
||||
}
|
||||
],
|
||||
"question": {
|
||||
"en": "What is the maximum speed in this street?",
|
||||
"nl": "Wat is de maximumsnelheid in deze straat?"
|
||||
"nl": "Wat is de maximumsnelheid in deze straat?",
|
||||
"de": "Was ist die Höchstgeschwindigkeit auf dieser Straße?"
|
||||
},
|
||||
"id": "Maxspeed (for road)"
|
||||
},
|
||||
{
|
||||
"render": {
|
||||
"en": "This cyleway is made of {cycleway:surface}",
|
||||
"nl": "Dit fietspad is gemaakt van {cycleway:surface}"
|
||||
"nl": "Dit fietspad is gemaakt van {cycleway:surface}",
|
||||
"de": "Der Radweg ist aus {cycleway:surface}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "cycleway:surface"
|
||||
|
@ -306,7 +333,8 @@
|
|||
"if": "cycleway:surface=unpaved",
|
||||
"then": {
|
||||
"en": "This cycleway is unpaved",
|
||||
"nl": "Dit fietspad is onverhard"
|
||||
"nl": "Dit fietspad is onverhard",
|
||||
"de": "Dieser Radweg hat keinen festen Belag"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -314,7 +342,8 @@
|
|||
"if": "cycleway:surface=paved",
|
||||
"then": {
|
||||
"en": "This cycleway is paved",
|
||||
"nl": "Dit fietspad is geplaveid"
|
||||
"nl": "Dit fietspad is geplaveid",
|
||||
"de": "Dieser Radweg hat einen festen Belag"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -322,28 +351,32 @@
|
|||
"if": "cycleway:surface=asphalt",
|
||||
"then": {
|
||||
"en": "This cycleway is made of asphalt",
|
||||
"nl": "Dit fietspad is gemaakt van asfalt"
|
||||
"nl": "Dit fietspad is gemaakt van asfalt",
|
||||
"de": "Der Radweg ist aus Asphalt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=paving_stones",
|
||||
"then": {
|
||||
"en": "This cycleway is made of smooth paving stones",
|
||||
"nl": "Dit fietspad is gemaakt van straatstenen"
|
||||
"nl": "Dit fietspad is gemaakt van straatstenen",
|
||||
"de": "Dieser Fahrradweg besteht aus ebenen Pflastersteinen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=concrete",
|
||||
"then": {
|
||||
"en": "This cycleway is made of concrete",
|
||||
"nl": "Dit fietspad is gemaakt van beton"
|
||||
"nl": "Dit fietspad is gemaakt van beton",
|
||||
"de": "Der Radweg ist aus Beton"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=cobblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of cobblestone (unhewn or sett)",
|
||||
"nl": "Dit fietspad is gemaakt van kasseien (natuurlijk of verwerkt)"
|
||||
"nl": "Dit fietspad is gemaakt van kasseien (natuurlijk of verwerkt)",
|
||||
"de": "Dieser Radweg besteht aus Kopfsteinpflaster"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -351,62 +384,71 @@
|
|||
"if": "cycleway:surface=unhewn_cobblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of raw, natural cobblestone",
|
||||
"nl": "Dit fietspad is gemaakt van ruwe, natuurlijke kasseien"
|
||||
"nl": "Dit fietspad is gemaakt van ruwe, natuurlijke kasseien",
|
||||
"de": "Dieser Fahrradweg besteht aus unregelmäßigem, unbehauenem Kopfsteinpflaster"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=sett",
|
||||
"then": {
|
||||
"en": "This cycleway is made of flat, square cobblestone",
|
||||
"nl": "Dit fietspad is gemaakt van vlakke, rechthoekige kasseien"
|
||||
"nl": "Dit fietspad is gemaakt van vlakke, rechthoekige kasseien",
|
||||
"de": "Dieser Fahrradweg besteht aus regelmäßigem, behauenem Kopfsteinpflaster"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=wood",
|
||||
"then": {
|
||||
"en": "This cycleway is made of wood",
|
||||
"nl": "Dit fietspad is gemaakt van hout"
|
||||
"nl": "Dit fietspad is gemaakt van hout",
|
||||
"de": "Der Radweg ist aus Holz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=gravel",
|
||||
"then": {
|
||||
"en": "This cycleway is made of gravel",
|
||||
"nl": "Dit fietspad is gemaakt van grind"
|
||||
"nl": "Dit fietspad is gemaakt van grind",
|
||||
"de": "Der Radweg ist aus Schotter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=fine_gravel",
|
||||
"then": {
|
||||
"en": "This cycleway is made of fine gravel",
|
||||
"nl": "Dit fietspad is gemaakt van fijn grind"
|
||||
"nl": "Dit fietspad is gemaakt van fijn grind",
|
||||
"de": "Dieser Radweg besteht aus feinem Schotter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=pebblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of pebblestone",
|
||||
"nl": "Dit fietspad is gemaakt van kiezelsteentjes"
|
||||
"nl": "Dit fietspad is gemaakt van kiezelsteentjes",
|
||||
"de": "Der Radweg ist aus Kies"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:surface=ground",
|
||||
"then": {
|
||||
"en": "This cycleway is made from raw ground",
|
||||
"nl": "Dit fietspad is gemaakt van aarde"
|
||||
"nl": "Dit fietspad is gemaakt van aarde",
|
||||
"de": "Dieser Radweg besteht aus Rohboden"
|
||||
}
|
||||
}
|
||||
],
|
||||
"question": {
|
||||
"en": "What is the surface of the cycleway made from?",
|
||||
"nl": "Waaruit is het oppervlak van het fietspad van gemaakt?"
|
||||
"nl": "Waaruit is het oppervlak van het fietspad van gemaakt?",
|
||||
"de": "Was ist der Belag dieses Radwegs?"
|
||||
},
|
||||
"id": "Cycleway:surface"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "What is the smoothness of this cycleway?",
|
||||
"nl": "Wat is de kwaliteit van dit fietspad?"
|
||||
"nl": "Wat is de kwaliteit van dit fietspad?",
|
||||
"de": "Wie eben ist dieser Radweg?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -420,56 +462,64 @@
|
|||
"if": "cycleway:smoothness=excellent",
|
||||
"then": {
|
||||
"en": "Usable for thin rollers: rollerblade, skateboard",
|
||||
"nl": "Geschikt voor fijne rollers: rollerblade, skateboard"
|
||||
"nl": "Geschikt voor fijne rollers: rollerblade, skateboard",
|
||||
"de": "Geeignet für dünne Rollen: Rollerblades, Skateboard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=good",
|
||||
"then": {
|
||||
"en": "Usable for thin wheels: racing bike",
|
||||
"nl": "Geschikt voor fijne wielen: racefiets"
|
||||
"nl": "Geschikt voor fijne wielen: racefiets",
|
||||
"de": "Geeignet für dünne Reifen: Rennrad"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=intermediate",
|
||||
"then": {
|
||||
"en": "Usable for normal wheels: city bike, wheelchair, scooter",
|
||||
"nl": "Geschikt voor normale wielen: stadsfiets, rolstoel, scooter"
|
||||
"nl": "Geschikt voor normale wielen: stadsfiets, rolstoel, scooter",
|
||||
"de": "Geeignet für normale Reifen: Fahrrad, Rollstuhl, Scooter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=bad",
|
||||
"then": {
|
||||
"en": "Usable for robust wheels: trekking bike, car, rickshaw",
|
||||
"nl": "Geschikt voor brede wielen: trekfiets, auto, rickshaw"
|
||||
"nl": "Geschikt voor brede wielen: trekfiets, auto, rickshaw",
|
||||
"de": "Geeignet für breite Reifen: Trekkingfahrrad, Auto, Rikscha"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=very_bad",
|
||||
"then": {
|
||||
"en": "Usable for vehicles with high clearance: light duty off-road vehicle",
|
||||
"nl": "Geschikt voor voertuigen met hoge banden: lichte terreinwagen"
|
||||
"nl": "Geschikt voor voertuigen met hoge banden: lichte terreinwagen",
|
||||
"de": "Geeignet für Fahrzeuge mit großer Bodenfreiheit: leichte Geländewagen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=horrible",
|
||||
"then": {
|
||||
"en": "Usable for off-road vehicles: heavy duty off-road vehicle",
|
||||
"nl": "Geschikt voor terreinwagens: zware terreinwagen"
|
||||
"nl": "Geschikt voor terreinwagens: zware terreinwagen",
|
||||
"de": "Geeignet für Geländefahrzeuge: schwerer Geländewagen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=very_horrible",
|
||||
"then": {
|
||||
"en": "Usable for specialized off-road vehicles: tractor, ATV",
|
||||
"nl": "Geschikt voor gespecialiseerde terreinwagens: tractor, alleterreinwagen"
|
||||
"nl": "Geschikt voor gespecialiseerde terreinwagens: tractor, alleterreinwagen",
|
||||
"de": "Geeignet für Geländefahrzeuge: Traktor, ATV"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:smoothness=impassable",
|
||||
"then": {
|
||||
"en": "Impassable / No wheeled vehicle",
|
||||
"nl": "Niet geschikt voor voertuigen met wielen"
|
||||
"nl": "Niet geschikt voor voertuigen met wielen",
|
||||
"de": "Unpassierbar / Keine bereiften Fahrzeuge"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -478,7 +528,8 @@
|
|||
{
|
||||
"render": {
|
||||
"en": "This road is made of {surface}",
|
||||
"nl": "Deze weg is gemaakt van {surface}"
|
||||
"nl": "Deze weg is gemaakt van {surface}",
|
||||
"de": "Der Radweg ist aus {surface}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "surface"
|
||||
|
@ -488,7 +539,8 @@
|
|||
"if": "surface=unpaved",
|
||||
"then": {
|
||||
"en": "This cycleway is unhardened",
|
||||
"nl": "Dit fietspad is onverhard"
|
||||
"nl": "Dit fietspad is onverhard",
|
||||
"de": "Dieser Radweg ist nicht befestigt"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -496,7 +548,8 @@
|
|||
"if": "surface=paved",
|
||||
"then": {
|
||||
"en": "This cycleway is paved",
|
||||
"nl": "Dit fietspad is geplaveid"
|
||||
"nl": "Dit fietspad is geplaveid",
|
||||
"de": "Dieser Radweg hat einen festen Belag"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -504,28 +557,32 @@
|
|||
"if": "surface=asphalt",
|
||||
"then": {
|
||||
"en": "This cycleway is made of asphalt",
|
||||
"nl": "Dit fietspad is gemaakt van asfalt"
|
||||
"nl": "Dit fietspad is gemaakt van asfalt",
|
||||
"de": "Der Radweg ist aus Asphalt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=paving_stones",
|
||||
"then": {
|
||||
"en": "This cycleway is made of smooth paving stones",
|
||||
"nl": "Dit fietspad is gemaakt van straatstenen"
|
||||
"nl": "Dit fietspad is gemaakt van straatstenen",
|
||||
"de": "Dieser Fahrradweg besteht aus ebenen Pflastersteinen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=concrete",
|
||||
"then": {
|
||||
"en": "This cycleway is made of concrete",
|
||||
"nl": "Dit fietspad is gemaakt van beton"
|
||||
"nl": "Dit fietspad is gemaakt van beton",
|
||||
"de": "Der Radweg ist aus Beton"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=cobblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of cobblestone (unhewn or sett)",
|
||||
"nl": "Dit fietspad is gemaakt van kasseien (natuurlijk of verwerkt)"
|
||||
"nl": "Dit fietspad is gemaakt van kasseien (natuurlijk of verwerkt)",
|
||||
"de": "Dieser Radweg besteht aus Kopfsteinpflaster"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -533,62 +590,71 @@
|
|||
"if": "surface=unhewn_cobblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of raw, natural cobblestone",
|
||||
"nl": "Dit fietspad is gemaakt van ruwe, natuurlijke kasseien"
|
||||
"nl": "Dit fietspad is gemaakt van ruwe, natuurlijke kasseien",
|
||||
"de": "Dieser Fahrradweg besteht aus unregelmäßigem, unbehauenem Kopfsteinpflaster"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=sett",
|
||||
"then": {
|
||||
"en": "This cycleway is made of flat, square cobblestone",
|
||||
"nl": "Dit fietspad is gemaakt van vlakke, rechthoekige kasseien"
|
||||
"nl": "Dit fietspad is gemaakt van vlakke, rechthoekige kasseien",
|
||||
"de": "Dieser Fahrradweg besteht aus regelmäßigem, behauenem Kopfsteinpflaster"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=wood",
|
||||
"then": {
|
||||
"en": "This cycleway is made of wood",
|
||||
"nl": "Dit fietspad is gemaakt van hout"
|
||||
"nl": "Dit fietspad is gemaakt van hout",
|
||||
"de": "Der Radweg ist aus Holz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=gravel",
|
||||
"then": {
|
||||
"en": "This cycleway is made of gravel",
|
||||
"nl": "Dit fietspad is gemaakt van grind"
|
||||
"nl": "Dit fietspad is gemaakt van grind",
|
||||
"de": "Der Radweg ist aus Schotter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=fine_gravel",
|
||||
"then": {
|
||||
"en": "This cycleway is made of fine gravel",
|
||||
"nl": "Dit fietspad is gemaakt van fijn grind"
|
||||
"nl": "Dit fietspad is gemaakt van fijn grind",
|
||||
"de": "Dieser Radweg besteht aus feinem Schotter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=pebblestone",
|
||||
"then": {
|
||||
"en": "This cycleway is made of pebblestone",
|
||||
"nl": "Dit fietspad is gemaakt van kiezelsteentjes"
|
||||
"nl": "Dit fietspad is gemaakt van kiezelsteentjes",
|
||||
"de": "Der Radweg ist aus Kies"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "surface=ground",
|
||||
"then": {
|
||||
"en": "This cycleway is made from raw ground",
|
||||
"nl": "Dit fietspad is gemaakt van aarde"
|
||||
"nl": "Dit fietspad is gemaakt van aarde",
|
||||
"de": "Dieser Radweg besteht aus Rohboden"
|
||||
}
|
||||
}
|
||||
],
|
||||
"question": {
|
||||
"en": "What is the surface of the street made from?",
|
||||
"nl": "Waaruit is het oppervlak van de straat gemaakt?"
|
||||
"nl": "Waaruit is het oppervlak van de straat gemaakt?",
|
||||
"de": "Was ist der Belag dieser Straße?"
|
||||
},
|
||||
"id": "Surface of the road"
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "What is the smoothness of this street?",
|
||||
"nl": "Wat is de kwaliteit van deze straat?"
|
||||
"nl": "Wat is de kwaliteit van deze straat?",
|
||||
"de": "Wie eben ist diese Straße?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -600,49 +666,57 @@
|
|||
{
|
||||
"if": "smoothness=excellent",
|
||||
"then": {
|
||||
"en": "Usable for thin rollers: rollerblade, skateboard"
|
||||
"en": "Usable for thin rollers: rollerblade, skateboard",
|
||||
"de": "Geeignet für dünne Rollen: Rollerblades, Skateboard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=good",
|
||||
"then": {
|
||||
"en": "Usable for thin wheels: racing bike"
|
||||
"en": "Usable for thin wheels: racing bike",
|
||||
"de": "Geeignet für dünne Reifen: Rennrad"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=intermediate",
|
||||
"then": {
|
||||
"en": "Usable for normal wheels: city bike, wheelchair, scooter"
|
||||
"en": "Usable for normal wheels: city bike, wheelchair, scooter",
|
||||
"de": "Geeignet für normale Reifen: Fahrrad, Rollstuhl, Scooter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=bad",
|
||||
"then": {
|
||||
"en": "Usable for robust wheels: trekking bike, car, rickshaw"
|
||||
"en": "Usable for robust wheels: trekking bike, car, rickshaw",
|
||||
"de": "Geeignet für breite Reifen: Trekkingfahrrad, Auto, Rikscha"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=very_bad",
|
||||
"then": {
|
||||
"en": "Usable for vehicles with high clearance: light duty off-road vehicle"
|
||||
"en": "Usable for vehicles with high clearance: light duty off-road vehicle",
|
||||
"de": "Geeignet für Fahrzeuge mit großer Bodenfreiheit: leichte Geländewagen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=horrible",
|
||||
"then": {
|
||||
"en": "Usable for off-road vehicles: heavy duty off-road vehicle"
|
||||
"en": "Usable for off-road vehicles: heavy duty off-road vehicle",
|
||||
"de": "Geeignet für Geländefahrzeuge: schwerer Geländewagen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=very_horrible",
|
||||
"then": {
|
||||
"en": "Usable for specialized off-road vehicles: tractor, ATV"
|
||||
"en": "Usable for specialized off-road vehicles: tractor, ATV",
|
||||
"de": "Geeignet für spezielle Geländewagen: Traktor, ATV"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "smoothness=impassable",
|
||||
"then": {
|
||||
"en": "Impassable / No wheeled vehicle"
|
||||
"en": "Impassable / No wheeled vehicle",
|
||||
"de": "Unpassierbar / Keine bereiften Fahrzeuge"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -668,8 +742,8 @@
|
|||
]
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the carriage width of this road (in meters)?",
|
||||
"nl": "Hoe breed is de rijbaan in deze straat (in meters)?"
|
||||
"en": "What is the carriage width of this road (in meters)?<br/><span class='subtle'>This is measured curb to curb and thus includes the width of parallell parking lanes</span>",
|
||||
"nl": "Hoe breed is de rijbaan in deze straat (in meters)?<br/><span class='subtle'>Dit is </span><br/><span class='subtle'>Meet dit van stoepsteen tot stoepsteen, dus inclusief een parallelle parkeerstrook</span>"
|
||||
},
|
||||
"id": "width:carriageway"
|
||||
},
|
||||
|
@ -677,7 +751,8 @@
|
|||
"id": "cycleway-lane-track-traffic-signs",
|
||||
"question": {
|
||||
"en": "What traffic sign does this cycleway have?",
|
||||
"nl": "Welk verkeersbord heeft dit fietspad?"
|
||||
"nl": "Welk verkeersbord heeft dit fietspad?",
|
||||
"de": "Welches Verkehrszeichen hat dieser Radweg?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -690,7 +765,8 @@
|
|||
"if": "cycleway:traffic_sign=BE:D7",
|
||||
"then": {
|
||||
"en": "Compulsory cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"nl": "Verplicht fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
"nl": "Verplicht fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"de": "Vorgeschriebener Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be"
|
||||
},
|
||||
|
@ -698,7 +774,8 @@
|
|||
"if": "cycleway:traffic_sign~BE:D7;.*",
|
||||
"then": {
|
||||
"en": "Compulsory cycleway (with supplementary sign)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'> ",
|
||||
"nl": "Verplicht fietspad (met onderbord)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
"nl": "Verplicht fietspad (met onderbord)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"de": "Vorgeschriebener Radweg (mit Zusatzschild)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'> "
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -706,7 +783,8 @@
|
|||
"if": "cycleway:traffic_sign=BE:D9",
|
||||
"then": {
|
||||
"en": "Segregated foot/cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>",
|
||||
"nl": "Afgescheiden voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>"
|
||||
"nl": "Afgescheiden voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>",
|
||||
"de": "Getrennter Fuß-/Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -718,7 +796,8 @@
|
|||
"if": "cycleway:traffic_sign=BE:D10",
|
||||
"then": {
|
||||
"en": "Unsegregated foot/cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>",
|
||||
"nl": "Gedeeld voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>"
|
||||
"nl": "Gedeeld voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>",
|
||||
"de": "Gemeinsamer Fuß-/Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -730,7 +809,8 @@
|
|||
"if": "cycleway:traffic_sign=none",
|
||||
"then": {
|
||||
"en": "No traffic sign present",
|
||||
"nl": "Geen verkeersbord aanwezig"
|
||||
"nl": "Geen verkeersbord aanwezig",
|
||||
"de": "Kein Verkehrsschild vorhanden"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -739,7 +819,8 @@
|
|||
"id": "cycleway-traffic-signs",
|
||||
"question": {
|
||||
"en": "What traffic sign does this cycleway have?",
|
||||
"nl": "Welk verkeersbord heeft dit fietspad?"
|
||||
"nl": "Welk verkeersbord heeft dit fietspad?",
|
||||
"de": "Welches Verkehrszeichen hat dieser Radweg?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -752,7 +833,8 @@
|
|||
"if": "traffic_sign=BE:D7",
|
||||
"then": {
|
||||
"en": "Compulsory cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"nl": "Verplicht fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
"nl": "Verplicht fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"de": "Vorgeschriebener Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -766,7 +848,8 @@
|
|||
"if": "traffic_sign~BE:D7;.*",
|
||||
"then": {
|
||||
"en": "Compulsory cycleway (with supplementary sign)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'> ",
|
||||
"nl": "Verplicht fietspad (met onderbord)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>"
|
||||
"nl": "Verplicht fietspad (met onderbord)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'>",
|
||||
"de": "Vorgeschriebener Radweg (mit Zusatzschild)<br><img src='./assets/themes/cycle_infra/Belgian_road_sign_D07.svg' style='width: 3em'> "
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -774,7 +857,8 @@
|
|||
"if": "traffic_sign=BE:D9",
|
||||
"then": {
|
||||
"en": "Segregated foot/cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>",
|
||||
"nl": "Afgescheiden voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>"
|
||||
"nl": "Afgescheiden voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>",
|
||||
"de": "Getrennter Fuß-/Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D09.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -790,7 +874,8 @@
|
|||
"if": "traffic_sign=BE:D10",
|
||||
"then": {
|
||||
"en": "Unsegregated foot/cycleway <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>",
|
||||
"nl": "Gedeeld voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>"
|
||||
"nl": "Gedeeld voet-/fietspad <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>",
|
||||
"de": "Gemeinsamer Fuß-/Radweg <img src='./assets/themes/cycle_infra/Belgian_road_sign_D10.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -806,7 +891,8 @@
|
|||
"if": "traffic_sign=none",
|
||||
"then": {
|
||||
"en": "No traffic sign present",
|
||||
"nl": "Geen verkeersbord aanwezig"
|
||||
"nl": "Geen verkeersbord aanwezig",
|
||||
"de": "Kein Verkehrsschild vorhanden"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -896,7 +982,8 @@
|
|||
"if": "cycleway:traffic_sign:supplementary=none",
|
||||
"then": {
|
||||
"en": "No supplementary traffic sign present",
|
||||
"nl": "Geen onderbord aanwezig"
|
||||
"nl": "Geen onderbord aanwezig",
|
||||
"de": "Kein zusätzliches Verkehrszeichen vorhanden"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -929,7 +1016,8 @@
|
|||
"if": "traffic_sign=BE:D7;BE:M13",
|
||||
"then": {
|
||||
"en": "<img src='./assets/themes/cycle_infra/Belgian_traffic_sign_M13.svg' style='width: 3em'>",
|
||||
"nl": "<img src='./assets/themes/cycle_infra/Belgian_traffic_sign_M13.svg' style='width: 3em'>"
|
||||
"nl": "<img src='./assets/themes/cycle_infra/Belgian_traffic_sign_M13.svg' style='width: 3em'>",
|
||||
"de": "<img src='./assets/themes/cycle_infra/Belgian_traffic_sign_M13.svg' style='width: 3em'>"
|
||||
},
|
||||
"hideInAnswer": "_country!=be",
|
||||
"addExtraTags": [
|
||||
|
@ -986,7 +1074,8 @@
|
|||
"if": "traffic_sign:supplementary=none",
|
||||
"then": {
|
||||
"en": "No supplementary traffic sign present",
|
||||
"nl": "Geen onderbord aanwezig"
|
||||
"nl": "Geen onderbord aanwezig",
|
||||
"de": "Kein zusätzliches Verkehrszeichen vorhanden"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -994,11 +1083,13 @@
|
|||
{
|
||||
"render": {
|
||||
"en": "The buffer besides this cycleway is {cycleway:buffer} m",
|
||||
"nl": "De schrikafstand van dit fietspad is {cycleway:buffer} m"
|
||||
"nl": "De schrikafstand van dit fietspad is {cycleway:buffer} m",
|
||||
"de": "Der Sicherheitsabstand zu diesem Radweg beträgt {cycleway:buffer} m"
|
||||
},
|
||||
"question": {
|
||||
"en": "How wide is the gap between the cycleway and the road?",
|
||||
"nl": "Hoe breed is de ruimte tussen het fietspad en de weg?"
|
||||
"nl": "Hoe breed is de ruimte tussen het fietspad en de weg?",
|
||||
"de": "Wie breit ist der Abstand zwischen Radweg und Straße?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -1020,7 +1111,8 @@
|
|||
"id": "cyclelan-segregation",
|
||||
"question": {
|
||||
"en": "How is this cycleway separated from the road?",
|
||||
"nl": "Hoe is dit fietspad gescheiden van de weg?"
|
||||
"nl": "Hoe is dit fietspad gescheiden van de weg?",
|
||||
"de": "Wie ist der Radweg von der Straße abgegrenzt?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -1033,28 +1125,32 @@
|
|||
"if": "cycleway:separation=dashed_line",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a dashed line",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een onderbroken streep"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een onderbroken streep",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine gestrichelte Linie"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:separation=solid_line",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a solid line",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een doorgetrokken streep"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een doorgetrokken streep",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine durchgezogene Linie"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:separation=parking_lane",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a parking lane",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met parkeervakken"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met parkeervakken",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine Parkspur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cycleway:separation=kerb",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a kerb",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een stoeprand"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een stoeprand",
|
||||
"de": "Dieser Radweg ist getrennt durch einen Bordstein"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1063,7 +1159,8 @@
|
|||
"id": "cycleway-segregation",
|
||||
"question": {
|
||||
"en": "How is this cycleway separated from the road?",
|
||||
"nl": "Hoe is dit fietspad gescheiden van de weg?"
|
||||
"nl": "Hoe is dit fietspad gescheiden van de weg?",
|
||||
"de": "Wie ist der Radweg von der Straße abgegrenzt?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -1076,28 +1173,32 @@
|
|||
"if": "separation=dashed_line",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a dashed line",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een onderbroken streep"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een onderbroken streep",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine gestrichelte Linie"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "separation=solid_line",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a solid line",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een doorgetrokken streep"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een doorgetrokken streep",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine durchgezogene Linie"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "separation=parking_lane",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a parking lane",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met parkeervakken"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met parkeervakken",
|
||||
"de": "Der Radweg ist abgegrenzt durch eine Parkspur"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "separation=kerb",
|
||||
"then": {
|
||||
"en": "This cycleway is separated by a kerb",
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een stoeprand"
|
||||
"nl": "Dit fietspad is gescheiden van de weg met een stoeprand",
|
||||
"de": "Dieser Radweg ist getrennt durch einen Bordstein"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1175,5 +1276,6 @@
|
|||
"then": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"allowSplit": true
|
||||
}
|
|
@ -35,12 +35,7 @@
|
|||
"mappings": [
|
||||
{
|
||||
"if": "_recently_surveyed=true",
|
||||
"then": {
|
||||
"en": "./assets/layers/defibrillator/aed_checked.svg",
|
||||
"ru": "./assets/layers/defibrillator/aed_checked.svg",
|
||||
"it": "./assets/layers/defibrillator/aed_checked.svg",
|
||||
"fr": "./assets/layers/defibrillator/aed_checked.svg"
|
||||
}
|
||||
"then": "./assets/layers/defibrillator/aed_checked.svg"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -189,7 +184,8 @@
|
|||
"en": "Not accessible, possibly only for professional use",
|
||||
"nl": "Niet toegankelijk, mogelijk enkel voor professionals",
|
||||
"fr": "Pas accessible, peut-être uniquement à usage professionnel",
|
||||
"it": "Non accessibile, potrebbe essere solo per uso professionale"
|
||||
"it": "Non accessibile, potrebbe essere solo per uso professionale",
|
||||
"de": "Nicht zugänglich, möglicherweise nur für betriebliche Nutzung"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -207,7 +203,8 @@
|
|||
"en": "Is this a a regular automatic defibrillator or a manual defibrillator for professionals only?",
|
||||
"nl": "Is dit een gewone automatische defibrillator of een manueel toestel enkel voor professionals?",
|
||||
"fr": "Est-ce un défibrillateur automatique normal ou un défibrillateur manuel à usage professionnel uniquement ?",
|
||||
"it": "Si tratta di un normale defibrillatore automatico o un defibrillatore manuale riservato ai professionisti?"
|
||||
"it": "Si tratta di un normale defibrillatore automatico o un defibrillatore manuale riservato ai professionisti?",
|
||||
"de": "Ist dies ein normaler automatischer Defibrillator oder ein manueller Defibrillator nur für Profis?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "defibrillator"
|
||||
|
@ -235,7 +232,8 @@
|
|||
"nl": "Dit is een gewone automatische defibrillator",
|
||||
"fr": "C'est un défibrillateur automatique manuel",
|
||||
"it": "È un normale defibrillatore automatico",
|
||||
"ru": "Это обычный автоматический дефибриллятор"
|
||||
"ru": "Это обычный автоматический дефибриллятор",
|
||||
"de": "Dies ist ein normaler automatischer Defibrillator"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"nl": "Richtingsvisualisatie",
|
||||
"fr": "Visualisation de la direction",
|
||||
"it": "Visualizzazione della direzione",
|
||||
"ru": "Визуализация направления"
|
||||
"ru": "Визуализация направления",
|
||||
"de": "Visualisierung der Richtung"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
|
@ -23,7 +24,8 @@
|
|||
"en": "This layer visualizes directions",
|
||||
"nl": "Deze laag toont de oriëntatie van een object",
|
||||
"fr": "Cette couche visualise les directions",
|
||||
"it": "Questo livello visualizza le direzioni"
|
||||
"it": "Questo livello visualizza le direzioni",
|
||||
"de": "Diese Ebene visualisiert Richtungen"
|
||||
},
|
||||
"tagRenderings": [],
|
||||
"icon": {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"nl": "Drinkbaar water",
|
||||
"fr": "Eau potable",
|
||||
"gl": "Auga potábel",
|
||||
"de": "Trinkwasser",
|
||||
"de": "Trinkwasserstelle",
|
||||
"it": "Acqua potabile",
|
||||
"ru": "Питьевая вода",
|
||||
"id": "Air minum"
|
||||
|
@ -16,7 +16,7 @@
|
|||
"nl": "Drinkbaar water",
|
||||
"fr": "Eau potable",
|
||||
"gl": "Auga potábel",
|
||||
"de": "Trinkwasser",
|
||||
"de": "Trinkwasserstelle",
|
||||
"it": "Acqua potabile",
|
||||
"ru": "Питьевая вода",
|
||||
"id": "Air minum"
|
||||
|
@ -61,7 +61,7 @@
|
|||
"nl": "drinkbaar water",
|
||||
"fr": "eau potable",
|
||||
"gl": "auga potábel",
|
||||
"de": "trinkwasser",
|
||||
"de": "Trinkwasserstelle",
|
||||
"it": "acqua potabile",
|
||||
"ru": "питьевая вода",
|
||||
"id": "air minum"
|
||||
|
@ -99,7 +99,8 @@
|
|||
"en": "This drinking water works",
|
||||
"nl": "Deze drinkwaterfontein werkt",
|
||||
"it": "La fontanella funziona",
|
||||
"fr": "Cette fontaine fonctionne"
|
||||
"fr": "Cette fontaine fonctionne",
|
||||
"de": "Diese Trinkwasserstelle funktioniert"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -108,7 +109,8 @@
|
|||
"en": "This drinking water is broken",
|
||||
"nl": "Deze drinkwaterfontein is kapot",
|
||||
"it": "La fontanella è guasta",
|
||||
"fr": "Cette fontaine est cassée"
|
||||
"fr": "Cette fontaine est cassée",
|
||||
"de": "Diese Trinkwasserstelle ist kaputt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -117,7 +119,8 @@
|
|||
"en": "This drinking water is closed",
|
||||
"nl": "Deze drinkwaterfontein is afgesloten",
|
||||
"it": "La fontanella è chiusa",
|
||||
"fr": "Cette fontaine est fermée"
|
||||
"fr": "Cette fontaine est fermée",
|
||||
"de": "Diese Trinkwasserstelle wurde geschlossen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -161,7 +164,7 @@
|
|||
"en": "<a href='#{_closest_other_drinking_water_id}'>There is another drinking water fountain at {_closest_other_drinking_water_distance} meter</a>",
|
||||
"nl": "<a href='#{_closest_other_drinking_water_id}'>Er bevindt zich een ander drinkwaterpunt op {_closest_other_drinking_water_distance} meter</a>",
|
||||
"it": "<a href='#{_closest_other_drinking_water_id}'>C’è un’altra fontanella a {_closest_other_drinking_water_distance} metri</a>",
|
||||
"de": "<a href='#{_closest_other_drinking_water_id}'>Ein weiterer Trinkwasserbrunnen befindet sich in {_closest_other_drinking_water_distance} Meter</a>",
|
||||
"de": "<a href='#{_closest_other_drinking_water_id}'>Eine weitere Trinkwasserstelle liegt {_closest_other_drinking_water_distance} Meter entfernt</a>",
|
||||
"fr": "<a href='#{_closest_other_drinking_water_id}'>Une autre source d’eau potable est à {_closest_other_drinking_water_distance} mètres a>"
|
||||
},
|
||||
"condition": "_closest_other_drinking_water_id~*"
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
"id": "wikipedia-etymology",
|
||||
"question": {
|
||||
"en": "What is the Wikidata-item that this object is named after?",
|
||||
"nl": "Wat is het Wikidata-item van hetgeen dit object is naar vernoemd?"
|
||||
"nl": "Wat is het Wikidata-item van hetgeen dit object is naar vernoemd?",
|
||||
"de": "Was ist das Wikidata-Element, nach dem dieses Objekt benannt ist?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name:etymology:wikidata",
|
||||
|
@ -71,7 +72,8 @@
|
|||
},
|
||||
"render": {
|
||||
"en": "<h3>Wikipedia article of the name giver</h3>{wikipedia(name:etymology:wikidata):max-height:20rem}",
|
||||
"nl": "<h3>Wikipedia artikel van de naamgever</h3>{wikipedia(name:etymology:wikidata):max-height:20rem}"
|
||||
"nl": "<h3>Wikipedia artikel van de naamgever</h3>{wikipedia(name:etymology:wikidata):max-height:20rem}",
|
||||
"de": "<h3>Wikipedia Artikel zur Namensherkunft</h3>{wikipedia(name:etymology:wikidata):max-height:20rem}"
|
||||
},
|
||||
"condition": "name:etymology!=unknown"
|
||||
},
|
||||
|
@ -87,7 +89,8 @@
|
|||
"id": "simple etymology",
|
||||
"question": {
|
||||
"en": "What is this object named after?<br/><span class='subtle'>This might be written on the street name sign</span>",
|
||||
"nl": "Naar wat is dit object vernoemd?<br/><span class='subtle'>Dit staat mogelijks vermeld op het straatnaambordje</subtle>"
|
||||
"nl": "Naar wat is dit object vernoemd?<br/><span class='subtle'>Dit staat mogelijks vermeld op het straatnaambordje</subtle>",
|
||||
"de": "Wonach ist dieses Objekt benannt?<br/><span class='subtle'>Das könnte auf einem Straßenschild stehen</span>"
|
||||
},
|
||||
"render": {
|
||||
"en": "Named after {name:etymology}",
|
||||
|
@ -102,7 +105,8 @@
|
|||
"if": "name:etymology=unknown",
|
||||
"then": {
|
||||
"en": "The origin of this name is unknown in all literature",
|
||||
"nl": "De oorsprong van deze naam is onbekend in de literatuur"
|
||||
"nl": "De oorsprong van deze naam is onbekend in de literatuur",
|
||||
"de": "Der Ursprung dieses Namens ist in der gesamten Literatur unbekannt"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"id": "food",
|
||||
"name": {
|
||||
"nl": "Eetgelegenheden",
|
||||
"en": "Restaurants and fast food"
|
||||
"en": "Restaurants and fast food",
|
||||
"de": "Restaurants und Fast Food"
|
||||
},
|
||||
"source": {
|
||||
"osmTags": {
|
||||
|
@ -64,14 +65,16 @@
|
|||
"title": {
|
||||
"en": "restaurant",
|
||||
"nl": "restaurant",
|
||||
"ru": "ресторан"
|
||||
"ru": "ресторан",
|
||||
"de": "Restaurant"
|
||||
},
|
||||
"tags": [
|
||||
"amenity=restaurant"
|
||||
],
|
||||
"description": {
|
||||
"nl": "Een eetgegelegenheid waar je aan tafel wordt bediend",
|
||||
"en": "A formal eating place with sit-down facilities selling full meals served by waiters"
|
||||
"en": "A formal eating place with sit-down facilities selling full meals served by waiters",
|
||||
"de": "Ein klassisches Speiselokal mit Sitzgelegenheiten, in dem vollständige Mahlzeiten von Kellnern serviert werden"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
|
@ -81,7 +84,8 @@
|
|||
"title": {
|
||||
"en": "fastfood",
|
||||
"nl": "fastfood-zaak",
|
||||
"ru": "быстрое питание"
|
||||
"ru": "быстрое питание",
|
||||
"de": "Schnellimbiss"
|
||||
},
|
||||
"tags": [
|
||||
"amenity=fast_food"
|
||||
|
@ -97,7 +101,8 @@
|
|||
{
|
||||
"title": {
|
||||
"en": "fries shop",
|
||||
"nl": "frituur"
|
||||
"nl": "frituur",
|
||||
"de": "Pommesbude"
|
||||
},
|
||||
"tags": [
|
||||
"amenity=fast_food",
|
||||
|
@ -125,7 +130,8 @@
|
|||
},
|
||||
"then": {
|
||||
"nl": "Restaurant <i>{name}</i>",
|
||||
"en": "Restaurant <i>{name}</i>"
|
||||
"en": "Restaurant <i>{name}</i>",
|
||||
"de": "Restaurant <i>{name}</i>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -137,7 +143,8 @@
|
|||
},
|
||||
"then": {
|
||||
"nl": "Fastfood-zaak <i>{name}</i>",
|
||||
"en": "Fastfood <i>{name}</i>"
|
||||
"en": "Fastfood <i>{name}</i>",
|
||||
"de": "Schnellrestaurant<i>{name}</i>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -147,11 +154,13 @@
|
|||
{
|
||||
"question": {
|
||||
"nl": "Wat is de naam van deze eetgelegenheid?",
|
||||
"en": "What is the name of this restaurant?"
|
||||
"en": "What is the name of this restaurant?",
|
||||
"de": "Wie heißt dieses Restaurant?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "De naam van deze eetgelegeheid is {name}",
|
||||
"en": "The name of this restaurant is {name}"
|
||||
"en": "The name of this restaurant is {name}",
|
||||
"de": "Das Restaurant heißt {name}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name"
|
||||
|
@ -161,7 +170,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "What type of business is this?",
|
||||
"nl": "Wat voor soort zaak is dit?"
|
||||
"nl": "Wat voor soort zaak is dit?",
|
||||
"de": "Um was für ein Geschäft handelt es sich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -188,11 +198,13 @@
|
|||
{
|
||||
"question": {
|
||||
"nl": "Welk soort gerechten worden hier geserveerd?",
|
||||
"en": "Which food is served here?"
|
||||
"en": "Which food is served here?",
|
||||
"de": "Welches Essen gibt es hier?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "Deze plaats serveert vooral {cuisine}",
|
||||
"en": "This place mostly serves {cuisine}"
|
||||
"en": "This place mostly serves {cuisine}",
|
||||
"de": "An diesem Ort gibt es hauptsächlich {cuisine}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "cuisine",
|
||||
|
@ -205,21 +217,24 @@
|
|||
"if": "cuisine=pizza",
|
||||
"then": {
|
||||
"en": "This is a pizzeria",
|
||||
"nl": "Dit is een pizzeria"
|
||||
"nl": "Dit is een pizzeria",
|
||||
"de": "Dies ist eine Pizzeria"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cuisine=friture",
|
||||
"then": {
|
||||
"en": "This is a friture",
|
||||
"nl": "Dit is een frituur"
|
||||
"nl": "Dit is een frituur",
|
||||
"de": "Dies ist eine Pommesbude"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "cuisine=pasta",
|
||||
"then": {
|
||||
"en": "Mainly serves pasta",
|
||||
"nl": "Dit is een pastazaak"
|
||||
"nl": "Dit is een pastazaak",
|
||||
"de": "Bietet vorwiegend Pastagerichte an"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -300,28 +315,32 @@
|
|||
{
|
||||
"question": {
|
||||
"nl": "Biedt deze zaak een afhaalmogelijkheid aan?",
|
||||
"en": "Does this place offer takea-way?"
|
||||
"en": "Does this place offer takea-way?",
|
||||
"de": "Ist an diesem Ort Mitnahme möglich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "takeaway=only",
|
||||
"then": {
|
||||
"en": "This is a take-away only business",
|
||||
"nl": "Hier is enkel afhaal mogelijk"
|
||||
"nl": "Hier is enkel afhaal mogelijk",
|
||||
"de": "Dieses Geschäft bietet nur Artikel zur Mitnahme an"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "takeaway=yes",
|
||||
"then": {
|
||||
"en": "Take-away is possible here",
|
||||
"nl": "Eten kan hier afgehaald worden"
|
||||
"nl": "Eten kan hier afgehaald worden",
|
||||
"de": "Mitnahme möglich"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "takeaway=no",
|
||||
"then": {
|
||||
"en": "Take-away is not possible here",
|
||||
"nl": "Hier is geen afhaalmogelijkheid"
|
||||
"nl": "Hier is geen afhaalmogelijkheid",
|
||||
"de": "Mitnahme nicht möglich"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -330,7 +349,8 @@
|
|||
{
|
||||
"question": {
|
||||
"nl": "Heeft deze eetgelegenheid een vegetarische optie?",
|
||||
"en": "Does this restaurant have a vegetarian option?"
|
||||
"en": "Does this restaurant have a vegetarian option?",
|
||||
"de": "Gibt es im das Restaurant vegetarische Speisen?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -397,35 +417,40 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Does this restaurant offer a halal menu?",
|
||||
"nl": "Heeft dit restaurant halal opties?"
|
||||
"nl": "Heeft dit restaurant halal opties?",
|
||||
"de": "Gibt es im das Restaurant halal Speisen?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "diet:halal=no",
|
||||
"then": {
|
||||
"en": "There are no halal options available",
|
||||
"nl": "Er zijn geen halal opties aanwezig"
|
||||
"nl": "Er zijn geen halal opties aanwezig",
|
||||
"de": "Hier gibt es keine halal Speisen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "diet:halal=limited",
|
||||
"then": {
|
||||
"en": "There is a small halal menu",
|
||||
"nl": "Er zijn een beperkt aantal halal opties"
|
||||
"nl": "Er zijn een beperkt aantal halal opties",
|
||||
"de": "Hier gibt es wenige halal Speisen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "diet:halal=yes",
|
||||
"then": {
|
||||
"nl": "Halal menu verkrijgbaar",
|
||||
"en": "There is a halal menu"
|
||||
"en": "There is a halal menu",
|
||||
"de": "Es gibt halal Speisen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "diet:halal=only",
|
||||
"then": {
|
||||
"nl": "Enkel halal opties zijn beschikbaar",
|
||||
"en": "Only halal options are available"
|
||||
"en": "Only halal options are available",
|
||||
"de": "Es gibt ausschließlich halal Speisen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -524,7 +549,8 @@
|
|||
"nl": "Als je je eigen container (bv. kookpot of kleine potjes voor saus) meeneemt, gebruikt de frituur deze dan om je bestelling in te doen?",
|
||||
"fr": "Est-il proposé d’utiliser ses propres contenants pour sa commande ?<br/>",
|
||||
"en": "If you bring your own container (such as a cooking pot and small pots), is it used to package your order?<br/>",
|
||||
"ja": "お客様が持参容器(調理用の鍋や小さな鍋など)をもってきた場合は、注文の梱包に使用されますか?<br/>"
|
||||
"ja": "お客様が持参容器(調理用の鍋や小さな鍋など)をもってきた場合は、注文の梱包に使用されますか?<br/>",
|
||||
"de": "Wenn Sie Ihr eigenes Behältnis mitbringen (z. B. einen Kochtopf und kleine Töpfe), wird es dann zum Verpacken Ihrer Bestellung verwendet?<br/>"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -533,7 +559,8 @@
|
|||
"nl": "Je mag je <b>eigen containers</b> meenemen om je bestelling in mee te nemen en zo minder afval te maken",
|
||||
"fr": "Vous pouvez <b>apporter vos contenants</b> pour votre commande, limitant l’usage de matériaux à usage unique et les déchets",
|
||||
"en": "You can bring <b>your own containers</b> to get your order, saving on single-use packaging material and thus waste",
|
||||
"ja": "<b>自分の容器</b>を持ってきて、注文を受け取ることができ、使い捨ての梱包材を節約して、無駄を省くことができます"
|
||||
"ja": "<b>自分の容器</b>を持ってきて、注文を受け取ることができ、使い捨ての梱包材を節約して、無駄を省くことができます",
|
||||
"de": "Sie können <b>ihre eigenen Behälter</b> mitbringen, um Ihre Bestellung zu erhalten, was Einwegverpackungsmaterial und damit Abfall spart"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -567,7 +594,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Opened now",
|
||||
"nl": "Nu geopened"
|
||||
"nl": "Nu geopened",
|
||||
"de": "Aktuell geöffnet"
|
||||
},
|
||||
"osmTags": "_isOpen=yes"
|
||||
}
|
||||
|
@ -579,7 +607,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Has a vegetarian menu",
|
||||
"nl": "Heeft een vegetarisch menu"
|
||||
"nl": "Heeft een vegetarisch menu",
|
||||
"de": "Hat vegetarische Speisen"
|
||||
},
|
||||
"osmTags": {
|
||||
"or": [
|
||||
|
@ -598,7 +627,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Has a vegan menu",
|
||||
"nl": "Heeft een veganistisch menu"
|
||||
"nl": "Heeft een veganistisch menu",
|
||||
"de": "Bietet vegan Speisen an"
|
||||
},
|
||||
"osmTags": {
|
||||
"or": [
|
||||
|
@ -615,7 +645,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Has a halal menu",
|
||||
"nl": "Heeft een halal menu"
|
||||
"nl": "Heeft een halal menu",
|
||||
"de": "Hat halal Speisen"
|
||||
},
|
||||
"osmTags": {
|
||||
"or": [
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": {
|
||||
"en": "Ghost bikes",
|
||||
"nl": "Witte Fietsen",
|
||||
"de": "Geisterrad",
|
||||
"de": "Geisterräder",
|
||||
"it": "Bici fantasma",
|
||||
"fr": "Vélos fantômes",
|
||||
"eo": "Fantombiciklo",
|
||||
|
@ -84,7 +84,7 @@
|
|||
"render": {
|
||||
"en": "A <b>ghost bike</b> is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.",
|
||||
"nl": "Een Witte Fiets (of Spookfiets) is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat over een witgeschilderde fiets die geplaatst werd in de buurt van het ongeval.",
|
||||
"de": "Ein <b>Geisterrad</b> ist ein Denkmal für einen Radfahrer, der bei einem Verkehrsunfall ums Leben kam, in Form eines weißen Fahrrades, das dauerhaft in der Nähe des Unfallortes aufgestellt wird.",
|
||||
"de": "Ein <b>Geisterrad</b> ist ein weißes Fahrrad, dass zum Gedenken eines tödlich verunglückten Radfahrers vor Ort aufgestellt wurde.",
|
||||
"it": "Una <b>bici fantasma</b> è il memoriale di un ciclista che è morto in un incidente stradale e che ha la forma di una bicicletta bianca piazzata in maniera stabile vicino al luogo dell’incidente.",
|
||||
"fr": "Un <b>vélo fantôme</b> est un monument commémoratif pour un cycliste décédé dans un accident de la route, sous la forme d'un vélo blanc placé en permanence près du lieu de l'accident."
|
||||
}
|
||||
|
@ -174,14 +174,16 @@
|
|||
"nl": "Wanneer werd deze witte fiets geplaatst?",
|
||||
"en": "When was this Ghost bike installed?",
|
||||
"it": "Quando è stata installata questa bici fantasma?",
|
||||
"fr": "Quand ce vélo fantôme a-t-il été installée ?"
|
||||
"fr": "Quand ce vélo fantôme a-t-il été installée ?",
|
||||
"de": "Wann wurde dieses Geisterrad aufgestellt?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "Geplaatst op {start_date}",
|
||||
"en": "Placed on {start_date}",
|
||||
"it": "Piazzata in data {start_date}",
|
||||
"fr": "Placé le {start_date}",
|
||||
"ru": "Установлен {start_date}"
|
||||
"ru": "Установлен {start_date}",
|
||||
"de": "Aufgestellt am {start_date}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "start_date",
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
"en": "A map, meant for tourists which is permanently installed in the public space",
|
||||
"nl": "Een permantent geinstalleerde kaart",
|
||||
"it": "Una mappa, destinata ai turisti e che è sistemata in maniera permanente in uno spazio pubblico",
|
||||
"fr": "Une carte, destinée aux touristes, installée en permanence dans l'espace public"
|
||||
"fr": "Une carte, destinée aux touristes, installée en permanence dans l'espace public",
|
||||
"de": "Eine Karte, die für Touristen gedacht ist und dauerhaft im öffentlichen Raum aufgestellt ist"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
|
|
|
@ -297,7 +297,8 @@
|
|||
"nl": "Wie is de conservator van dit gebied?<br/><span class='subtle'>Respecteer privacy - geef deze naam enkel als die duidelijk is gepubliceerd",
|
||||
"en": "Whom is the curator of this nature reserve?<br/><span class='subtle'>Respect privacy - only fill out a name if this is widely published",
|
||||
"it": "Chi è il curatore di questa riserva naturale?<br/><span class='subtle'>Rispetta la privacy (scrivi il nome solo se questo è noto pubblicamente)",
|
||||
"fr": "Qui est en charge de la conservation de la réserve ?<br/><span class='subtle'>À ne remplir seulement que si le nom est diffusé au public"
|
||||
"fr": "Qui est en charge de la conservation de la réserve ?<br/><span class='subtle'>À ne remplir seulement que si le nom est diffusé au public",
|
||||
"de": "Wer ist der Verwalter dieses Naturschutzgebietes?<br/><span class='subtle'>Respektieren Sie die Privatsphäre - geben Sie nur dann einen Namen an, wenn dieser allgemein bekannt ist"
|
||||
},
|
||||
"render": {
|
||||
"nl": "{curator} is de beheerder van dit gebied",
|
||||
|
@ -381,7 +382,8 @@
|
|||
"en": "Surface area: {_surface:ha}Ha",
|
||||
"nl": "Totale oppervlakte: {_surface:ha}Ha",
|
||||
"it": "Area: {_surface:ha} ha",
|
||||
"fr": "Superficie : {_surface:ha} ha"
|
||||
"fr": "Superficie : {_surface:ha} ha",
|
||||
"de": "Grundfläche: {_surface:ha}ha"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
|
|
@ -3,14 +3,16 @@
|
|||
"name": {
|
||||
"en": "Observation towers",
|
||||
"nl": "Uitkijktorens",
|
||||
"ru": "Смотровые башни"
|
||||
"ru": "Смотровые башни",
|
||||
"de": "Aussichtstürme"
|
||||
},
|
||||
"minzoom": 8,
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Observation tower",
|
||||
"nl": "Uitkijktoren",
|
||||
"ru": "Смотровая башня"
|
||||
"ru": "Смотровая башня",
|
||||
"de": "Beobachtungsturm"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -18,25 +20,29 @@
|
|||
"then": {
|
||||
"en": "<b>{name}</b>",
|
||||
"nl": "<b>{name}</b>",
|
||||
"ru": "<b>{name}</b>"
|
||||
"ru": "<b>{name}</b>",
|
||||
"de": "<b>{name}</b>"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"en": "Towers with a panoramic view",
|
||||
"nl": "Torens om van het uitzicht te genieten"
|
||||
"nl": "Torens om van het uitzicht te genieten",
|
||||
"de": "Türme zur Aussicht auf die umgebende Landschaft"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
{
|
||||
"question": {
|
||||
"en": "What is the name of this tower?",
|
||||
"nl": "Heeft deze toren een naam?"
|
||||
"nl": "Heeft deze toren een naam?",
|
||||
"de": "Wie heißt dieser Turm?"
|
||||
},
|
||||
"render": {
|
||||
"en": "This tower is called <b>{name}</b>",
|
||||
"nl": "Deze toren heet <b>{name}</b>"
|
||||
"nl": "Deze toren heet <b>{name}</b>",
|
||||
"de": "Der Name dieses Turms lautet <b>{name}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name"
|
||||
|
@ -46,7 +52,8 @@
|
|||
"if": "noname=yes",
|
||||
"then": {
|
||||
"en": "This tower doesn't have a specific name",
|
||||
"nl": "Deze toren heeft geen specifieke naam"
|
||||
"nl": "Deze toren heeft geen specifieke naam",
|
||||
"de": "Dieser Turm hat keinen eigenen Namen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -55,11 +62,13 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "What is the height of this tower?",
|
||||
"nl": "Hoe hoog is deze toren?"
|
||||
"nl": "Hoe hoog is deze toren?",
|
||||
"de": "Wie hoch ist dieser Turm?"
|
||||
},
|
||||
"render": {
|
||||
"en": "This tower is {height} high",
|
||||
"nl": "Deze toren is {height} hoog"
|
||||
"nl": "Deze toren is {height} hoog",
|
||||
"de": "Dieser Turm ist {height} hoch"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "height",
|
||||
|
@ -70,11 +79,13 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Who maintains this tower?",
|
||||
"nl": "Wie onderhoudt deze toren?"
|
||||
"nl": "Wie onderhoudt deze toren?",
|
||||
"de": "Wer betreibt diesen Turm?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "Wordt onderhouden door <b>{operator}</b>",
|
||||
"en": "Maintained by <b>{operator}</b>"
|
||||
"en": "Maintained by <b>{operator}</b>",
|
||||
"de": "Betrieben von <b>{operator}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
|
@ -85,11 +96,13 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "How much does one have to pay to enter this tower?",
|
||||
"nl": "Hoeveel moet men betalen om deze toren te bezoeken?"
|
||||
"nl": "Hoeveel moet men betalen om deze toren te bezoeken?",
|
||||
"de": "Was kostet der Zugang zu diesem Turm?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Visiting this tower costs <b>{charge}</b>",
|
||||
"nl": "Deze toren bezoeken kost <b>{charge}</b>"
|
||||
"nl": "Deze toren bezoeken kost <b>{charge}</b>",
|
||||
"de": "Der Besuch des Turms kostet <b>{charge}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "charge",
|
||||
|
@ -107,7 +120,8 @@
|
|||
},
|
||||
"then": {
|
||||
"en": "Free to visit",
|
||||
"nl": "Gratis te bezoeken"
|
||||
"nl": "Gratis te bezoeken",
|
||||
"de": "Eintritt kostenlos"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -150,7 +164,8 @@
|
|||
"title": {
|
||||
"en": "observation tower",
|
||||
"nl": "Uitkijktoren",
|
||||
"ru": "смотровая башня"
|
||||
"ru": "смотровая башня",
|
||||
"de": "Beobachtungsturm"
|
||||
},
|
||||
"description": {
|
||||
"nl": "Een publiek toegankelijke uitkijktoren"
|
||||
|
@ -179,7 +194,8 @@
|
|||
"human": {
|
||||
"nl": " meter",
|
||||
"en": " meter",
|
||||
"ru": " метр"
|
||||
"ru": " метр",
|
||||
"de": " Meter"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
"nl": "Deze laag toont picnictafels",
|
||||
"it": "Il livello che mostra i tavoli da picnic",
|
||||
"fr": "La couche montrant les tables de pique-nique",
|
||||
"ru": "Слой, отображающий столы для пикника"
|
||||
"ru": "Слой, отображающий столы для пикника",
|
||||
"de": "Die Ebene zeigt Picknicktische an"
|
||||
},
|
||||
"tagRenderings": [
|
||||
{
|
||||
|
|
|
@ -205,14 +205,16 @@
|
|||
"en": "Accessible to kids older than {min_age} years",
|
||||
"it": "Accessibile ai bambini di almeno {min_age} anni",
|
||||
"ru": "Доступно для детей старше {min_age} лет",
|
||||
"fr": "Accessible aux enfants de plus de {min_age} ans"
|
||||
"fr": "Accessible aux enfants de plus de {min_age} ans",
|
||||
"de": "Zugang nur für Kinder ab {min_age} Jahren"
|
||||
},
|
||||
"question": {
|
||||
"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 ?",
|
||||
"ru": "С какого возраста доступна эта детская площадка?"
|
||||
"ru": "С какого возраста доступна эта детская площадка?",
|
||||
"de": "Ab welchem Alter dürfen Kinder auf diesem Spielplatz spielen?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "min_age",
|
||||
|
@ -226,13 +228,15 @@
|
|||
"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",
|
||||
"ru": "Доступно детям до {max_age}"
|
||||
"ru": "Доступно детям до {max_age}",
|
||||
"de": "Zugang nur für Kinder bis maximal {max_age}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wat is de maximaal toegestane leeftijd voor deze speeltuin?",
|
||||
"en": "What is the maximum age allowed to access this playground?",
|
||||
"it": "Qual è l’età massima per accedere a questo parco giochi?",
|
||||
"fr": "Quel est l’âge maximum autorisé pour utiliser l’aire de jeu ?"
|
||||
"fr": "Quel est l’âge maximum autorisé pour utiliser l’aire de jeu ?",
|
||||
"de": "Bis zu welchem Alter dürfen Kinder auf diesem Spielplatz spielen?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "max_age",
|
||||
|
@ -353,7 +357,8 @@
|
|||
"nl": "Wie kan men bellen indien er problemen zijn met de speeltuin?",
|
||||
"en": "What is the phone number of the playground maintainer?",
|
||||
"fr": "Quel est le numéro de téléphone du responsable du terrain de jeux ?",
|
||||
"it": "Qual è il numero di telefono del gestore del campetto?"
|
||||
"it": "Qual è il numero di telefono del gestore del campetto?",
|
||||
"de": "Wie lautet die Telefonnummer vom Betreiber des Spielplatzes?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "De bevoegde dienst kan getelefoneerd worden via <a href='tel:{phone}'>{phone}</a>",
|
||||
|
@ -428,7 +433,8 @@
|
|||
"en": "When is this playground accessible?",
|
||||
"fr": "Quand ce terrain de jeux est-il accessible ?",
|
||||
"it": "Quando si può accedere a questo campetto?",
|
||||
"ru": "Когда открыта эта игровая площадка?"
|
||||
"ru": "Когда открыта эта игровая площадка?",
|
||||
"de": "Wann ist dieser Spielplatz zugänglich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -438,7 +444,8 @@
|
|||
"en": "Accessible from sunrise till sunset",
|
||||
"fr": "Accessible du lever au coucher du soleil",
|
||||
"it": "Si può accedere dall'alba al tramonto",
|
||||
"ru": "Открыто от рассвета до заката"
|
||||
"ru": "Открыто от рассвета до заката",
|
||||
"de": "Zugänglich von Sonnenaufgang bis Sonnenuntergang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -448,7 +455,8 @@
|
|||
"en": "Always accessible",
|
||||
"fr": "Toujours accessible",
|
||||
"ru": "Всегда доступен",
|
||||
"it": "Si può sempre accedere"
|
||||
"it": "Si può sempre accedere",
|
||||
"de": "Immer zugänglich"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -458,7 +466,8 @@
|
|||
"en": "Always accessible",
|
||||
"ru": "Всегда доступен",
|
||||
"fr": "Toujours accessible",
|
||||
"it": "Si può sempre accedere"
|
||||
"it": "Si può sempre accedere",
|
||||
"de": "Immer zugänglich"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -523,7 +532,8 @@
|
|||
"en": "Playground",
|
||||
"ru": "Детская площадка",
|
||||
"fr": "Terrain de jeux",
|
||||
"it": "Campetto"
|
||||
"it": "Campetto",
|
||||
"de": "Spielplatz"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -467,7 +467,8 @@
|
|||
{
|
||||
"question": {
|
||||
"nl": "Binnen of buiten",
|
||||
"en": "Indoor or outdoor"
|
||||
"en": "Indoor or outdoor",
|
||||
"de": "Innen oder Außen"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
"nl": "Winkel",
|
||||
"de": "Geschäft"
|
||||
},
|
||||
"minzoom": 16,
|
||||
"source": {
|
||||
|
@ -21,7 +22,8 @@
|
|||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
"nl": "Winkel",
|
||||
"de": "Geschäft"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -34,7 +36,8 @@
|
|||
"en": "{name}",
|
||||
"fr": "{name}",
|
||||
"ru": "{name}",
|
||||
"ja": "{name}"
|
||||
"ja": "{name}",
|
||||
"de": "{name}"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -47,7 +50,8 @@
|
|||
"en": "{shop}",
|
||||
"fr": "{shop}",
|
||||
"ru": "{shop}",
|
||||
"ja": "{shop}"
|
||||
"ja": "{shop}",
|
||||
"de": "{shop}"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -57,7 +61,8 @@
|
|||
"fr": "Un magasin",
|
||||
"ja": "ショップ",
|
||||
"nl": "Een winkel",
|
||||
"ru": "Магазин"
|
||||
"ru": "Магазин",
|
||||
"de": "Ein Geschäft"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
|
@ -67,7 +72,8 @@
|
|||
"fr": "Qu'est-ce que le nom de ce magasin?",
|
||||
"ru": "Как называется этот магазин?",
|
||||
"ja": "このお店の名前は何ですか?",
|
||||
"nl": "Wat is de naam van deze winkel?"
|
||||
"nl": "Wat is de naam van deze winkel?",
|
||||
"de": "Wie ist der Name dieses Geschäfts?"
|
||||
},
|
||||
"render": "This shop is called <i>{name}</i>",
|
||||
"freeform": {
|
||||
|
@ -79,13 +85,15 @@
|
|||
"render": {
|
||||
"en": "This shop sells {shop}",
|
||||
"fr": "Ce magasin vends {shop}",
|
||||
"ja": "こちらのお店では{shop}を販売しております"
|
||||
"ja": "こちらのお店では{shop}を販売しております",
|
||||
"de": "Dieses Geschäft verkauft {shop}"
|
||||
},
|
||||
"question": {
|
||||
"en": "What does this shop sell?",
|
||||
"fr": "Que vends ce magasin ?",
|
||||
"ja": "このお店では何を売っていますか?",
|
||||
"ru": "Что продаётся в этом магазине?"
|
||||
"ru": "Что продаётся в этом магазине?",
|
||||
"de": "Was wird in diesem Geschäft verkauft?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "shop"
|
||||
|
@ -100,7 +108,8 @@
|
|||
"then": {
|
||||
"en": "Convenience store",
|
||||
"fr": "Épicerie/superette",
|
||||
"ja": "コンビニエンスストア"
|
||||
"ja": "コンビニエンスストア",
|
||||
"de": "Lebensmittelladen"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -114,7 +123,8 @@
|
|||
"fr": "Supermarché",
|
||||
"ru": "Супермаркет",
|
||||
"ja": "スーパーマーケット",
|
||||
"nl": "Supermarkt"
|
||||
"nl": "Supermarkt",
|
||||
"de": "Supermarkt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -127,7 +137,8 @@
|
|||
"en": "Clothing store",
|
||||
"fr": "Magasin de vêtements",
|
||||
"ru": "Магазин одежды",
|
||||
"ja": "衣料品店"
|
||||
"ja": "衣料品店",
|
||||
"de": "Bekleidungsgeschäft"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -141,7 +152,8 @@
|
|||
"fr": "Coiffeur",
|
||||
"ru": "Парикмахерская",
|
||||
"ja": "理容師",
|
||||
"nl": "Kapper"
|
||||
"nl": "Kapper",
|
||||
"de": "Friseur"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -154,7 +166,8 @@
|
|||
"en": "Bakery",
|
||||
"fr": "Boulangerie",
|
||||
"ja": "ベーカリー",
|
||||
"nl": "Bakkerij"
|
||||
"nl": "Bakkerij",
|
||||
"de": "Bäckerei"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -166,7 +179,8 @@
|
|||
"then": {
|
||||
"en": "Car repair (garage)",
|
||||
"fr": "Garagiste",
|
||||
"ja": "自動車修理(ガレージ)"
|
||||
"ja": "自動車修理(ガレージ)",
|
||||
"de": "Autoreparatur (Werkstatt)"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -179,7 +193,8 @@
|
|||
"en": "Car dealer",
|
||||
"fr": "Concessionnaire",
|
||||
"ru": "Автосалон",
|
||||
"ja": "自動車ディーラー"
|
||||
"ja": "自動車ディーラー",
|
||||
"de": "Autohändler"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -192,14 +207,16 @@
|
|||
"ca": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"id": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ru": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"ja": "<a href='tel:{phone}'>{phone}</a>"
|
||||
"ja": "<a href='tel:{phone}'>{phone}</a>",
|
||||
"de": "<a href='tel:{phone}'>{phone}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the phone number?",
|
||||
"fr": "Quel est le numéro de téléphone ?",
|
||||
"ja": "電話番号は何番ですか?",
|
||||
"nl": "Wat is het telefoonnummer?",
|
||||
"ru": "Какой телефон?"
|
||||
"ru": "Какой телефон?",
|
||||
"de": "Wie ist die Telefonnummer?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "phone",
|
||||
|
@ -214,14 +231,16 @@
|
|||
"ca": "<a href='{website}'>{website}</a>",
|
||||
"id": "<a href='{website}'>{website}</a>",
|
||||
"ru": "<a href='{website}'>{website}</a>",
|
||||
"ja": "<a href='{website}'>{website}</a>"
|
||||
"ja": "<a href='{website}'>{website}</a>",
|
||||
"de": "<a href='{website}'>{website}</a>"
|
||||
},
|
||||
"question": {
|
||||
"en": "What is the website of this shop?",
|
||||
"fr": "Quel est le site internet de ce magasin ?",
|
||||
"ja": "このお店のホームページは何ですか?",
|
||||
"nl": "Wat is de website van deze winkel?",
|
||||
"ru": "Какой веб-сайт у этого магазина?"
|
||||
"ru": "Какой веб-сайт у этого магазина?",
|
||||
"de": "Wie lautet die Webseite dieses Geschäfts?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "website",
|
||||
|
@ -242,7 +261,8 @@
|
|||
"fr": "Quelle est l'adresse électronique de ce magasin ?",
|
||||
"ja": "このお店のメールアドレスは何ですか?",
|
||||
"ru": "Каков адрес электронной почты этого магазина?",
|
||||
"nl": "Wat is het e-mailadres van deze winkel?"
|
||||
"nl": "Wat is het e-mailadres van deze winkel?",
|
||||
"de": "Wie ist die Email-Adresse dieses Geschäfts?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "email",
|
||||
|
@ -262,7 +282,8 @@
|
|||
"fr": "Quels sont les horaires d'ouverture de ce magasin ?",
|
||||
"ja": "この店の営業時間は何時から何時までですか?",
|
||||
"nl": "Wat zijn de openingsuren van deze winkel?",
|
||||
"ru": "Каковы часы работы этого магазина?"
|
||||
"ru": "Каковы часы работы этого магазина?",
|
||||
"de": "Wie sind die Öffnungszeiten dieses Geschäfts?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "opening_hours",
|
||||
|
@ -302,14 +323,16 @@
|
|||
"fr": "Magasin",
|
||||
"ru": "Магазин",
|
||||
"ja": "店",
|
||||
"nl": "Winkel"
|
||||
"nl": "Winkel",
|
||||
"de": "Geschäft"
|
||||
},
|
||||
"description": {
|
||||
"en": "Add a new shop",
|
||||
"fr": "Ajouter un nouveau magasin",
|
||||
"ru": "Добавить новый магазин",
|
||||
"ja": "新しい店を追加する",
|
||||
"nl": "Voeg een nieuwe winkel toe"
|
||||
"nl": "Voeg een nieuwe winkel toe",
|
||||
"de": "Ein neues Geschäft hinzufügen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -116,7 +116,8 @@
|
|||
"en": "The surface is <b>{surface}</b>",
|
||||
"ru": "Поверхность - <b>{surface}</b>",
|
||||
"fr": "La surface en <b>{surface}</b>",
|
||||
"it": "La superficie è <b>{surface}</b>"
|
||||
"it": "La superficie è <b>{surface}</b>",
|
||||
"de": "Die Oberfläche ist <b>{surface}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "surface"
|
||||
|
@ -129,7 +130,8 @@
|
|||
"en": "The surface is <b>grass</b>",
|
||||
"ru": "Поверхность - <b>трава</b>",
|
||||
"fr": "La surface est en <b>herbe</b>",
|
||||
"it": "La superficie è <b>erba</b>"
|
||||
"it": "La superficie è <b>erba</b>",
|
||||
"de": "Die Oberfläche ist <b>Gras</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -139,7 +141,8 @@
|
|||
"en": "The surface is <b>ground</b>",
|
||||
"ru": "Поверхность - <b>земля</b>",
|
||||
"fr": "La surface est en <b>terre</b>",
|
||||
"it": "La superficie è <b>terreno</b>"
|
||||
"it": "La superficie è <b>terreno</b>",
|
||||
"de": "Die Oberfläche ist <b>Erde</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -148,7 +151,8 @@
|
|||
"nl": "De ondergrond is <b>onverhard</b>",
|
||||
"en": "The surface is <b>unpaved</b>",
|
||||
"fr": "La surface est <b>non pavée</b>",
|
||||
"it": "La superficie è <b>non pavimentata</b>"
|
||||
"it": "La superficie è <b>non pavimentata</b>",
|
||||
"de": "Die Oberfläche ist <b>ohne festen Belag</b>"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -159,7 +163,8 @@
|
|||
"en": "The surface is <b>sand</b>",
|
||||
"ru": "Поверхность - <b>песок</b>",
|
||||
"fr": "La surface est en <b>sable</b>",
|
||||
"it": "La superficie è <b>sabbia</b>"
|
||||
"it": "La superficie è <b>sabbia</b>",
|
||||
"de": "Die Oberfläche ist <b>Sand</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -169,7 +174,8 @@
|
|||
"en": "The surface is <b>paving stones</b>",
|
||||
"ru": "Поверхность - <b>брусчатка</b>",
|
||||
"it": "La superficie è <b>pietre irregolari</b>",
|
||||
"fr": "La surface est en <b>pierres pavées</b>"
|
||||
"fr": "La surface est en <b>pierres pavées</b>",
|
||||
"de": "Die Oberfläche ist aus <b>Pflastersteinen</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -179,7 +185,8 @@
|
|||
"en": "The surface is <b>asphalt</b>",
|
||||
"ru": "Поверхность - <b>асфальт</b>",
|
||||
"it": "La superficie è <b>asfalto</b>",
|
||||
"fr": "La surface est en <b>bitume</b>"
|
||||
"fr": "La surface est en <b>bitume</b>",
|
||||
"de": "Die Oberfläche ist <b>Asphalt</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -189,7 +196,8 @@
|
|||
"en": "The surface is <b>concrete</b>",
|
||||
"ru": "Поверхность - <b>бетон</b>",
|
||||
"fr": "La surface est en <b>béton</b>",
|
||||
"it": "La superficie è <b>calcestruzzo</b>"
|
||||
"it": "La superficie è <b>calcestruzzo</b>",
|
||||
"de": "Die Oberfläche ist <b>Beton</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -198,7 +206,8 @@
|
|||
"nl": "De ondergrond is <b>verhard</b>",
|
||||
"en": "The surface is <b>paved</b>",
|
||||
"fr": "La surface est <b>pavée</b>",
|
||||
"it": "La superficie è <b>pavimentata</b>"
|
||||
"it": "La superficie è <b>pavimentata</b>",
|
||||
"de": "Die Oberfläche ist <b>gepflastert</b>"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"fr": "Terrains de sport",
|
||||
"en": "Sport pitches",
|
||||
"ru": "Спортивные площадки",
|
||||
"it": "Campi sportivi"
|
||||
"it": "Campi sportivi",
|
||||
"de": "Sportplätze"
|
||||
},
|
||||
"wayHandling": 1,
|
||||
"minzoom": 12,
|
||||
|
@ -25,7 +26,8 @@
|
|||
"fr": "Terrain de sport",
|
||||
"en": "Sport pitch",
|
||||
"ru": "Спортивная площадка",
|
||||
"it": "Campo sportivo"
|
||||
"it": "Campo sportivo",
|
||||
"de": "Sportplatz"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
|
@ -33,7 +35,8 @@
|
|||
"fr": "Un terrain de sport",
|
||||
"en": "A sport pitch",
|
||||
"it": "Un campo sportivo",
|
||||
"ru": "Спортивная площадка"
|
||||
"ru": "Спортивная площадка",
|
||||
"de": "Ein Sportplatz"
|
||||
},
|
||||
"tagRenderings": [
|
||||
"images",
|
||||
|
@ -42,7 +45,8 @@
|
|||
"nl": "Hier kan men {sport} beoefenen",
|
||||
"fr": "Ici on joue au {sport}",
|
||||
"en": "{sport} is played here",
|
||||
"it": "Qui si gioca a {sport}"
|
||||
"it": "Qui si gioca a {sport}",
|
||||
"de": "Hier wird {sport} gespielt"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "sport"
|
||||
|
@ -51,7 +55,8 @@
|
|||
"nl": "Welke sporten kan men hier beoefenen?",
|
||||
"fr": "À quel sport peut-on jouer ici ?",
|
||||
"en": "Which sport can be played here?",
|
||||
"it": "Quale sport si gioca qui?"
|
||||
"it": "Quale sport si gioca qui?",
|
||||
"de": "Welche Sportarten können hier gespielt werden?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
|
@ -66,7 +71,8 @@
|
|||
"fr": "Ici, on joue au basketball",
|
||||
"en": "Basketball is played here",
|
||||
"it": "Qui si gioca a basket",
|
||||
"ru": "Здесь можно играть в баскетбол"
|
||||
"ru": "Здесь можно играть в баскетбол",
|
||||
"de": "Hier wird Basketball gespielt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -80,7 +86,8 @@
|
|||
"fr": "Ici, on joue au football",
|
||||
"en": "Soccer is played here",
|
||||
"it": "Qui si gioca a calcio",
|
||||
"ru": "Здесь можно играть в футбол"
|
||||
"ru": "Здесь можно играть в футбол",
|
||||
"de": "Hier wird Fußball gespielt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -94,7 +101,8 @@
|
|||
"fr": "C'est une table de ping-pong",
|
||||
"en": "This is a pingpong table",
|
||||
"ru": "Это стол для пинг-понга",
|
||||
"it": "Questo è un tavolo da ping pong"
|
||||
"it": "Questo è un tavolo da ping pong",
|
||||
"de": "Dies ist eine Tischtennisplatte"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -108,7 +116,8 @@
|
|||
"fr": "Ici, on joue au tennis",
|
||||
"en": "Tennis is played here",
|
||||
"it": "Qui si gioca a tennis",
|
||||
"ru": "Здесь можно играть в теннис"
|
||||
"ru": "Здесь можно играть в теннис",
|
||||
"de": "Hier wird Tennis gespielt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -122,7 +131,8 @@
|
|||
"fr": "Ici, on joue au korfball",
|
||||
"en": "Korfball is played here",
|
||||
"it": "Qui si gioca a korfball",
|
||||
"ru": "Здесь можно играть в корфбол"
|
||||
"ru": "Здесь можно играть в корфбол",
|
||||
"de": "Hier wird Kopfball gespielt"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -136,7 +146,8 @@
|
|||
"fr": "Ici, on joue au basketball",
|
||||
"en": "Basketball is played here",
|
||||
"it": "Qui si gioca a basket",
|
||||
"ru": "Здесь можно играть в баскетбол"
|
||||
"ru": "Здесь можно играть в баскетбол",
|
||||
"de": "Hier wird Basketball gespielt"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -149,14 +160,16 @@
|
|||
"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?",
|
||||
"ru": "Какое покрытие на этой спортивной площадке?"
|
||||
"ru": "Какое покрытие на этой спортивной площадке?",
|
||||
"de": "Was ist die Oberfläche dieses Sportplatzes?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "De ondergrond is <b>{surface}</b>",
|
||||
"fr": "La surface est <b>{surface}</b>",
|
||||
"en": "The surface is <b>{surface}</b>",
|
||||
"ru": "Поверхность - <b>{surface}</b>",
|
||||
"it": "La superficie è <b>{surface}</b>"
|
||||
"it": "La superficie è <b>{surface}</b>",
|
||||
"de": "Die Oberfläche ist <b>{surface}</b>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "surface"
|
||||
|
@ -169,7 +182,8 @@
|
|||
"fr": "La surface est de l'<b>herbe</b>",
|
||||
"en": "The surface is <b>grass</b>",
|
||||
"ru": "Поверхность - <b>трава</b>",
|
||||
"it": "La superficie è <b>erba</b>"
|
||||
"it": "La superficie è <b>erba</b>",
|
||||
"de": "Die Oberfläche ist <b>Gras</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -179,7 +193,8 @@
|
|||
"fr": "La surface est du <b>sable</b>",
|
||||
"en": "The surface is <b>sand</b>",
|
||||
"ru": "Поверхность - <b>песок</b>",
|
||||
"it": "La superficie è <b>sabbia</b>"
|
||||
"it": "La superficie è <b>sabbia</b>",
|
||||
"de": "Die Oberfläche ist <b>Sand</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -189,7 +204,8 @@
|
|||
"fr": "La surface est des <b>pavés</b>",
|
||||
"en": "The surface is <b>paving stones</b>",
|
||||
"ru": "Поверхность - <b>брусчатка</b>",
|
||||
"it": "La superficie è <b>pietre irregolari</b>"
|
||||
"it": "La superficie è <b>pietre irregolari</b>",
|
||||
"de": "Die Oberfläche ist aus <b>Pflastersteinen</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -199,7 +215,8 @@
|
|||
"fr": "La surface est de l'<b>asphalte</b>",
|
||||
"en": "The surface is <b>asphalt</b>",
|
||||
"ru": "Поверхность - <b>асфальт</b>",
|
||||
"it": "La superficie è <b>asfalto</b>"
|
||||
"it": "La superficie è <b>asfalto</b>",
|
||||
"de": "Die Oberfläche ist <b>Asphalt</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -209,7 +226,8 @@
|
|||
"fr": "La surface est du <b>béton</b>",
|
||||
"en": "The surface is <b>concrete</b>",
|
||||
"ru": "Поверхность - <b>бетон</b>",
|
||||
"it": "La superficie è <b>calcestruzzo</b>"
|
||||
"it": "La superficie è <b>calcestruzzo</b>",
|
||||
"de": "Die Oberfläche ist <b>Beton</b>"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -222,7 +240,8 @@
|
|||
"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?",
|
||||
"ru": "Есть ли свободный доступ к этой спортивной площадке?"
|
||||
"ru": "Есть ли свободный доступ к этой спортивной площадке?",
|
||||
"de": "Ist dieser Sportplatz öffentlich zugänglich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -232,7 +251,8 @@
|
|||
"fr": "Accessible au public",
|
||||
"en": "Public access",
|
||||
"it": "Aperto al pubblico",
|
||||
"ru": "Свободный доступ"
|
||||
"ru": "Свободный доступ",
|
||||
"de": "Öffentlicher Zugang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -242,7 +262,8 @@
|
|||
"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, ...)",
|
||||
"ru": "Ограниченный доступ (напр., только по записи, в определённые часы, ...)"
|
||||
"ru": "Ограниченный доступ (напр., только по записи, в определённые часы, ...)",
|
||||
"de": "Eingeschränkter Zugang (z. B. nur mit Termin, zu bestimmten Zeiten, ...)"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -252,7 +273,8 @@
|
|||
"fr": "Accessible uniquement aux membres du club",
|
||||
"en": "Only accessible for members of the club",
|
||||
"it": "Accesso limitato ai membri dell'associazione",
|
||||
"ru": "Доступ только членам клуба"
|
||||
"ru": "Доступ только членам клуба",
|
||||
"de": "Zugang nur für Vereinsmitglieder"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -261,7 +283,8 @@
|
|||
"nl": "Privaat en niet toegankelijk",
|
||||
"fr": "Privé - Pas accessible au public",
|
||||
"en": "Private - not accessible to the public",
|
||||
"it": "Privato - non aperto al pubblico"
|
||||
"it": "Privato - non aperto al pubblico",
|
||||
"de": "Privat - kein öffentlicher Zugang"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -273,7 +296,8 @@
|
|||
"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?",
|
||||
"ru": "Нужна ли предварительная запись для доступа на эту спортивную площадку?"
|
||||
"ru": "Нужна ли предварительная запись для доступа на эту спортивную площадку?",
|
||||
"de": "Muss man einen Termin vereinbaren, um diesen Sportplatz zu benutzen?"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
|
@ -289,7 +313,8 @@
|
|||
"nl": "Reserveren is verplicht om gebruik te maken van dit sportterrein",
|
||||
"fr": "Il est obligatoire de réserver pour utiliser ce terrain de sport",
|
||||
"en": "Making an appointment is obligatory to use this sport pitch",
|
||||
"it": "La prenotazione è obbligatoria per usare questo campo sportivo"
|
||||
"it": "La prenotazione è obbligatoria per usare questo campo sportivo",
|
||||
"de": "Für die Nutzung des Sportplatzes ist eine Voranmeldung erforderlich"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -299,7 +324,8 @@
|
|||
"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",
|
||||
"ru": "Желательна предварительная запись для доступа на эту спортивную площадку"
|
||||
"ru": "Желательна предварительная запись для доступа на эту спортивную площадку",
|
||||
"de": "Für die Nutzung des Sportplatzes wird eine Voranmeldung empfohlen"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -309,7 +335,8 @@
|
|||
"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",
|
||||
"ru": "Предварительная запись для доступа на эту спортивную площадку возможна, но не обязательна"
|
||||
"ru": "Предварительная запись для доступа на эту спортивную площадку возможна, но не обязательна",
|
||||
"de": "Eine Voranmeldung ist möglich, aber nicht notwendig, um diesen Sportplatz zu nutzen"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -319,7 +346,8 @@
|
|||
"fr": "On ne peut pas réserver",
|
||||
"en": "Making an appointment is not possible",
|
||||
"it": "Non è possibile prenotare",
|
||||
"ru": "Невозможна предварительная запись"
|
||||
"ru": "Невозможна предварительная запись",
|
||||
"de": "Termine nach Vereinbarung nicht möglich"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -329,7 +357,8 @@
|
|||
"nl": "Wat is het telefoonnummer van de bevoegde dienst of uitbater?",
|
||||
"fr": "Quel est le numéro de téléphone du gérant ?",
|
||||
"en": "What is the phone number of the operator?",
|
||||
"it": "Qual è il numero di telefono del gestore?"
|
||||
"it": "Qual è il numero di telefono del gestore?",
|
||||
"de": "Wie ist die Telefonnummer des Betreibers?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "phone",
|
||||
|
@ -343,7 +372,8 @@
|
|||
"nl": "Wat is het email-adres van de bevoegde dienst of uitbater?",
|
||||
"fr": "Quelle est l'adresse courriel du gérant ?",
|
||||
"en": "What is the email address of the operator?",
|
||||
"it": "Qual è l'indirizzo email del gestore?"
|
||||
"it": "Qual è l'indirizzo email del gestore?",
|
||||
"de": "Wie ist die Email-Adresse des Betreibers?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "email",
|
||||
|
@ -358,7 +388,8 @@
|
|||
"fr": "Quand ce terrain est-il accessible ?",
|
||||
"en": "When is this pitch accessible?",
|
||||
"it": "Quando è aperto questo campo sportivo?",
|
||||
"ru": "В какое время доступна эта площадка?"
|
||||
"ru": "В какое время доступна эта площадка?",
|
||||
"de": "Wann ist dieser Sportplatz zugänglich?"
|
||||
},
|
||||
"render": "Openingsuren: {opening_hours_table()}",
|
||||
"freeform": {
|
||||
|
@ -378,7 +409,8 @@
|
|||
"fr": "Accessible en permanence",
|
||||
"en": "Always accessible",
|
||||
"ru": "Всегда доступен",
|
||||
"it": "Sempre aperto"
|
||||
"it": "Sempre aperto",
|
||||
"de": "Immer zugänglich"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -470,7 +502,8 @@
|
|||
"fr": "Table de ping-pong",
|
||||
"en": "Tabletennis table",
|
||||
"it": "Tavolo da tennistavolo",
|
||||
"ru": "Стол для настольного тенниса"
|
||||
"ru": "Стол для настольного тенниса",
|
||||
"de": "Tischtennisplatte"
|
||||
},
|
||||
"tags": [
|
||||
"leisure=pitch",
|
||||
|
@ -483,7 +516,8 @@
|
|||
"fr": "Terrain de sport",
|
||||
"en": "Sport pitch",
|
||||
"ru": "Спортивная площадка",
|
||||
"it": "Campo sportivo"
|
||||
"it": "Campo sportivo",
|
||||
"de": "Sportplatz"
|
||||
},
|
||||
"tags": [
|
||||
"leisure=pitch",
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"nl": "Bewakingscamera's",
|
||||
"ru": "Камеры наблюдения",
|
||||
"fr": "Caméras de surveillance",
|
||||
"it": "Videocamere di sorveglianza"
|
||||
"it": "Videocamere di sorveglianza",
|
||||
"de": "Überwachungskameras"
|
||||
},
|
||||
"minzoom": 12,
|
||||
"source": {
|
||||
|
@ -28,7 +29,8 @@
|
|||
"nl": "Bewakingscamera",
|
||||
"ru": "Камера наблюдения",
|
||||
"fr": "Caméra de surveillance",
|
||||
"it": "Videocamera di sorveglianza"
|
||||
"it": "Videocamera di sorveglianza",
|
||||
"de": "Überwachungskamera"
|
||||
}
|
||||
},
|
||||
"tagRenderings": [
|
||||
|
@ -39,7 +41,8 @@
|
|||
"nl": "Wat voor soort camera is dit?",
|
||||
"fr": "Quel genre de caméra est-ce ?",
|
||||
"it": "Di che tipo di videocamera si tratta?",
|
||||
"ru": "Какая это камера?"
|
||||
"ru": "Какая это камера?",
|
||||
"de": "Um welche Kameratyp handelt se sich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -52,7 +55,8 @@
|
|||
"en": "A fixed (non-moving) camera",
|
||||
"nl": "Een vaste camera",
|
||||
"fr": "Une caméra fixe (non mobile)",
|
||||
"it": "Una videocamera fissa (non semovente)"
|
||||
"it": "Una videocamera fissa (non semovente)",
|
||||
"de": "Eine fest montierte (nicht bewegliche) Kamera"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -66,7 +70,8 @@
|
|||
"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)",
|
||||
"ru": "Камера с поворотным механизмом"
|
||||
"ru": "Камера с поворотным механизмом",
|
||||
"de": "Eine Kuppelkamera (drehbar)"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -80,7 +85,8 @@
|
|||
"nl": "Een camera die (met een motor) van links naar rechts kan draaien",
|
||||
"ru": "Панорамная камера",
|
||||
"fr": "Une caméra panoramique",
|
||||
"it": "Una videocamera panoramica"
|
||||
"it": "Una videocamera panoramica",
|
||||
"de": "Eine bewegliche Kamera"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -91,7 +97,8 @@
|
|||
"en": "In which geographical direction does this camera film?",
|
||||
"nl": "In welke geografische richting filmt deze camera?",
|
||||
"fr": "Dans quelle direction géographique cette caméra filme-t-elle ?",
|
||||
"it": "In quale direzione geografica punta questa videocamera?"
|
||||
"it": "In quale direzione geografica punta questa videocamera?",
|
||||
"de": "In welche Himmelsrichtung ist diese Kamera ausgerichtet?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Films to a compass heading of {camera:direction}",
|
||||
|
@ -143,13 +150,15 @@
|
|||
"en": "Who operates this CCTV?",
|
||||
"nl": "Wie beheert deze bewakingscamera?",
|
||||
"fr": "Qui exploite ce système de vidéosurveillance ?",
|
||||
"it": "Chi gestisce questa videocamera a circuito chiuso?"
|
||||
"it": "Chi gestisce questa videocamera a circuito chiuso?",
|
||||
"de": "Wer betreibt diese CCTV Kamera?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Operated by {operator}",
|
||||
"nl": "Beheer door {operator}",
|
||||
"fr": "Exploité par {operator}",
|
||||
"it": "È gestita da {operator}"
|
||||
"it": "È gestita da {operator}",
|
||||
"de": "Betrieben von {operator}"
|
||||
},
|
||||
"id": "Operator"
|
||||
},
|
||||
|
@ -158,7 +167,8 @@
|
|||
"en": "What kind of surveillance is this camera",
|
||||
"nl": "Wat soort bewaking wordt hier uitgevoerd?",
|
||||
"fr": "Quel genre de surveillance est cette caméra",
|
||||
"it": "Che cosa sorveglia questa videocamera"
|
||||
"it": "Che cosa sorveglia questa videocamera",
|
||||
"de": "Um was für eine Überwachungskamera handelt es sich"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -184,7 +194,8 @@
|
|||
"en": "An outdoor, yet private area is surveilled (e.g. a parking lot, a fuel station, courtyard, entrance, private driveway, ...)",
|
||||
"nl": "Een buitenruimte met privaat karakter (zoals een privé-oprit, een parking, tankstation, ...)",
|
||||
"fr": "Une zone extérieure, mais privée, est surveillée (par exemple, un parking, une station-service, une cour, une entrée, une allée privée, etc.)",
|
||||
"it": "Sorveglia un'area esterna di proprietà privata (un parcheggio, una stazione di servizio, un cortile, un ingresso, un vialetto privato, ...)"
|
||||
"it": "Sorveglia un'area esterna di proprietà privata (un parcheggio, una stazione di servizio, un cortile, un ingresso, un vialetto privato, ...)",
|
||||
"de": "Ein privater Außenbereich wird überwacht (z. B. ein Parkplatz, eine Tankstelle, ein Innenhof, ein Eingang, eine private Einfahrt, ...)"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -197,7 +208,8 @@
|
|||
"nl": "Een private binnenruimte wordt bewaakt, bv. een winkel, een parkeergarage, ...",
|
||||
"en": "A private indoor area is surveilled, e.g. a shop, a private underground parking, ...",
|
||||
"fr": "Une zone intérieure privée est surveillée, par exemple un magasin, un parking souterrain privé…",
|
||||
"it": "Sorveglia un ambiente interno di proprietà privata, per esempio un negozio, un parcheggio sotterraneo privato, ..."
|
||||
"it": "Sorveglia un ambiente interno di proprietà privata, per esempio un negozio, un parcheggio sotterraneo privato, ...",
|
||||
"de": "Ein privater Innenbereich wird überwacht, z. B. ein Geschäft, eine private Tiefgarage, ..."
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -208,7 +220,8 @@
|
|||
"en": "Is the public space surveilled by this camera an indoor or outdoor space?",
|
||||
"nl": "Bevindt de bewaakte publieke ruimte camera zich binnen of buiten?",
|
||||
"fr": "L'espace public surveillé par cette caméra est-il un espace intérieur ou extérieur ?",
|
||||
"it": "Lo spazio pubblico sorvegliato da questa videocamera è all'aperto o al chiuso?"
|
||||
"it": "Lo spazio pubblico sorvegliato da questa videocamera è all'aperto o al chiuso?",
|
||||
"de": "Handelt es sich bei dem von dieser Kamera überwachten öffentlichen Raum um einen Innen- oder Außenbereich?"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
|
@ -222,7 +235,8 @@
|
|||
"en": "This camera is located indoors",
|
||||
"nl": "Deze camera bevindt zich binnen",
|
||||
"fr": "Cette caméra est située à l'intérieur",
|
||||
"it": "Questa videocamera si trova al chiuso"
|
||||
"it": "Questa videocamera si trova al chiuso",
|
||||
"de": "Diese Kamera befindet sich im Innenraum"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -232,7 +246,8 @@
|
|||
"nl": "Deze camera bevindt zich buiten",
|
||||
"fr": "Cette caméra est située à l'extérieur",
|
||||
"it": "Questa videocamera si trova all'aperto",
|
||||
"ru": "Эта камера расположена снаружи"
|
||||
"ru": "Эта камера расположена снаружи",
|
||||
"de": "Diese Kamera befindet sich im Freien"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -242,7 +257,8 @@
|
|||
"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",
|
||||
"ru": "Возможно, эта камера расположена снаружи"
|
||||
"ru": "Возможно, эта камера расположена снаружи",
|
||||
"de": "Diese Kamera ist möglicherweise im Freien"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -254,13 +270,15 @@
|
|||
"en": "On which level is this camera located?",
|
||||
"nl": "Op welke verdieping bevindt deze camera zich?",
|
||||
"fr": "À quel niveau se trouve cette caméra ?",
|
||||
"it": "A che piano si trova questa videocamera?"
|
||||
"it": "A che piano si trova questa videocamera?",
|
||||
"de": "Auf welcher Ebene befindet sich diese Kamera?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Located on level {level}",
|
||||
"nl": "Bevindt zich op verdieping {level}",
|
||||
"fr": "Situé au niveau {level}",
|
||||
"it": "Si trova al piano {level}"
|
||||
"it": "Si trova al piano {level}",
|
||||
"de": "Befindet sich auf Ebene {level}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "level",
|
||||
|
@ -279,7 +297,8 @@
|
|||
"en": "What exactly is surveilled here?",
|
||||
"nl": "Wat wordt hier precies bewaakt?",
|
||||
"fr": "Qu'est-ce qui est surveillé ici ?",
|
||||
"it": "Che cosa è sorvegliato qui?"
|
||||
"it": "Che cosa è sorvegliato qui?",
|
||||
"de": "Was genau wird hier überwacht?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "surveillance:zone"
|
||||
|
@ -288,7 +307,8 @@
|
|||
"en": " Surveills a {surveillance:zone}",
|
||||
"nl": "Bewaakt een {surveillance:zone}",
|
||||
"fr": " Surveille un(e) {surveillance:zone}",
|
||||
"it": " Sorveglia una {surveillance:zone}"
|
||||
"it": " Sorveglia una {surveillance:zone}",
|
||||
"de": " Überwacht ein/e {surveillance:zone}"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -301,7 +321,8 @@
|
|||
"en": "Surveills a parking",
|
||||
"nl": "Bewaakt een parking",
|
||||
"fr": "Surveille un parking",
|
||||
"it": "Sorveglia un parcheggio"
|
||||
"it": "Sorveglia un parcheggio",
|
||||
"de": "Überwacht einen Parkplatz"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -314,7 +335,8 @@
|
|||
"en": "Surveills the traffic",
|
||||
"nl": "Bewaakt het verkeer",
|
||||
"fr": "Surveille la circulation",
|
||||
"it": "Sorveglia il traffico"
|
||||
"it": "Sorveglia il traffico",
|
||||
"de": "Überwacht den Verkehr"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -327,7 +349,8 @@
|
|||
"en": "Surveills an entrance",
|
||||
"nl": "Bewaakt een ingang",
|
||||
"fr": "Surveille une entrée",
|
||||
"it": "Sorveglia un ingresso"
|
||||
"it": "Sorveglia un ingresso",
|
||||
"de": "Überwacht einen Eingang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -340,7 +363,8 @@
|
|||
"en": "Surveills a corridor",
|
||||
"nl": "Bewaakt een gang",
|
||||
"fr": "Surveille un couloir",
|
||||
"it": "Sorveglia un corridoio"
|
||||
"it": "Sorveglia un corridoio",
|
||||
"de": "Überwacht einen Gang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -353,7 +377,8 @@
|
|||
"en": "Surveills a public tranport platform",
|
||||
"nl": "Bewaakt een perron of bushalte",
|
||||
"fr": "Surveille un quai de transport public",
|
||||
"it": "Sorveglia una pensilina del trasporto pubblico"
|
||||
"it": "Sorveglia una pensilina del trasporto pubblico",
|
||||
"de": "Überwacht eine Haltestelle"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -366,7 +391,8 @@
|
|||
"en": "Surveills a shop",
|
||||
"nl": "Bewaakt een winkel",
|
||||
"fr": "Surveille un magasin",
|
||||
"it": "Sorveglia un negozio"
|
||||
"it": "Sorveglia un negozio",
|
||||
"de": "Überwacht ein Geschäft"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -378,13 +404,15 @@
|
|||
"nl": "Hoe is deze camera geplaatst?",
|
||||
"fr": "Comment cette caméra est-elle placée ?",
|
||||
"it": "Com'è posizionata questa telecamera?",
|
||||
"ru": "Как расположена эта камера?"
|
||||
"ru": "Как расположена эта камера?",
|
||||
"de": "Wie ist diese Kamera montiert?"
|
||||
},
|
||||
"render": {
|
||||
"en": "Mounting method: {mount}",
|
||||
"nl": "Montage: {camera:mount}",
|
||||
"fr": "Méthode de montage : {mount}",
|
||||
"it": "Metodo di montaggio: {mount}"
|
||||
"it": "Metodo di montaggio: {mount}",
|
||||
"de": "Montageart: {mount}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "camera:mount"
|
||||
|
@ -396,7 +424,8 @@
|
|||
"en": "This camera is placed against a wall",
|
||||
"nl": "Deze camera hangt aan een muur",
|
||||
"fr": "Cette caméra est placée contre un mur",
|
||||
"it": "Questa telecamera è posizionata contro un muro"
|
||||
"it": "Questa telecamera è posizionata contro un muro",
|
||||
"de": "Diese Kamera ist an einer Wand montiert"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -405,7 +434,8 @@
|
|||
"en": "This camera is placed one a pole",
|
||||
"nl": "Deze camera staat op een paal",
|
||||
"fr": "Cette caméra est placée sur un poteau",
|
||||
"it": "Questa telecamera è posizionata su un palo"
|
||||
"it": "Questa telecamera è posizionata su un palo",
|
||||
"de": "Diese Kamera ist an einer Stange montiert"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -414,7 +444,8 @@
|
|||
"en": "This camera is placed on the ceiling",
|
||||
"nl": "Deze camera hangt aan het plafond",
|
||||
"fr": "Cette caméra est placée au plafond",
|
||||
"it": "Questa telecamera è posizionata sul soffitto"
|
||||
"it": "Questa telecamera è posizionata sul soffitto",
|
||||
"de": "Diese Kamera ist an der Decke montiert"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -412,21 +412,24 @@
|
|||
"id": "toilet-handwashing",
|
||||
"question": {
|
||||
"en": "Do these toilets have a sink to wash your hands?",
|
||||
"nl": "Hebben deze toiletten een lavabo om de handen te wassen?"
|
||||
"nl": "Hebben deze toiletten een lavabo om de handen te wassen?",
|
||||
"de": "Verfügt diese Toilette über ein Waschbecken?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "toilets:handwashing=yes",
|
||||
"then": {
|
||||
"en": "This toilets have a sink to wash your hands",
|
||||
"nl": "Deze toiletten hebben een lavabo waar men de handen kan wassen"
|
||||
"nl": "Deze toiletten hebben een lavabo waar men de handen kan wassen",
|
||||
"de": "Diese Toilette verfügt über ein Waschbecken"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "toilets:handwashing=no",
|
||||
"then": {
|
||||
"en": "This toilets <b>don't</b> have a sink to wash your hands",
|
||||
"nl": "Deze toiletten hebben <b>geen</b> lavabo waar men de handen kan wassen"
|
||||
"nl": "Deze toiletten hebben <b>geen</b> lavabo waar men de handen kan wassen",
|
||||
"de": "Diese Toilette verfügt über <b>kein</b> Waschbecken"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -435,7 +438,8 @@
|
|||
"id": "toilet-has-paper",
|
||||
"question": {
|
||||
"en": "Does one have to bring their own toilet paper to this toilet?",
|
||||
"nl": "Moet je je eigen toiletpappier meenemen naar deze toilet?"
|
||||
"nl": "Moet je je eigen toiletpappier meenemen naar deze toilet?",
|
||||
"de": "Muss man für diese Toilette sein eigenes Toilettenpapier mitbringen?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -449,7 +453,8 @@
|
|||
"if": "toilets:paper_supplied=no",
|
||||
"then": {
|
||||
"en": "You have to bring your own toilet paper to this toilet",
|
||||
"nl": "Je moet je eigen toiletpapier meebrengen naar deze toilet"
|
||||
"nl": "Je moet je eigen toiletpapier meebrengen naar deze toilet",
|
||||
"de": "Für diese Toilette müssen Sie Ihr eigenes Toilettenpapier mitbringen"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -462,7 +467,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Wheelchair accessible",
|
||||
"nl": "Rolstoel toegankelijk"
|
||||
"nl": "Rolstoel toegankelijk",
|
||||
"de": "Rollstuhlgerecht"
|
||||
},
|
||||
"osmTags": "wheelchair=yes"
|
||||
}
|
||||
|
@ -474,7 +480,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Has a changing table",
|
||||
"nl": "Heeft een luiertafel"
|
||||
"nl": "Heeft een luiertafel",
|
||||
"de": "Hat einen Wickeltisch"
|
||||
},
|
||||
"osmTags": "changing_table=yes"
|
||||
}
|
||||
|
@ -486,7 +493,8 @@
|
|||
{
|
||||
"question": {
|
||||
"en": "Free to use",
|
||||
"nl": "Gratis toegankelijk"
|
||||
"nl": "Gratis toegankelijk",
|
||||
"de": "Nutzung kostenlos"
|
||||
},
|
||||
"osmTags": {
|
||||
"or": [
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"name": {
|
||||
"en": "Trails",
|
||||
"nl": "Wandeltochten",
|
||||
"ru": "Тропы"
|
||||
"ru": "Тропы",
|
||||
"de": "Wanderwege"
|
||||
},
|
||||
"minzoom": 12,
|
||||
"source": {
|
||||
|
@ -23,7 +24,8 @@
|
|||
"render": {
|
||||
"en": "Trail",
|
||||
"nl": "Wandeltocht",
|
||||
"ru": "Тропа"
|
||||
"ru": "Тропа",
|
||||
"de": "Wanderweg"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -38,7 +40,8 @@
|
|||
"id": "trail-length",
|
||||
"render": {
|
||||
"en": "The trail is {_length:km} kilometers long",
|
||||
"nl": "Deze wandeling is {_length:km} kilometer lang"
|
||||
"nl": "Deze wandeling is {_length:km} kilometer lang",
|
||||
"de": "Der Wanderweg ist {_length:km} Kilometer lang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -104,28 +107,32 @@
|
|||
"if": "colour=blue",
|
||||
"then": {
|
||||
"nl": "Blauwe wandeling",
|
||||
"en": "Blue trail"
|
||||
"en": "Blue trail",
|
||||
"de": "Blauer Weg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "colour=red",
|
||||
"then": {
|
||||
"nl": "Rode wandeling",
|
||||
"en": "Red trail"
|
||||
"en": "Red trail",
|
||||
"de": "Roter Weg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "colour=green",
|
||||
"then": {
|
||||
"nl": "Groene wandeling",
|
||||
"en": "Green trail"
|
||||
"en": "Green trail",
|
||||
"de": "Grüner Weg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "colour=yellow",
|
||||
"then": {
|
||||
"nl": "Gele wandeling",
|
||||
"en": "Yellow trail"
|
||||
"en": "Yellow trail",
|
||||
"de": "Gelber Weg"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
"en": "Height: {height}",
|
||||
"it": "Altezza: {height}",
|
||||
"ru": "Высота: {height}",
|
||||
"fr": "Hauteur : {height}"
|
||||
"fr": "Hauteur : {height}",
|
||||
"de": "Höhe: {height}"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
|
@ -69,7 +70,8 @@
|
|||
"en": "Height: {height} m",
|
||||
"it": "Altezza: {height} m",
|
||||
"ru": "Высота: {height} м",
|
||||
"fr": "Hauteur : {height} m"
|
||||
"fr": "Hauteur : {height} m",
|
||||
"de": "Höhe: {height} m"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -80,7 +82,8 @@
|
|||
"nl": "Is dit een naald- of loofboom?",
|
||||
"en": "Is this a broadleaved or needleleaved tree?",
|
||||
"it": "Si tratta di un albero latifoglia o aghifoglia?",
|
||||
"fr": "Cet arbre est-il un feuillu ou un résineux ?"
|
||||
"fr": "Cet arbre est-il un feuillu ou un résineux ?",
|
||||
"de": "Ist dies ein Laub- oder Nadelbaum?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -93,7 +96,8 @@
|
|||
"nl": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Loofboom",
|
||||
"en": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Broadleaved",
|
||||
"it": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Latifoglia",
|
||||
"fr": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Feuillu"
|
||||
"fr": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Feuillu",
|
||||
"de": "<img src=\"./assets/themes/trees/broadleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Laubbaum"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -106,7 +110,8 @@
|
|||
"nl": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Naaldboom",
|
||||
"en": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Needleleaved",
|
||||
"it": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Aghifoglia",
|
||||
"fr": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Résineux"
|
||||
"fr": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Résineux",
|
||||
"de": "<img src=\"./assets/themes/trees/needleleaved.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Nadelbaum"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -119,7 +124,8 @@
|
|||
"nl": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Permanent bladloos",
|
||||
"en": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Permanently leafless",
|
||||
"it": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Privo di foglie (permanente)",
|
||||
"fr": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Sans feuilles (Permanent)"
|
||||
"fr": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Sans feuilles (Permanent)",
|
||||
"de": "<img src=\"./assets/themes/trees/leafless.svg\" style=\"width:1.5em;height:1.5em\" alt=\"\"/> Dauerhaft blattlos"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -131,7 +137,8 @@
|
|||
"nl": "Hoe significant is deze boom? Kies het eerste antwoord dat van toepassing is.",
|
||||
"en": "How significant is this tree? Choose the first answer that applies.",
|
||||
"it": "Quanto significativo è questo albero? Scegli la prima risposta che corrisponde.",
|
||||
"fr": "Quelle est l'importance de cet arbre ? Choisissez la première réponse qui s'applique."
|
||||
"fr": "Quelle est l'importance de cet arbre ? Choisissez la première réponse qui s'applique.",
|
||||
"de": "Wie bedeutsam ist dieser Baum? Wählen Sie die erste Antwort, die zutrifft."
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -144,7 +151,8 @@
|
|||
"nl": "De boom valt op door zijn grootte of prominente locatie. Hij is nuttig voor navigatie.",
|
||||
"en": "The tree is remarkable due to its size or prominent location. It is useful for navigation.",
|
||||
"it": "È un albero notevole per le sue dimensioni o per la posizione prominente. È utile alla navigazione.",
|
||||
"fr": "L'arbre est remarquable en raison de sa taille ou de son emplacement proéminent. Il est utile pour la navigation."
|
||||
"fr": "L'arbre est remarquable en raison de sa taille ou de son emplacement proéminent. Il est utile pour la navigation.",
|
||||
"de": "Der Baum ist aufgrund seiner Größe oder seiner markanten Lage bedeutsam. Er ist nützlich zur Orientierung."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -157,7 +165,8 @@
|
|||
"nl": "De boom is een natuurlijk monument, bijvoorbeeld doordat hij bijzonder oud of van een waardevolle soort is.",
|
||||
"en": "The tree is a natural monument, e.g. because it is especially old, or of a valuable species.",
|
||||
"it": "L’albero è un monumento naturale, ad esempio perché specialmente antico o appartenente a specie importanti.",
|
||||
"fr": "Cet arbre est un monument naturel (ex : âge, espèce, etc…)"
|
||||
"fr": "Cet arbre est un monument naturel (ex : âge, espèce, etc…)",
|
||||
"de": "Der Baum ist ein Naturdenkmal, z. B. weil er besonders alt ist oder zu einer wertvollen Art gehört."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -170,7 +179,8 @@
|
|||
"nl": "De boom wordt voor landbouwdoeleinden gebruikt, bijvoorbeeld in een boomgaard.",
|
||||
"en": "The tree is used for agricultural purposes, e.g. in an orchard.",
|
||||
"it": "L’albero è usato per scopi agricoli, ad esempio in un frutteto.",
|
||||
"fr": "Cet arbre est utilisé à but d’agriculture (ex : dans un verger)"
|
||||
"fr": "Cet arbre est utilisé à but d’agriculture (ex : dans un verger)",
|
||||
"de": "Der Baum wird für landwirtschaftliche Zwecke genutzt, z. B. in einer Obstplantage."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -183,7 +193,8 @@
|
|||
"nl": "De boom staat in een park of dergelijke (begraafplaats, schoolterrein, …).",
|
||||
"en": "The tree is in a park or similar (cemetery, school grounds, …).",
|
||||
"it": "L’albero è in un parco o qualcosa di simile (cimitero, aree didattiche, etc.).",
|
||||
"fr": "Cet arbre est dans un parc ou une aire similaire (ex : cimetière, cour d’école, …)."
|
||||
"fr": "Cet arbre est dans un parc ou une aire similaire (ex : cimetière, cour d’école, …).",
|
||||
"de": "Der Baum steht in einem Park oder ähnlichem (Friedhof, Schulgelände, ...)."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -209,7 +220,8 @@
|
|||
"nl": "Dit is een laanboom.",
|
||||
"en": "This is a tree along an avenue.",
|
||||
"it": "Fa parte di un viale alberato.",
|
||||
"fr": "C'est un arbre le long d'une avenue."
|
||||
"fr": "C'est un arbre le long d'une avenue.",
|
||||
"de": "Dieser Baum steht entlang einer Straße."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -235,7 +247,8 @@
|
|||
"nl": "De boom staat buiten een woonkern.",
|
||||
"en": "The tree is outside of an urban area.",
|
||||
"it": "L’albero si trova fuori dall’area urbana.",
|
||||
"fr": "Cet arbre est en zone rurale."
|
||||
"fr": "Cet arbre est en zone rurale.",
|
||||
"de": "Dieser Baum steht außerhalb eines städtischen Gebiets."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -247,7 +260,8 @@
|
|||
"en": "Is this tree evergreen or deciduous?",
|
||||
"it": "È un sempreverde o caduco?",
|
||||
"ru": "Это дерево вечнозелёное или листопадное?",
|
||||
"fr": "L’arbre est-il à feuillage persistant ou caduc ?"
|
||||
"fr": "L’arbre est-il à feuillage persistant ou caduc ?",
|
||||
"de": "Ist dies ein Nadelbaum oder ein Laubbaum?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -261,7 +275,8 @@
|
|||
"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.",
|
||||
"ru": "Листопадное: у дерева опадают листья в определённое время года.",
|
||||
"fr": "Caduc : l’arbre perd son feuillage une partie de l’année."
|
||||
"fr": "Caduc : l’arbre perd son feuillage une partie de l’année.",
|
||||
"de": "Laubabwerfend: Der Baum verliert für eine gewisse Zeit des Jahres seine Blätter."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -275,7 +290,8 @@
|
|||
"en": "Evergreen.",
|
||||
"it": "Sempreverde.",
|
||||
"fr": "À feuilles persistantes.",
|
||||
"ru": "Вечнозелёное."
|
||||
"ru": "Вечнозелёное.",
|
||||
"de": "immergrüner Baum."
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -292,14 +308,16 @@
|
|||
"it": "Nome: {name}",
|
||||
"ru": "Название: {name}",
|
||||
"fr": "Nom : {name}",
|
||||
"id": "Nama: {name}"
|
||||
"id": "Nama: {name}",
|
||||
"de": "Name: {name}"
|
||||
},
|
||||
"question": {
|
||||
"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 ?",
|
||||
"ru": "Есть ли у этого дерева название?"
|
||||
"ru": "Есть ли у этого дерева название?",
|
||||
"de": "Hat der Baum einen Namen?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name",
|
||||
|
@ -320,7 +338,8 @@
|
|||
"en": "The tree does not have a name.",
|
||||
"it": "L’albero non ha un nome.",
|
||||
"fr": "L'arbre n'a pas de nom.",
|
||||
"ru": "У этого дерева нет названия."
|
||||
"ru": "У этого дерева нет названия.",
|
||||
"de": "Der Baum hat keinen Namen."
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -339,7 +358,8 @@
|
|||
"nl": "Is deze boom erkend als erfgoed?",
|
||||
"en": "Is this tree registered heritage?",
|
||||
"it": "Quest’albero è registrato come patrimonio?",
|
||||
"fr": "Cet arbre est-il inscrit au patrimoine ?"
|
||||
"fr": "Cet arbre est-il inscrit au patrimoine ?",
|
||||
"de": "Ist dieser Baum ein Naturdenkmal?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -353,7 +373,8 @@
|
|||
"nl": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Erkend als houtig erfgoed door Onroerend Erfgoed Vlaanderen",
|
||||
"en": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Registered as heritage by <i>Onroerend Erfgoed</i> Flanders",
|
||||
"it": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/>Registrato come patrimonio da <i>Onroerend Erfgoed</i> Flanders",
|
||||
"fr": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Fait partie du patrimoine par <i>Onroerend Erfgoed</i>"
|
||||
"fr": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Fait partie du patrimoine par <i>Onroerend Erfgoed</i>",
|
||||
"de": "<img src=\"./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg\" style=\"width:0.85em;height:1em;vertical-align:middle\" alt=\"\"/> Als Denkmal registriert von der <i>Onroerend Erfgoed</i> Flandern"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -367,7 +388,8 @@
|
|||
"nl": "Erkend als natuurlijk erfgoed door Directie Cultureel Erfgoed Brussel",
|
||||
"en": "Registered as heritage by <i>Direction du Patrimoine culturel</i> Brussels",
|
||||
"it": "Registrato come patrimonio da <i>Direction du Patrimoine culturel</i> di Bruxelles",
|
||||
"fr": "Enregistré comme patrimoine par la <i>Direction du Patrimoine culturel</i> Bruxelles"
|
||||
"fr": "Enregistré comme patrimoine par la <i>Direction du Patrimoine culturel</i> Bruxelles",
|
||||
"de": "Als Denkmal registriert von der <i>Direction du Patrimoine culturel</i> Brüssel"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -395,7 +417,8 @@
|
|||
"nl": "Niet erkend als erfgoed",
|
||||
"en": "Not registered as heritage",
|
||||
"it": "Non è registrato come patrimonio",
|
||||
"fr": "Non enregistré comme patrimoine"
|
||||
"fr": "Non enregistré comme patrimoine",
|
||||
"de": "Nicht als Denkmal registriert"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -432,7 +455,8 @@
|
|||
"nl": "Wat is het ID uitgegeven door Onroerend Erfgoed Vlaanderen?",
|
||||
"en": "What is the ID issued by Onroerend Erfgoed Flanders?",
|
||||
"it": "Qual è l’ID rilasciato da Onroerend Erfgoed Flanders?",
|
||||
"fr": "Quel est son identifiant donné par Onroerend Erfgoed ?"
|
||||
"fr": "Quel est son identifiant donné par Onroerend Erfgoed ?",
|
||||
"de": "Wie lautet die Kennung der Onroerend Erfgoed Flanders?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "ref:OnroerendErfgoed",
|
||||
|
@ -458,7 +482,8 @@
|
|||
"nl": "Wat is het Wikidata-ID van deze boom?",
|
||||
"en": "What is the Wikidata ID for this tree?",
|
||||
"it": "Qual è l’ID Wikidata per questo albero?",
|
||||
"fr": "Quel est l'identifiant Wikidata de cet arbre ?"
|
||||
"fr": "Quel est l'identifiant Wikidata de cet arbre ?",
|
||||
"de": "Was ist das passende Wikidata Element zu diesem Baum?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "wikidata",
|
||||
|
@ -516,13 +541,15 @@
|
|||
"en": "Broadleaved tree",
|
||||
"it": "Albero latifoglia",
|
||||
"fr": "Arbre feuillu",
|
||||
"ru": "Лиственное дерево"
|
||||
"ru": "Лиственное дерево",
|
||||
"de": "Laubbaum"
|
||||
},
|
||||
"description": {
|
||||
"nl": "Een boom van een soort die blaadjes heeft, bijvoorbeeld eik of populier.",
|
||||
"en": "A tree of a species with leaves, such as oak or populus.",
|
||||
"it": "Un albero di una specie con foglie larghe come la quercia o il pioppo.",
|
||||
"fr": "Un arbre d'une espèce avec de larges feuilles, comme le chêne ou le peuplier."
|
||||
"fr": "Un arbre d'une espèce avec de larges feuilles, comme le chêne ou le peuplier.",
|
||||
"de": "Ein Baum mit Blättern, z. B. Eiche oder Buche."
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "photo"
|
||||
|
@ -538,14 +565,16 @@
|
|||
"en": "Needleleaved tree",
|
||||
"it": "Albero aghifoglia",
|
||||
"ru": "Хвойное дерево",
|
||||
"fr": "Arbre résineux"
|
||||
"fr": "Arbre résineux",
|
||||
"de": "Nadelbaum"
|
||||
},
|
||||
"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.",
|
||||
"ru": "Дерево с хвоей (иглами), например, сосна или ель.",
|
||||
"fr": "Une espèce d’arbre avec des épines comme le pin ou l’épicéa."
|
||||
"fr": "Une espèce d’arbre avec des épines comme le pin ou l’épicéa.",
|
||||
"de": "Ein Baum mit Nadeln, z. B. Kiefer oder Fichte."
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "photo"
|
||||
|
@ -569,7 +598,8 @@
|
|||
"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.",
|
||||
"ru": "Если вы не уверены в том, лиственное это дерево или хвойное."
|
||||
"ru": "Если вы не уверены в том, лиственное это дерево или хвойное.",
|
||||
"de": "Wenn Sie nicht sicher sind, ob es sich um einen Laubbaum oder einen Nadelbaum handelt."
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "photo"
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
},
|
||||
"description": {
|
||||
"en": "A visitor center offers information about a specific attraction or place of interest where it is located.",
|
||||
"nl": "Een bezoekerscentrum biedt informatie over een specifieke attractie of bezienswaardigheid waar het is gevestigd."
|
||||
"nl": "Een bezoekerscentrum biedt informatie over een specifieke attractie of bezienswaardigheid waar het is gevestigd.",
|
||||
"de": "Ein Besucherzentrum bietet Informationen über eine bestimmte Attraktion oder Sehenswürdigkeit, an der es sich befindet."
|
||||
},
|
||||
"tagRenderings": [],
|
||||
"icon": {
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"name": {
|
||||
"en": "Waste Basket",
|
||||
"nl": "Vuilnisbak",
|
||||
"ru": "Контейнер для мусора"
|
||||
"ru": "Контейнер для мусора",
|
||||
"de": "Abfalleimer"
|
||||
},
|
||||
"minzoom": 17,
|
||||
"source": {
|
||||
|
@ -17,7 +18,8 @@
|
|||
"render": {
|
||||
"en": "Waste Basket",
|
||||
"nl": "Vuilnisbak",
|
||||
"ru": "Контейнер для мусора"
|
||||
"ru": "Контейнер для мусора",
|
||||
"de": "Abfalleimer"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
|
@ -30,7 +32,8 @@
|
|||
"id": "waste-basket-waste-types",
|
||||
"question": {
|
||||
"en": "What kind of waste basket is this?",
|
||||
"nl": "Wat voor soort vuilnisbak is dit?"
|
||||
"nl": "Wat voor soort vuilnisbak is dit?",
|
||||
"de": "Um was für einen Abfalleimer handelt es sich?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
|
@ -38,7 +41,8 @@
|
|||
"if": "waste=",
|
||||
"then": {
|
||||
"en": "A waste basket for general waste",
|
||||
"nl": "Een vuilnisbak voor zwerfvuil"
|
||||
"nl": "Een vuilnisbak voor zwerfvuil",
|
||||
"de": "Ein Abfalleimer für allgemeinen Müll"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -46,28 +50,32 @@
|
|||
"if": "waste=trash",
|
||||
"then": {
|
||||
"en": "A waste basket for general waste",
|
||||
"nl": "Een vuilnisbak voor zwerfvuil"
|
||||
"nl": "Een vuilnisbak voor zwerfvuil",
|
||||
"de": "Ein Abfalleimer für allgemeinen Müll"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "waste=dog_excrement",
|
||||
"then": {
|
||||
"en": "A waste basket for dog excrements",
|
||||
"nl": "Een vuilnisbak specifiek voor hondenuitwerpselen"
|
||||
"nl": "Een vuilnisbak specifiek voor hondenuitwerpselen",
|
||||
"de": "Ein Abfalleimer für Hundekot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "waste=cigarettes",
|
||||
"then": {
|
||||
"en": "A waste basket for cigarettes",
|
||||
"nl": "Een vuilnisbak voor sigarettenpeuken"
|
||||
"nl": "Een vuilnisbak voor sigarettenpeuken",
|
||||
"de": "Mülleimer für Zigaretten"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "waste=drugs",
|
||||
"then": {
|
||||
"en": "A waste basket for drugs",
|
||||
"nl": "Een vuilnisbak voor (vervallen) medicatie en drugs"
|
||||
"nl": "Een vuilnisbak voor (vervallen) medicatie en drugs",
|
||||
"de": "Mülleimer für Drogen"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -82,7 +90,9 @@
|
|||
{
|
||||
"id": "dispensing_dog_bags",
|
||||
"question": {
|
||||
"en": "Does this waste basket have a dispenser for dog excrement bags?"
|
||||
"en": "Does this waste basket have a dispenser for dog excrement bags?",
|
||||
"nl": "Heeft deze vuilnisbak een verdeler voor hondenpoepzakjes?",
|
||||
"de": "Verfügt dieser Abfalleimer über einen Spender für (Hunde-)Kotbeutel?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
@ -100,7 +110,9 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This waste basket has a dispenser for (dog) excrement bags"
|
||||
"en": "This waste basket has a dispenser for (dog) excrement bags",
|
||||
"nl": "Deze vuilnisbak heeft een verdeler voor hondenpoepzakjes",
|
||||
"de": "Dieser Abfalleimer verfügt über einen Spender für (Hunde-)Kotbeutel"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -111,13 +123,17 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This waste basket <b>does not</b> have a dispenser for (dog) excrement bags"
|
||||
"en": "This waste basket <b>does not</b> have a dispenser for (dog) excrement bags",
|
||||
"nl": "Deze vuilbak heeft <b>geen</b> verdeler voor hondenpoepzakjes",
|
||||
"de": "Dieser Abfalleimer <b>hat keinen</b> Spender für (Hunde-)Kotbeutel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "vending=",
|
||||
"then": {
|
||||
"en": "This waste basket <b>does not</b> have a dispenser for (dog) excrement bags"
|
||||
"en": "This waste basket <b>does not</b> have a dispenser for (dog) excrement bags",
|
||||
"nl": "Deze vuilnisbak heeft <b>geen</b> verdeler voor hondenpoepzakjes",
|
||||
"de": "Dieser Abfalleimer <b>hat keinen</b> Spender für (Hunde-)Kotbeutel"
|
||||
},
|
||||
"hideInAnwer": true
|
||||
}
|
||||
|
@ -142,7 +158,8 @@
|
|||
"then": {
|
||||
"en": "Waste Basket",
|
||||
"nl": "Vuilnisbak",
|
||||
"ru": "Контейнер для мусора"
|
||||
"ru": "Контейнер для мусора",
|
||||
"de": "Abfalleimer"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -158,7 +175,8 @@
|
|||
"title": {
|
||||
"en": "Waste Basket",
|
||||
"nl": "Vuilnisbak",
|
||||
"ru": "Контейнер для мусора"
|
||||
"ru": "Контейнер для мусора",
|
||||
"de": "Abfalleimer"
|
||||
},
|
||||
"presiceInput": {
|
||||
"preferredBackground": "photo"
|
||||
|
|
|
@ -2,83 +2,80 @@
|
|||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 26.458333 26.458334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="close.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<defs
|
||||
id="defs2"/>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="-12.514944"
|
||||
inkscape:cy="118.94409"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1">
|
||||
<sodipodi:guide
|
||||
position="13.229167,23.859748"
|
||||
orientation="1,0"
|
||||
id="guide815"
|
||||
inkscape:locked="false"/>
|
||||
<sodipodi:guide
|
||||
position="14.944824,13.229167"
|
||||
orientation="0,1"
|
||||
id="guide817"
|
||||
inkscape:locked="false"/>
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-270.54165)">
|
||||
<g
|
||||
id="g836"
|
||||
transform="matrix(1.7481308,0,0,1.7481308,-10.001295,-212.27744)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path815"
|
||||
d="M 18.972892,289.3838 7.7469352,278.15784 v 0"
|
||||
style="fill:none;stroke:#000000;stroke-width:3.4395833;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path815-3"
|
||||
d="M 18.98982,278.10371 7.7638604,289.32967 v 0"
|
||||
style="fill:none;stroke:#000000;stroke-width:3.4395833;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
</g>
|
||||
</g>
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 26.458333 26.458334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="close.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="-14.459488"
|
||||
inkscape:cy="118.94409"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1003"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1">
|
||||
<sodipodi:guide
|
||||
position="13.229167,23.859748"
|
||||
orientation="1,0"
|
||||
id="guide815"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="14.944824,13.229167"
|
||||
orientation="0,1"
|
||||
id="guide817"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-270.54165)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.0128417;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 23.165802,293.60329 3.541361,273.97885 v 0"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:6.01292087;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 23.195394,273.88422 3.5709485,293.50867 v 0"
|
||||
id="path815-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.5 KiB |
|
@ -6,14 +6,18 @@
|
|||
"render": "{wikipedia():max-height:25rem}",
|
||||
"question": {
|
||||
"en": "What is the corresponding Wikidata entity?",
|
||||
"nl": "Welk Wikidata-item komt overeen met dit object?"
|
||||
"nl": "Welk Wikidata-item komt overeen met dit object?",
|
||||
"de": "Was ist das entsprechende Wikidata Element?",
|
||||
"pt": "Qual é a entidade Wikidata correspondente?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "wikidata=",
|
||||
"then": {
|
||||
"en": "No Wikipedia page has been linked yet",
|
||||
"nl": "Er werd nog geen Wikipedia-pagina gekoppeld"
|
||||
"nl": "Er werd nog geen Wikipedia-pagina gekoppeld",
|
||||
"de": "Es wurde noch keine Wikipedia-Seite verlinkt",
|
||||
"pt": "Ainda não foi vinculada nenhuma página da Wikipédia"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
|
@ -64,14 +68,18 @@
|
|||
"render": "<a href='https://wikipedia.org/wiki/{wikipedia}' target='_blank'><img src='./assets/wikipedia.svg' alt='WP'/></a>",
|
||||
"question": {
|
||||
"en": "What is the corresponding item on Wikipedia?",
|
||||
"nl": "Welk Wikipedia-artikel beschrijft dit object?"
|
||||
"nl": "Welk Wikipedia-artikel beschrijft dit object?",
|
||||
"de": "Was ist der entsprechende Artikel auf Wikipedia?",
|
||||
"pt": "Qual é o item correspondente na Wikipédia?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "wikidata=",
|
||||
"then": {
|
||||
"en": "Not linked with Wikipedia",
|
||||
"nl": "Nog geen Wikipedia-artikel bekend"
|
||||
"nl": "Nog geen Wikipedia-artikel bekend",
|
||||
"de": "Nicht mit Wikipedia verknüpft",
|
||||
"pt": "Não vinculado à Wikipédia"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -131,7 +139,8 @@
|
|||
"en": "Is this place accessible with a wheelchair?",
|
||||
"pt": "Este lugar é acessível a utilizadores de cadeiras de rodas?",
|
||||
"pt_BR": "Este lugar é acessível com uma cadeira de rodas?",
|
||||
"de": "Ist dieser Ort mit einem Rollstuhl zugänglich?"
|
||||
"de": "Ist dieser Ort mit einem Rollstuhl zugänglich?",
|
||||
"fr": "Est-ce que cet endroit est accessible en chaise roulante ?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -145,7 +154,7 @@
|
|||
"en": "This place is specially adapated for wheelchair users",
|
||||
"pt": "Este lugar está especialmente adaptado para utilizadores de cadeira de rodas",
|
||||
"pt_BR": "Este lugar é especialmente adaptado para usuários de cadeira de rodas",
|
||||
"de": "Dieser Ort ist speziell für Rollstuhlfahrer eingerichtet."
|
||||
"de": "Dieser Ort ist speziell für Rollstuhlfahrer eingerichtet"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -173,7 +182,8 @@
|
|||
"en": "It is possible to reach this place in a wheelchair, but it is not easy",
|
||||
"pt": "É possível chegar a este local em cadeira de rodas, mas não é fácil",
|
||||
"pt_BR": "É possível chegar a esse local em uma cadeira de rodas, mas não é fácil",
|
||||
"de": "Es ist möglich, diesen Ort mit einem Rollstuhl zu erreichen, aber es ist nicht einfach"
|
||||
"de": "Es ist möglich, diesen Ort mit einem Rollstuhl zu erreichen, aber es ist nicht einfach",
|
||||
"fr": "Il est possible d'accéder à cet endroit en chaise roulante, mais ce n'est pas facile"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -187,7 +197,8 @@
|
|||
"en": "This place is not reachable with a wheelchair",
|
||||
"pt": "Este lugar não é acessível com uma cadeira de rodas",
|
||||
"pt_BR": "Este lugar não é alcançável com uma cadeira de rodas",
|
||||
"de": "Dieser Ort ist nicht mit einem Rollstuhl erreichbar"
|
||||
"de": "Dieser Ort ist nicht mit einem Rollstuhl erreichbar",
|
||||
"fr": "Cet endroit n'est pas accessible en chaise roulante"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -197,7 +208,8 @@
|
|||
"en": "Are dogs allowed in this business?",
|
||||
"nl": "Zijn honden toegelaten in deze zaak?",
|
||||
"pt": "Os cães são permitidos neste estabelecimento?",
|
||||
"de": "Sind Hunde in diesem Geschäft erlaubt?"
|
||||
"de": "Sind Hunde in diesem Geschäft erlaubt?",
|
||||
"fr": "Est-ce que les chiens sont admis ici ?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -206,7 +218,8 @@
|
|||
"en": "Dogs are allowed",
|
||||
"nl": "honden zijn toegelaten",
|
||||
"pt": "Os cães são permitidos",
|
||||
"de": "Hunde sind erlaubt"
|
||||
"de": "Hunde sind erlaubt",
|
||||
"fr": "Chiens admis"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -215,7 +228,8 @@
|
|||
"en": "Dogs are <b>not</b> allowed",
|
||||
"nl": "honden zijn <b>niet</b> toegelaten",
|
||||
"pt": "Os cães <b>não</b> são permitidos",
|
||||
"de": "Hunde sind <b>nicht</b> erlaubt"
|
||||
"de": "Hunde sind <b>nicht</b> erlaubt",
|
||||
"fr": "Les chiens <b>ne</b> sont <b>pas</b> admis"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -224,7 +238,8 @@
|
|||
"en": "Dogs are allowed, but they have to be leashed",
|
||||
"nl": "honden zijn <b>enkel aan de leiband</b> welkom",
|
||||
"pt": "Os cães são permitidos, mas têm de ser presos pela trela",
|
||||
"de": "Hunde sind erlaubt, müssen aber angeleint sein."
|
||||
"de": "Hunde sind erlaubt, müssen aber angeleint sein",
|
||||
"fr": "Les chiens sont admis, mais ils doivent être tenus en laisse"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -233,7 +248,8 @@
|
|||
"en": "Dogs are allowed and can run around freely",
|
||||
"nl": "honden zijn welkom en mogen vrij rondlopen",
|
||||
"pt": "Os cães são permitidos e podem correr livremente",
|
||||
"de": "Hunde sind erlaubt und können frei herumlaufen"
|
||||
"de": "Hunde sind erlaubt und können frei herumlaufen",
|
||||
"fr": "Les chiens sont admis et peuvent circuler librement"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -298,7 +314,8 @@
|
|||
"pt": "Que métodos de pagamento são aceites aqui?",
|
||||
"pt_BR": "Quais métodos de pagamento são aceitos aqui?",
|
||||
"id": "Metode pembayaran manakah yang di terima disini?",
|
||||
"de": "Welche Zahlungsmethoden werden hier akzeptiert?"
|
||||
"de": "Welche Zahlungsmethoden werden hier akzeptiert?",
|
||||
"fr": "Quelles sont les méthodes de paiement acceptées ici ?"
|
||||
},
|
||||
"multiAnswer": true,
|
||||
"mappings": [
|
||||
|
@ -311,7 +328,8 @@
|
|||
"pt": "Aceitam pagamento com dinheiro aqui",
|
||||
"pt_BR": "Dinheiro é aceito aqui",
|
||||
"id": "Disini menerima pembayaran tunai",
|
||||
"de": "Hier wird Bargeld akzeptiert"
|
||||
"de": "Hier wird Bargeld akzeptiert",
|
||||
"fr": "Paiement en liquide accepté"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -323,7 +341,8 @@
|
|||
"pt": "Aceitam pagamento com cartões bancários aqui",
|
||||
"pt_BR": "Cartões de pagamento são aceitos aqui",
|
||||
"id": "Disini menerima pembayaran dengan kartu",
|
||||
"de": "Hier werden Zahlungskarten akzeptiert"
|
||||
"de": "Hier werden Zahlungskarten akzeptiert",
|
||||
"fr": "Paiement par carte accepté"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
"startLat": 51.25634,
|
||||
"startLon": 3.195682,
|
||||
"startZoom": 12,
|
||||
"clustering": {
|
||||
"maxZoom": 0
|
||||
},
|
||||
"layers": [
|
||||
"defibrillator",
|
||||
{
|
||||
|
|
|
@ -58,6 +58,5 @@
|
|||
"bench",
|
||||
"bench_at_pt",
|
||||
"picnic_table"
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -42,7 +42,6 @@
|
|||
"startLon": 0,
|
||||
"startZoom": 1,
|
||||
"widenFactor": 1.5,
|
||||
"roamingRenderings": [],
|
||||
"layers": [
|
||||
{
|
||||
"builtin": "bicycle_library",
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"startLon": 0,
|
||||
"startZoom": 1,
|
||||
"widenFactor": 1,
|
||||
"roamingRenderings": [],
|
||||
"layers": [
|
||||
"public_bookcase"
|
||||
]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"id": "buurtnatuur",
|
||||
"title": {
|
||||
"#": "DO NOT TRANSLATE THIS THEME - this one is only meant to be in dutch!",
|
||||
"nl": "Breng jouw buurtnatuur in kaart"
|
||||
},
|
||||
"shortDescription": {
|
||||
|
@ -343,263 +342,265 @@
|
|||
},
|
||||
"viewpoint"
|
||||
],
|
||||
"roamingRenderings": [
|
||||
{
|
||||
"#": "Access tag",
|
||||
"condition": {
|
||||
"and": [
|
||||
"tourism!~viewpoint"
|
||||
"overrideAll": {
|
||||
"tagRenderings+": [
|
||||
{
|
||||
"id": "Access tag",
|
||||
"condition": {
|
||||
"and": [
|
||||
"tourism!~viewpoint"
|
||||
]
|
||||
},
|
||||
"render": {
|
||||
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Is dit gebied toegankelijk?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "access:description",
|
||||
"addExtraTags": [
|
||||
"access="
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=",
|
||||
"leisure=park"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied is vrij toegankelijk"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=yes",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Vrij toegankelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=no",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Niet toegankelijk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=private",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Niet toegankelijk, want privégebied"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=permissive",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Toegankelijk, ondanks dat het privegebied is"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=guided",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Enkel toegankelijk met een gids of tijdens een activiteit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=yes",
|
||||
"fee=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Toegankelijk mits betaling"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"render": {
|
||||
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Is dit gebied toegankelijk?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "access:description",
|
||||
"addExtraTags": [
|
||||
"access="
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=",
|
||||
"leisure=park"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied is vrij toegankelijk"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
{
|
||||
"id": "Operator tag",
|
||||
"render": {
|
||||
"nl": "Beheer door {operator}"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=yes",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Vrij toegankelijk"
|
||||
}
|
||||
"question": {
|
||||
"nl": "Wie beheert dit gebied?"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=no",
|
||||
"fee="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Niet toegankelijk"
|
||||
}
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=private",
|
||||
"fee="
|
||||
]
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"leisure=park",
|
||||
"operator="
|
||||
]
|
||||
},
|
||||
"then": "Beheer door de gemeente",
|
||||
"hideInAnswer": true
|
||||
},
|
||||
"then": {
|
||||
"nl": "Niet toegankelijk, want privégebied"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=permissive",
|
||||
"fee="
|
||||
]
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator=Natuurpunt"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door Natuurpunt"
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"nl": "Toegankelijk, ondanks dat het privegebied is"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=guided",
|
||||
"fee="
|
||||
]
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator~(n|N)atuurpunt.*"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door {operator}"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
"then": {
|
||||
"nl": "Enkel toegankelijk met een gids of tijdens een activiteit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=yes",
|
||||
"fee=yes"
|
||||
]
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator=Agentschap Natuur en Bos"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/ANB.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"nl": "Toegankelijk mits betaling"
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator:type=private"
|
||||
]
|
||||
},
|
||||
"then": "Beheer door een privépersoon",
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator:type=private",
|
||||
"operator="
|
||||
]
|
||||
},
|
||||
"then": "Beheer door een privépersoon"
|
||||
}
|
||||
],
|
||||
"condition": {
|
||||
"and": [
|
||||
"leisure!~park",
|
||||
"tourism!~viewpoint"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"#": "Operator tag",
|
||||
"render": {
|
||||
"nl": "Beheer door {operator}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wie beheert dit gebied?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"leisure=park",
|
||||
"operator="
|
||||
]
|
||||
},
|
||||
"then": "Beheer door de gemeente",
|
||||
"hideInAnswer": true
|
||||
{
|
||||
"id": "Non-editable description {description}",
|
||||
"render": {
|
||||
"nl": "Extra info: <i>{description}</i>"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator=Natuurpunt"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door Natuurpunt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator~(n|N)atuurpunt.*"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door {operator}"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator=Agentschap Natuur en Bos"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/themes/buurtnatuur/ANB.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator:type=private"
|
||||
]
|
||||
},
|
||||
"then": "Beheer door een privépersoon",
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"operator:type=private",
|
||||
"operator="
|
||||
]
|
||||
},
|
||||
"then": "Beheer door een privépersoon"
|
||||
"freeform": {
|
||||
"key": "description"
|
||||
}
|
||||
],
|
||||
"condition": {
|
||||
"and": [
|
||||
"leisure!~park",
|
||||
"tourism!~viewpoint"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"#": "Non-editable description {description}",
|
||||
"render": {
|
||||
"nl": "Extra info: <i>{description}</i>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "description"
|
||||
}
|
||||
},
|
||||
{
|
||||
"#": "Editable description {description:0}",
|
||||
"question": "Is er extra info die je kwijt wil?<br/><span class='subtle'>De <i>naam</i> van het gebied wordt in de volgende vraag gesteld</span>",
|
||||
"render": {
|
||||
"nl": "Extra info via buurtnatuur.be: <i>{description:0}</i>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "description:0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"#": "Name:nl-tag",
|
||||
"render": {
|
||||
"nl": "Dit gebied heet {name:nl}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wat is de Nederlandstalige naam van dit gebied?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name:nl"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
"name:nl~*",
|
||||
"viewpoint!~tourism"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"#": "Name tag",
|
||||
"render": {
|
||||
"nl": "Dit gebied heet {name}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wat is de naam van dit gebied?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name",
|
||||
"addExtraTags": [
|
||||
"noname="
|
||||
]
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
"name:nl=",
|
||||
"tourism!~viewpoint"
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"noname=yes",
|
||||
"name="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied heeft geen naam"
|
||||
}
|
||||
{
|
||||
"id": "Editable description {description:0}",
|
||||
"question": "Is er extra info die je kwijt wil?<br/><span class='subtle'>De <i>naam</i> van het gebied wordt in de volgende vraag gesteld</span>",
|
||||
"render": {
|
||||
"nl": "Extra info via buurtnatuur.be: <i>{description:0}</i>"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "description:0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Name:nl-tag",
|
||||
"render": {
|
||||
"nl": "Dit gebied heet {name:nl}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wat is de Nederlandstalige naam van dit gebied?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name:nl"
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
"name:nl~*",
|
||||
"viewpoint!~tourism"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Name tag",
|
||||
"render": {
|
||||
"nl": "Dit gebied heet {name}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Wat is de naam van dit gebied?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "name",
|
||||
"addExtraTags": [
|
||||
"noname="
|
||||
]
|
||||
},
|
||||
"condition": {
|
||||
"and": [
|
||||
"name:nl=",
|
||||
"tourism!~viewpoint"
|
||||
]
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"noname=yes",
|
||||
"name="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied heeft geen naam"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"id": "campersite",
|
||||
"title": {
|
||||
"en": "Campersites",
|
||||
"nl": "Kampeersite",
|
||||
"nl": "Camperplaatsen",
|
||||
"it": "Aree camper",
|
||||
"ru": "Кемпинги",
|
||||
"ja": "キャンプサイト",
|
||||
|
@ -304,7 +304,8 @@
|
|||
"zh_Hant": "{capacity} 露營者能夠同時使用這個地方",
|
||||
"fr": "{capacity} personnes peuvent utiliser cet espace en même temps",
|
||||
"pt_BR": "{capacity} campistas podem usar este lugar ao mesmo tempo",
|
||||
"de": "{capacity} Wohnmobile können diesen Platz gleichzeitig nutzen"
|
||||
"de": "{capacity} Wohnmobile können diesen Platz gleichzeitig nutzen",
|
||||
"nl": "{capacity} campers kunnen deze plaats tegelijk gebruiken"
|
||||
},
|
||||
"question": {
|
||||
"en": "How many campers can stay here? (skip if there is no obvious number of spaces or allowed vehicles)",
|
||||
|
@ -314,7 +315,8 @@
|
|||
"zh_Hant": "多少露營者能夠待在這裡?(如果沒有明顯的空間數字或是允許車輛則可以跳過)",
|
||||
"fr": "Combien de personnes peuvent camper ici ? (Passez s’il n’y a pas de places délimitées)",
|
||||
"pt_BR": "Quantos campistas podem ficar aqui? (pule se não houver um número óbvio de vagas ou veículos permitidos)",
|
||||
"de": "Wie viele Wohnmobile können hier parken? (Überspringen, wenn es keine offensichtliche Anzahl von Stellplätzen oder erlaubten Fahrzeugen gibt)"
|
||||
"de": "Wie viele Wohnmobile können hier parken? (Überspringen, wenn es keine offensichtliche Anzahl von Stellplätzen oder erlaubten Fahrzeugen gibt)",
|
||||
"nl": "Hoeveel campers kunnen hier overnachten? (sla dit over als er geen duidelijk aantal plaatsen of aangeduid maximum is)"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "capacity",
|
||||
|
@ -351,7 +353,8 @@
|
|||
"zh_Hant": "這裡有網路連線",
|
||||
"fr": "Il y a un accès internet",
|
||||
"pt_BR": "Há acesso à internet",
|
||||
"de": "Internetzugang ist vorhanden"
|
||||
"de": "Internetzugang ist vorhanden",
|
||||
"nl": "Er is internettoegang"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -370,7 +373,8 @@
|
|||
"zh_Hant": "這裡有網路連線",
|
||||
"fr": "Il y a un accès internet",
|
||||
"pt_BR": "Há acesso à Internet",
|
||||
"de": "Internetzugang ist vorhanden"
|
||||
"de": "Internetzugang ist vorhanden",
|
||||
"nl": "Er is internettoegang"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -609,7 +613,8 @@
|
|||
"it": "Maggiori dettagli su questo luogo: {description}",
|
||||
"fr": "Plus de détails à propos du site : {description}",
|
||||
"pt_BR": "Mais detalhes sobre este lugar: {description}",
|
||||
"de": "Mehr Details über diesen Ort: {description}"
|
||||
"de": "Mehr Details über diesen Ort: {description}",
|
||||
"nl": "Meer details over deze plaats: {description}"
|
||||
},
|
||||
"question": {
|
||||
"en": "Would you like to add a general description of this place? (Do not repeat information previously asked or shown above. Please keep it objective - opinions go into the reviews)",
|
||||
|
@ -618,7 +623,8 @@
|
|||
"zh_Hant": "你想要為這個地方加一般的敘述嗎?(不要重覆加先前問過或提供的資訊,請保持敘述性-請將意見留在評價)",
|
||||
"it": "Desideri aggiungere una descrizione del luogo? (Non vanno ripetute informazioni già richieste e mostrate precedentemente. Si prega di attenersi a dati oggettivi - le opinioni vanno nelle recensioni)",
|
||||
"fr": "Souhaitez-vous ajouter une description générale du lieu ? (Ne pas répéter les informations précédentes et rester neutre, les opinions vont dans les avis)",
|
||||
"de": "Möchten Sie eine allgemeine Beschreibung für diesen Ort hinzufügen? (Bitte wiederholen Sie keine Informationen, die Sie bereits zuvor angegeben haben. Bitte bleiben Sie objektiv - Meinungen gehen in die Bewertungen ein)"
|
||||
"de": "Möchten Sie eine allgemeine Beschreibung für diesen Ort hinzufügen? (Bitte wiederholen Sie keine Informationen, die Sie bereits zuvor angegeben haben. Bitte bleiben Sie objektiv - Meinungen gehen in die Bewertungen ein)",
|
||||
"nl": "Wil je graag een algemene beschrijving toevoegen van deze plaats? (Herhaal hier niet de antwoorden op de vragen die reeds gesteld zijn. Hou het objectief - je kan je mening geven via een review)"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "description",
|
||||
|
@ -664,7 +670,8 @@
|
|||
"it": "luogo di campeggio",
|
||||
"fr": "Aire de camping",
|
||||
"pt_BR": "local de acampamento",
|
||||
"de": "Wohnmobilstellplatz"
|
||||
"de": "Wohnmobilstellplatz",
|
||||
"nl": "camperplaats"
|
||||
},
|
||||
"description": {
|
||||
"en": "Add a new official camper site. These are designated places to stay overnight with your camper. They might look like a real camping or just look like a parking. They might not be signposted at all, but just be defined in a municipal decision. A regular parking intended for campers where it is not expected to spend the night, is -not- a camper site ",
|
||||
|
@ -672,7 +679,8 @@
|
|||
"ja": "新しい公式キャンプサイトを追加します。お客様のキャンピングカーで一泊する指定の場所です。本物のキャンプのように見えるかもしれないし、単なる駐車場のように見えるかもしれない。それらは全く署名されていないかもしれませんが、自治体の決定で定義されているだけです。夜を過ごすことが予想されないキャンパー向けの通常の駐車場は、キャンプサイトではない ",
|
||||
"it": "Aggiungi una nuova area di sosta ufficiale per camper. Si tratta di aree destinate alla sosta notturna dei camper. Potrebbe trattarsi di luoghi di campeggio o semplici parcheggi. Potrebbero anche non essere segnalati sul posto, ma semplicemente indicati in una delibera comunale. Un parcheggio destinato ai camper in cui non è però consentito trascorrere la notte -non- va considerato un'area di sosta per camper. ",
|
||||
"fr": "Ajouter une nouvelle aire de camping officielle, destinée à y passer la nuit avec un camping-car. Elle ne nécessite pas d’infrastructures particulières et peut être simplement désignée sous arrêté municipal, un simple parking ne suffit pas à rentrer dans cette catégorie ",
|
||||
"de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem übernachten nicht zulässig ist, ist kein Wohnmobilstellplatz. "
|
||||
"de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem Übernachten nicht zulässig ist, ist kein Wohnmobilstellplatz. ",
|
||||
"nl": "Voeg een nieuwe officiële camperplaats toe. Dit zijn speciaal aangeduide plaatsen waar het toegestaan is om te overnachten met een camper. Ze kunnen er uitzien als een parking, of soms eerder als een camping. Soms staan ze niet ter plaatse aangeduid, maar heeft de gemeente wel degelijk beslist dat dit een camperplaats is. Een parking voor campers waar je niet mag overnachten is géén camperplaats. "
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1078,66 +1086,70 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"roamingRenderings": [
|
||||
{
|
||||
"render": {
|
||||
"en": "This place is operated by {operator}",
|
||||
"ja": "この場所は{operator}によって運営されます",
|
||||
"it": "Questo luogo è gestito da {operator}",
|
||||
"fr": "Ce site est exploité par {operator}",
|
||||
"de": "Dieser Ort wird betrieben von {operator}"
|
||||
},
|
||||
"question": {
|
||||
"en": "Who operates this place?",
|
||||
"ja": "この店は誰が経営しているんですか?",
|
||||
"it": "Chi gestisce questo luogo?",
|
||||
"fr": "Qui est l’exploitant du site ?",
|
||||
"de": "Wer betreibt diesen Ort?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
}
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Does this place have a power supply?",
|
||||
"ja": "この場所に電源はありますか?",
|
||||
"it": "Questo luogo fornisce corrente elettrica?",
|
||||
"fr": "Ce site a-t’il une source d’électricité ?",
|
||||
"de": "Hat dieser Ort eine Stromversorgung?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"power_supply=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This place has a power supply",
|
||||
"id": "Tempat ini memiliki catu daya",
|
||||
"ja": "この場所には電源があります",
|
||||
"it": "Questo luogo fornisce corrente elettrica",
|
||||
"fr": "Ce site a une source d’alimentation",
|
||||
"de": "Dieser Ort hat eine Stromversorgung"
|
||||
}
|
||||
"overrideAll": {
|
||||
"tagRenderings+": [
|
||||
{
|
||||
"id": "operator",
|
||||
"render": {
|
||||
"en": "This place is operated by {operator}",
|
||||
"ja": "この場所は{operator}によって運営されます",
|
||||
"it": "Questo luogo è gestito da {operator}",
|
||||
"fr": "Ce site est exploité par {operator}",
|
||||
"de": "Dieser Ort wird betrieben von {operator}"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"power_supply=no"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This place does not have power supply",
|
||||
"id": "Tempat ini tidak memiliki sumber listrik",
|
||||
"ja": "この場所には電源がありません",
|
||||
"it": "Questo luogo non fornisce corrente elettrica",
|
||||
"fr": "Ce site n’a pas de source d’alimentation",
|
||||
"de": "Dieser Ort hat keine Stromversorgung"
|
||||
}
|
||||
"question": {
|
||||
"en": "Who operates this place?",
|
||||
"ja": "この店は誰が経営しているんですか?",
|
||||
"it": "Chi gestisce questo luogo?",
|
||||
"fr": "Qui est l’exploitant du site ?",
|
||||
"de": "Wer betreibt diesen Ort?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "operator"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "power_supply",
|
||||
"question": {
|
||||
"en": "Does this place have a power supply?",
|
||||
"ja": "この場所に電源はありますか?",
|
||||
"it": "Questo luogo fornisce corrente elettrica?",
|
||||
"fr": "Ce site a-t’il une source d’électricité ?",
|
||||
"de": "Hat dieser Ort eine Stromversorgung?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"power_supply=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This place has a power supply",
|
||||
"id": "Tempat ini memiliki catu daya",
|
||||
"ja": "この場所には電源があります",
|
||||
"it": "Questo luogo fornisce corrente elettrica",
|
||||
"fr": "Ce site a une source d’alimentation",
|
||||
"de": "Dieser Ort hat eine Stromversorgung"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"power_supply=no"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"en": "This place does not have power supply",
|
||||
"id": "Tempat ini tidak memiliki sumber listrik",
|
||||
"ja": "この場所には電源がありません",
|
||||
"it": "Questo luogo non fornisce corrente elettrica",
|
||||
"fr": "Ce site n’a pas de source d’alimentation",
|
||||
"de": "Dieser Ort hat keine Stromversorgung"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -46,6 +46,5 @@
|
|||
"defaultBackgroundId": "CartoDB.Voyager",
|
||||
"layers": [
|
||||
"charging_station"
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -43,105 +43,6 @@
|
|||
"maxZoom": 12,
|
||||
"minNeededElements": 200
|
||||
},
|
||||
"roamingRenderings": [
|
||||
{
|
||||
"question": {
|
||||
"nl": "Is deze straat een fietsstraat?",
|
||||
"en": "Is this street a cyclestreet?",
|
||||
"ja": "この通りはcyclestreetですか?",
|
||||
"nb_NO": "Er denne gaten en sykkelvei?",
|
||||
"de": "Ist diese Straße eine Fahrradstraße?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=yes",
|
||||
"maxspeed=30",
|
||||
"overtaking:motor_vehicle=no",
|
||||
"proposed:cyclestreet="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat is een fietsstraat (en dus zone 30)",
|
||||
"en": "This street is a cyclestreet (and has a speed limit of 30 km/h)",
|
||||
"ja": "cyclestreet(最高速度は30km/h)",
|
||||
"nb_NO": "Denne gaten er en sykkelvei (og har en fartsgrense på 30 km/t)",
|
||||
"de": "Diese Straße ist eine Fahrradstraße (mit einer Geschwindigkeitsbegrenzung von 30 km/h)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=yes",
|
||||
"proposed:cyclestreet="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat i een fietsstraat",
|
||||
"en": "This street is a cyclestreet",
|
||||
"ja": "この通りはcyclestreetだ",
|
||||
"nb_NO": "Denne gaten er en sykkelvei",
|
||||
"de": "Diese Straße ist eine Fahrradstraße"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=",
|
||||
"proposed:cyclestreet=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat wordt binnenkort een fietsstraat",
|
||||
"en": "This street will become a cyclstreet soon",
|
||||
"ja": "この通りはまもなくcyclstreetになるだろう",
|
||||
"nb_NO": "Denne gaten vil bli sykkelvei ganske snart",
|
||||
"de": "Diese Straße wird bald eine Fahrradstraße sein"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=",
|
||||
"proposed:cyclestreet=",
|
||||
"overtaking:motor_vehicle="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat is geen fietsstraat",
|
||||
"en": "This street is not a cyclestreet",
|
||||
"ja": "この通りはcyclestreetではない",
|
||||
"nb_NO": "Denne gaten er ikke en sykkelvei",
|
||||
"it": "Questa strada non è una strada ciclabile",
|
||||
"de": "Diese Straße ist keine Fahrradstraße"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"nl": "Wanneer wordt deze straat een fietsstraat?",
|
||||
"en": "When will this street become a cyclestreet?",
|
||||
"ja": "この通りはいつcyclestreetになるんですか?",
|
||||
"it": "Questa strada diventerà una strada ciclabile quando?",
|
||||
"de": "Wann wird diese Straße eine Fahrradstraße?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "Deze straat wordt fietsstraat op {cyclestreet:start_date}",
|
||||
"en": "This street will become a cyclestreet at {cyclestreet:start_date}",
|
||||
"ja": "この通りは{cyclestreet:start_date}に、cyclestreetになります",
|
||||
"it": "Questa strada diventerà una strada ciclabile dal {cyclestreet:start_date}",
|
||||
"de": "Diese Straße wird am {cyclestreet:start_date} zu einer Fahrradstraße"
|
||||
},
|
||||
"condition": "proposed:cyclestreet=yes",
|
||||
"freeform": {
|
||||
"type": "date",
|
||||
"key": "cyclestreet:start_date"
|
||||
}
|
||||
}
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"id": "fietsstraat",
|
||||
|
@ -304,6 +205,107 @@
|
|||
}
|
||||
],
|
||||
"overrideAll": {
|
||||
"allowSplit": true
|
||||
"allowSplit": true,
|
||||
"tagRenderings+": [
|
||||
{
|
||||
"id": "is_cyclestreet",
|
||||
"question": {
|
||||
"nl": "Is deze straat een fietsstraat?",
|
||||
"en": "Is this street a cyclestreet?",
|
||||
"ja": "この通りはcyclestreetですか?",
|
||||
"nb_NO": "Er denne gaten en sykkelvei?",
|
||||
"de": "Ist diese Straße eine Fahrradstraße?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=yes",
|
||||
"maxspeed=30",
|
||||
"overtaking:motor_vehicle=no",
|
||||
"proposed:cyclestreet="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat is een fietsstraat (en dus zone 30)",
|
||||
"en": "This street is a cyclestreet (and has a speed limit of 30 km/h)",
|
||||
"ja": "cyclestreet(最高速度は30km/h)",
|
||||
"nb_NO": "Denne gaten er en sykkelvei (og har en fartsgrense på 30 km/t)",
|
||||
"de": "Diese Straße ist eine Fahrradstraße (mit einer Geschwindigkeitsbegrenzung von 30 km/h)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=yes",
|
||||
"proposed:cyclestreet="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat i een fietsstraat",
|
||||
"en": "This street is a cyclestreet",
|
||||
"ja": "この通りはcyclestreetだ",
|
||||
"nb_NO": "Denne gaten er en sykkelvei",
|
||||
"de": "Diese Straße ist eine Fahrradstraße"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=",
|
||||
"proposed:cyclestreet=yes"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat wordt binnenkort een fietsstraat",
|
||||
"en": "This street will become a cyclstreet soon",
|
||||
"ja": "この通りはまもなくcyclstreetになるだろう",
|
||||
"nb_NO": "Denne gaten vil bli sykkelvei ganske snart",
|
||||
"de": "Diese Straße wird bald eine Fahrradstraße sein"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"cyclestreet=",
|
||||
"proposed:cyclestreet=",
|
||||
"overtaking:motor_vehicle="
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Deze straat is geen fietsstraat",
|
||||
"en": "This street is not a cyclestreet",
|
||||
"ja": "この通りはcyclestreetではない",
|
||||
"nb_NO": "Denne gaten er ikke en sykkelvei",
|
||||
"it": "Questa strada non è una strada ciclabile",
|
||||
"de": "Diese Straße ist keine Fahrradstraße"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "future_cyclestreet",
|
||||
"question": {
|
||||
"nl": "Wanneer wordt deze straat een fietsstraat?",
|
||||
"en": "When will this street become a cyclestreet?",
|
||||
"ja": "この通りはいつcyclestreetになるんですか?",
|
||||
"it": "Questa strada diventerà una strada ciclabile quando?",
|
||||
"de": "Wann wird diese Straße eine Fahrradstraße?"
|
||||
},
|
||||
"render": {
|
||||
"nl": "Deze straat wordt fietsstraat op {cyclestreet:start_date}",
|
||||
"en": "This street will become a cyclestreet at {cyclestreet:start_date}",
|
||||
"ja": "この通りは{cyclestreet:start_date}に、cyclestreetになります",
|
||||
"it": "Questa strada diventerà una strada ciclabile dal {cyclestreet:start_date}",
|
||||
"de": "Diese Straße wird am {cyclestreet:start_date} zu einer Fahrradstraße"
|
||||
},
|
||||
"condition": "proposed:cyclestreet=yes",
|
||||
"freeform": {
|
||||
"type": "date",
|
||||
"key": "cyclestreet:start_date"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
"nl": "Cyclofix - een open kaart voor fietsers",
|
||||
"fr": "Cyclofix - Une carte ouverte pour les cyclistes",
|
||||
"gl": "Cyclofix - Un mapa aberto para os ciclistas",
|
||||
"de": "Cyclofix - eine offene Karte für Radfahrer",
|
||||
"de": "Cyclofix - eine freie Karte für Radfahrer",
|
||||
"ru": "Cyclofix - открытая карта для велосипедистов",
|
||||
"ja": "Cyclofix - サイクリストのためのオープンマップ",
|
||||
"zh_Hant": "單車修正 - 單車騎士的開放地圖",
|
||||
|
@ -16,7 +16,7 @@
|
|||
"nl": "Het doel van deze kaart is om fietsers een gebruiksvriendelijke oplossing te bieden voor het vinden van de juiste infrastructuur voor hun behoeften.<br><br>U kunt uw exacte locatie volgen (enkel mobiel) en in de linkerbenedenhoek categorieën selecteren die voor u relevant zijn. U kunt deze tool ook gebruiken om 'spelden' aan de kaart toe te voegen of te bewerken en meer gegevens te verstrekken door de vragen te beantwoorden.<br><br>Alle wijzigingen die u maakt worden automatisch opgeslagen in de wereldwijde database van OpenStreetMap en kunnen door anderen vrij worden hergebruikt.<br><br>Bekijk voor meer info over cyclofix ook <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
|
||||
"fr": "Le but de cette carte est de présenter aux cyclistes une solution facile à utiliser pour trouver l'infrastructure appropriée à leurs besoins.<br><br>Vous pouvez suivre votre localisation précise (mobile uniquement) et sélectionner les couches qui vous concernent dans le coin inférieur gauche. Vous pouvez également utiliser cet outil pour ajouter ou modifier des épingles (points d'intérêt) sur la carte et fournir plus de données en répondant aux questions.<br><br>Toutes les modifications que vous apportez seront automatiquement enregistrées dans la base de données mondiale d'OpenStreetMap et peuvent être librement réutilisées par d'autres.<br><br>Pour plus d'informations sur le projet cyclofix, rendez-vous sur <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
|
||||
"gl": "O obxectivo deste mapa é amosar ós ciclistas unha solución doada de empregar para atopar a infraestrutura axeitada para as súas necesidades.<br><br>Podes obter a túa localización precisa (só para dispositivos móbiles) e escoller as capas que sexan relevantes para ti na esquina inferior esquerda. Tamén podes empregar esta ferramenta para engadir ou editar puntos de interese ó mapa e fornecer máis datos respondendo as cuestións.<br><br>Todas as modificacións que fagas serán gardadas de xeito automático na base de datos global do OpenStreetMap e outros poderán reutilizalos libremente.<br><br>Para máis información sobre o proxecto cyclofix, vai a <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
|
||||
"de": "Das Ziel dieser Karte ist es, den Radfahrern eine einfach zu benutzende Lösung zu präsentieren, um die geeignete Infrastruktur für ihre Bedürfnisse zu finden.<br><br>Sie können Ihren genauen Standort verfolgen (nur mobil) und in der linken unteren Ecke die für Sie relevanten Ebenen auswählen. Sie können dieses Tool auch verwenden, um Pins (Points of Interest/Interessante Orte) zur Karte hinzuzufügen oder zu bearbeiten und mehr Daten durch Beantwortung der Fragen bereitstellen.<br><br>Alle Änderungen, die Sie vornehmen, werden automatisch in der globalen Datenbank von OpenStreetMap gespeichert und können von anderen frei wiederverwendet werden.<br><br>Weitere Informationen über das Projekt Cyclofix finden Sie unter <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
|
||||
"de": "Mit dieser Karte soll Radfahrern eine einfache Lösung bereitgestellt werden, um die passende Farradinfrastruktur zu finden.<br><br>Sie können Ihren genauen Standort verfolgen (nur mobil) und in der linken unteren Ecke die für Sie relevanten Ebenen auswählen. Sie können dieses Tool auch verwenden, um Pins (Points of Interest/Interessante Orte) zur Karte hinzuzufügen oder zu bearbeiten und mehr Daten durch Beantwortung der Fragen bereitstellen.<br><br>Ihre Änderungen, werden automatisch in der Datenbank von OpenStreetMap gespeichert und können von anderen frei verwendet werden.<br><br>Weitere Informationen über Cyclofix finden Sie unter <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
|
||||
"ja": "このマップの目的は、サイクリストのニーズに適した施設を見つけるための使いやすいソリューションを提供することです。<br><br>正確な位置を追跡し(モバイルのみ)、左下コーナーで関連するレイヤを選択できます。このツールを使用して、マップにピン(注目点)を追加または編集したり、質問に答えることでより多くのデータを提供することもできます。<br><br>変更内容はすべてOpenStreetMapのグローバルデータベースに自動的に保存され、他のユーザーが自由に再利用できます。<br><br>cyclofixプロジェクトの詳細については、 <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a> を参照してください。",
|
||||
"zh_Hant": "這份地圖的目的是為單車騎士能夠輕易顯示滿足他們需求的相關設施。<br><br>你可以追蹤你確切位置 (只有行動版),以及在左下角選擇相關的圖層。你可以使用這工具在地圖新增或編輯釘子,以及透過回答問題來提供更多資訊。<br><br>所有你的變動都會自動存在開放街圖這全球資料圖,並且能被任何人自由取用。<br><br>你可以到 <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a> 閱讀更多資訊。",
|
||||
"it": "Questa mappa offre a chi va in bici una soluzione semplice per trovare tutte le infrastrutture di cui ha bisogno.<br><br>Puoi tracciare la tua posizione esatta (solo su mobile) e selezionare i livelli che ti interessano nell'angolo in basso a sinistra. Puoi anche usare questo strumento per aggiungere o modificare punti di interesse alla mappa e aggiungere nuove informazioni rispendendo alle domande.<br><br>Tutte le modifiche che apporterai saranno automaticamente salvate nel database mondiale di OpenStreetMap e potranno essere liberamente riutilizzate da tutti e tutte.<br><br>Per maggiori informazioni sul progetto ciclofix, visita <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>."
|
||||
|
@ -57,6 +57,5 @@
|
|||
"bike_themed_object",
|
||||
"bike_cleaning",
|
||||
"bike_parking"
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
"ja": "飲料水",
|
||||
"zh_Hant": "飲用水",
|
||||
"it": "Acqua potabile",
|
||||
"de": "Trinkwasser"
|
||||
"de": "Trinkwasserstelle"
|
||||
},
|
||||
"description": {
|
||||
"en": "On this map, publicly accessible drinking water spots are shown and can be easily added",
|
||||
|
@ -18,7 +18,7 @@
|
|||
"zh_Hant": "在這份地圖上,公共可及的飲水點可以顯示出來,也能輕易的增加",
|
||||
"it": "Questa mappa mostra tutti i luoghi in cui è disponibile acqua potabile ed è possibile aggiungerne di nuovi",
|
||||
"ru": "На этой карте показываются и могут быть легко добавлены общедоступные точки питьевой воды",
|
||||
"de": "Auf dieser Karte sind öffentlich zugängliche Trinkwasserstellen eingezeichnet und können leicht hinzugefügt werden"
|
||||
"de": "Eine Karte zum Anzeigen und Bearbeiten öffentlicher Trinkwasserstellen"
|
||||
},
|
||||
"language": [
|
||||
"en",
|
||||
|
@ -40,6 +40,5 @@
|
|||
"widenFactor": 2,
|
||||
"layers": [
|
||||
"drinking_water"
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
"description": {
|
||||
"en": "On this map, you can see what an object is named after. The streets, buildings, ... come from OpenStreetMap which got linked with Wikidata. In the popup, you'll see the Wikipedia article (if it exists) or a wikidata box of what the object is named after. If the object itself has a wikipedia page, that'll be shown too.<br/><br/><b>You can help contribute too!</b>Zoom in enough and <i>all</i> streets will show up. You can click one and a Wikidata-search box will popup. With a few clicks, you can add an etymology link. Note that you need a free OpenStreetMap account to do this.",
|
||||
"nl": "Op deze kaart zie je waar een plaats naar is vernoemd. De straten, gebouwen, ... komen uit OpenStreetMap, waar een link naar Wikidata werd gelegd. In de popup zie je het Wikipedia-artikel van hetgeen naarwaar het vernoemd is of de Wikidata-box.<br/><br/><b>Je kan zelf ook meehelpen!</b>Als je ver inzoomt, krijg je alle straten te zien. Klik je een straat aan, dan krijg je een zoekfunctie waarmee je snel een nieuwe link kan leggen. Je hebt hiervoor een gratis OpenStreetMap account nodig.",
|
||||
"de": "Auf dieser Karte können Sie sehen, nach was ein Objekt benannt ist. Die Straßen, Gebäude, ... stammen von OpenStreetMap, das mit Wikidata verknüpft wurde. Die Informationen stammen aus Wikipedia."
|
||||
"de": "Auf dieser Karte können Sie sehen, wonach ein Objekt benannt ist. Die Straßen, Gebäude, ... stammen von OpenStreetMap, das mit Wikidata verknüpft wurde. In dem Popup sehen Sie den Wikipedia-Artikel (falls vorhanden) oder ein Wikidata-Feld, nach dem das Objekt benannt ist. Wenn das Objekt selbst eine Wikipedia-Seite hat, wird auch diese angezeigt.<br/><br/><b>Sie können auch einen Beitrag leisten!</b>Zoomen Sie genug hinein und <i>alle</i> Straßen werden angezeigt. Wenn Sie auf eine Straße klicken, öffnet sich ein Wikidata-Suchfeld. Mit ein paar Klicks können Sie einen Etymologie-Link hinzufügen. Beachten Sie, dass Sie dazu ein kostenloses OpenStreetMap-Konto benötigen."
|
||||
},
|
||||
"language": [
|
||||
"en",
|
||||
|
@ -28,6 +28,10 @@
|
|||
"startZoom": 1,
|
||||
"widenFactor": 2,
|
||||
"socialImage": "",
|
||||
"clustering": {
|
||||
"maxZoom": 14,
|
||||
"minNeededElements": 250
|
||||
},
|
||||
"layers": [
|
||||
"etymology",
|
||||
{
|
||||
|
@ -36,7 +40,8 @@
|
|||
"id": "streets_without_etymology",
|
||||
"name": {
|
||||
"en": "Streets without etymology information",
|
||||
"nl": "Straten zonder etymologische informatie"
|
||||
"nl": "Straten zonder etymologische informatie",
|
||||
"de": "Straßen ohne Informationen zur Namensherkunft"
|
||||
},
|
||||
"minzoom": 18,
|
||||
"source": {
|
||||
|
@ -56,7 +61,8 @@
|
|||
"id": "parks_and_forests_without_etymology",
|
||||
"name": {
|
||||
"en": "Parks and forests without etymology information",
|
||||
"nl": "Parken en bossen zonder etymologische informatie"
|
||||
"nl": "Parken en bossen zonder etymologische informatie",
|
||||
"de": "Parks und Waldflächen ohne Informationen zur Namensherkunft"
|
||||
},
|
||||
"minzoom": 18,
|
||||
"source": {
|
||||
|
@ -75,5 +81,5 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"hideFromOverview": true
|
||||
"hideFromOverview": false
|
||||
}
|
|
@ -456,6 +456,5 @@
|
|||
],
|
||||
"wayHandling": 1
|
||||
}
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -54,6 +54,5 @@
|
|||
"filter": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -172,6 +172,5 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"roamingRenderings": []
|
||||
]
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
"title": {
|
||||
"en": "Ghost bikes",
|
||||
"nl": "Witte Fietsen",
|
||||
"de": "Geisterrad",
|
||||
"de": "Geisterräder",
|
||||
"ja": "ゴーストバイク",
|
||||
"nb_NO": "Spøkelsessykler",
|
||||
"zh_Hant": "幽靈單車",
|
||||
|
@ -43,7 +43,7 @@
|
|||
"description": {
|
||||
"en": "A <b>ghost bike</b> is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.<br/><br/>On this map, one can see all the ghost bikes which are known by OpenStreetMap. Is a ghost bike missing? Everyone can add or update information here - you only need to have a (free) OpenStreetMap account.",
|
||||
"nl": "Een <b>Witte Fiets</b> of <b>Spookfiets</b> is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat om een fiets die volledig wit is geschilderd en in de buurt van het ongeval werd geinstalleerd.<br/><br/>Op deze kaart zie je alle witte fietsen die door OpenStreetMap gekend zijn. Ontbreekt er een Witte Fiets of wens je informatie aan te passen? Meld je dan aan met een (gratis) OpenStreetMap account.",
|
||||
"de": "Ein <b>Geisterrad</b> ist ein Denkmal für einen Radfahrer, der bei einem Verkehrsunfall ums Leben kam, in Form eines weißen Fahrrades, das dauerhaft in der Nähe des Unfallortes aufgestellt ist.<br/><br/> Auf dieser Karte kann man alle Geisterräder sehen, die OpenStreetMap kennt. Fehlt ein Geisterrad? Jeder kann hier Informationen hinzufügen oder aktualisieren - Sie benötigen lediglich einen (kostenlosen) OpenStreetMap-Account.",
|
||||
"de": "Ein <b>Geisterrad</b> ist ein Denkmal für einen Radfahrer, der bei einem Verkehrsunfall ums Leben kam, in Form eines weißen Fahrrades, das dauerhaft in der Nähe des Unfallortes aufgestellt ist.<br/><br/> Auf dieser Karte kann man alle Geisterräder sehen, die in OpenStreetMap eingetragen sind. Fehlt ein Geisterrad? Jeder kann hier Informationen hinzufügen oder aktualisieren - Sie benötigen lediglich einen (kostenlosen) OpenStreetMap-Account.",
|
||||
"ja": "<b>ゴーストバイク</b>は、交通事故で死亡したサイクリストを記念するもので、事故現場の近くに恒久的に置かれた白い自転車の形をしています。<br/><br/>このマップには、OpenStreetMapで知られているゴーストバイクがすべて表示されます。ゴーストバイクは行方不明ですか?誰でもここで情報の追加や更新ができます。必要なのは(無料の)OpenStreetMapアカウントだけです。",
|
||||
"zh_Hant": "<b>幽靈單車</b>是用來紀念死於交通事故的單車騎士,在事發地點附近放置白色單車。<br/><br/>在這份地圖上面,你可以看到所有在開放街圖已知的幽靈單車。有缺漏的幽靈單車嗎?所有人都可以在這邊新增或是更新資訊-只有你有(免費)開放街圖帳號。",
|
||||
"fr": "Les <b>vélos fantômes</b> sont des mémoriaux pour les cyclistes tuées sur la route, prenant la forme de vélos blancs placés à proximité des faits.<br/><br/>Cette carte indique leur emplacement à partir d’OpenStreetMap. Il est possible de contribuer aux informations ici, sous réserve d’avoir un compte OpenStreetMap (gratuit)."
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
"startLon": 3.231,
|
||||
"startZoom": 14,
|
||||
"widenFactor": 2,
|
||||
"cacheTimeout": 3600,
|
||||
"socialImage": "",
|
||||
"layers": [
|
||||
{
|
||||
|
@ -29,6 +28,7 @@
|
|||
},
|
||||
"minzoom": 12,
|
||||
"source": {
|
||||
"maxCacheAge": 0,
|
||||
"osmTags": {
|
||||
"and": [
|
||||
"fixme~*",
|
||||
|
@ -201,6 +201,5 @@
|
|||
}
|
||||
],
|
||||
"hideFromOverview": true,
|
||||
"roamingRenderings": [],
|
||||
"defaultBackgroundId": "AGIVFlandersGRB"
|
||||
}
|
|
@ -18,7 +18,8 @@
|
|||
"en": "On this map you can find and update hydrants, fire stations, ambulance stations, and extinguishers in your favorite neighborhoods. \n\nYou can track your precise location (mobile only) and select layers that are relevant for you in the bottom left corner. You can also use this tool to add or edit pins (points of interest) to the map and provide additional details by answering available questions. \n\nAll changes you make will automatically be saved in the global database of OpenStreetMap and can be freely re-used by others.",
|
||||
"ja": "このマップでは、お気に入りの近隣にある消火栓、消防署、救急ステーション、消火器を検索して更新できます。\n\n正確な位置を追跡し(モバイルのみ)、左下コーナーで関連するレイヤを選択できます。このツールを使用して、マップにピン(注視点)を追加または編集したり、利用可能な質問に答えることによって追加の詳細を提供することもできます。\n\nすべての変更は自動的にOpenStreetMapのグローバルデータベースに保存され、他のユーザが自由に再利用できます。",
|
||||
"zh_Hant": "在這份地圖上面你可以在你喜愛的社區尋找與更新消防栓、消防隊、急救站與滅火器。\n\n你可以追蹤確切位置 (只有行動版) 以及在左下角選擇與你相關的圖層。你也可以使用這工具新增或編輯地圖上的釘子 (興趣點),以及透過回答一些問題提供額外的資訊。\n\n所有你做出的變動都會自動存到開放街圖這個全球資料庫,而且能自由讓其他人取用。",
|
||||
"fr": "Sur cette carte on trouve et met à jour les bornes incendies, extincteurs, casernes de pompiers et ambulanciers dans son quartier.<br/>Les options en haut à gauche permettent de localiser sa position (sur téléphone) et de filtrer les éléments. Il est possible d’utiliser cet outil pour ajouter et éditer les points d’intérêt de la carte et d’y ajouter des détails en répondant aux questions.<br/>Toutes les modifications sont automatiquement enregistrées dans la base de données OpenStreetMap et peuvent êtres librement réutilisées par d’autres."
|
||||
"fr": "Sur cette carte on trouve et met à jour les bornes incendies, extincteurs, casernes de pompiers et ambulanciers dans son quartier.<br/>Les options en haut à gauche permettent de localiser sa position (sur téléphone) et de filtrer les éléments. Il est possible d’utiliser cet outil pour ajouter et éditer les points d’intérêt de la carte et d’y ajouter des détails en répondant aux questions.<br/>Toutes les modifications sont automatiquement enregistrées dans la base de données OpenStreetMap et peuvent êtres librement réutilisées par d’autres.",
|
||||
"de": "Auf dieser Karte können Sie Hydranten, Feuerwachen, Krankenwagen und Feuerlöscher in Ihren bevorzugten Stadtvierteln finden und aktualisieren. \n\nSie können Ihren genauen Standort verfolgen (nur mobil) und in der unteren linken Ecke die für Sie relevanten Ebenen auswählen. Sie können mit diesem Tool auch Pins (Points of Interest) zur Karte hinzufügen oder bearbeiten und durch die Beantwortung verfügbarer Fragen zusätzliche Angaben machen. \n\nAlle von Ihnen vorgenommenen Änderungen werden automatisch in der globalen Datenbank von OpenStreetMap gespeichert und können von anderen frei weiterverwendet werden."
|
||||
},
|
||||
"language": [
|
||||
"en",
|
||||
|
@ -26,6 +27,7 @@
|
|||
"zh_Hant",
|
||||
"ru",
|
||||
"fr",
|
||||
"de",
|
||||
"nb_NO",
|
||||
"it",
|
||||
"id"
|
||||
|
@ -47,7 +49,8 @@
|
|||
"zh_Hant": "消防栓地圖",
|
||||
"nb_NO": "Kart over brannhydranter",
|
||||
"ru": "Карта пожарных гидрантов",
|
||||
"fr": "Carte des bornes incendie"
|
||||
"fr": "Carte des bornes incendie",
|
||||
"de": "Karte der Hydranten"
|
||||
},
|
||||
"minzoom": 14,
|
||||
"source": {
|
||||
|
@ -63,7 +66,8 @@
|
|||
"ru": "Гидрант",
|
||||
"ja": "消火栓",
|
||||
"nb_NO": "Brannhydrant",
|
||||
"fr": "Bornes incendie"
|
||||
"fr": "Bornes incendie",
|
||||
"de": "Hydrant"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
|
@ -72,7 +76,8 @@
|
|||
"zh_Hant": "顯示消防栓的地圖圖層。",
|
||||
"nb_NO": "Kartlag for å vise brannhydranter.",
|
||||
"ru": "Слой карты, отображающий пожарные гидранты.",
|
||||
"fr": "Couche des bornes incendie."
|
||||
"fr": "Couche des bornes incendie.",
|
||||
"de": "Kartenebene zur Anzeige von Hydranten."
|
||||
},
|
||||
"tagRenderings": [
|
||||
{
|
||||
|
@ -82,14 +87,16 @@
|
|||
"ja": "消火栓の色は何色ですか?",
|
||||
"nb_NO": "Hvilken farge har brannhydranten?",
|
||||
"ru": "Какого цвета гидрант?",
|
||||
"fr": "Quelle est la couleur de la borne ?"
|
||||
"fr": "Quelle est la couleur de la borne ?",
|
||||
"de": "Welche Farbe hat der Hydrant?"
|
||||
},
|
||||
"render": {
|
||||
"en": "The hydrant color is {colour}",
|
||||
"ja": "消火栓の色は{color}です",
|
||||
"nb_NO": "Brannhydranter er {colour}",
|
||||
"ru": "Цвет гидранта {colour}",
|
||||
"fr": "La borne est {colour}"
|
||||
"fr": "La borne est {colour}",
|
||||
"de": "Der Hydrant hat die Farbe {colour}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "colour"
|
||||
|
@ -105,7 +112,8 @@
|
|||
"en": "The hydrant color is unknown.",
|
||||
"ja": "消火栓の色は不明です。",
|
||||
"ru": "Цвет гидранта не определён.",
|
||||
"fr": "La borne est de couleur inconnue."
|
||||
"fr": "La borne est de couleur inconnue.",
|
||||
"de": "Die Farbe des Hydranten ist unbekannt."
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -119,7 +127,8 @@
|
|||
"en": "The hydrant color is yellow.",
|
||||
"ja": "消火栓の色は黄色です。",
|
||||
"ru": "Гидрант жёлтого цвета.",
|
||||
"fr": "La borne est jaune."
|
||||
"fr": "La borne est jaune.",
|
||||
"de": "Die Farbe des Hydranten ist gelb."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -133,7 +142,8 @@
|
|||
"ja": "消火栓の色は赤です。",
|
||||
"it": "L'idrante è rosso.",
|
||||
"ru": "Гидрант красного цвета.",
|
||||
"fr": "La borne est rouge."
|
||||
"fr": "La borne est rouge.",
|
||||
"de": "Die Farbe des Hydranten ist rot."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -145,7 +155,8 @@
|
|||
"ja": "どんな消火栓なんですか?",
|
||||
"it": "Di che tipo è questo idrante?",
|
||||
"ru": "К какому типу относится этот гидрант?",
|
||||
"fr": "De quel type de borne s’agit-il ?"
|
||||
"fr": "De quel type de borne s’agit-il ?",
|
||||
"de": "Um welche Art von Hydrant handelt es sich?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "fire_hydrant:type"
|
||||
|
@ -155,7 +166,8 @@
|
|||
"ru": " Тип гидранта: {fire_hydrant:type}",
|
||||
"ja": " 消火栓のタイプ:{fire_hydrant:type}",
|
||||
"it": " Tipo di idrante: {fire_hydrant:type}",
|
||||
"fr": " Type de borne : {fire_hydrant:type}"
|
||||
"fr": " Type de borne : {fire_hydrant:type}",
|
||||
"de": " Hydranten-Typ: {fire_hydrant:type}"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -169,7 +181,8 @@
|
|||
"ja": "消火栓の種類は不明です。",
|
||||
"it": "Il tipo di idrante è sconosciuto.",
|
||||
"ru": "Тип гидранта не определён.",
|
||||
"fr": "La borne est de type inconnu."
|
||||
"fr": "La borne est de type inconnu.",
|
||||
"de": "Der Typ des Hydranten ist unbekannt."
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
|
@ -182,7 +195,8 @@
|
|||
"then": {
|
||||
"en": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_pillar.svg\" /> Pillar type.",
|
||||
"ja": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_pillar.svg\" /> ピラー型。",
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_pillar.svg\" /> Pilier."
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_pillar.svg\" /> Pilier.",
|
||||
"de": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_pillar.svg\" /> Säulenart."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -194,7 +208,8 @@
|
|||
"then": {
|
||||
"en": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Pipe type.",
|
||||
"ja": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> パイプ型。",
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Tuyau."
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Tuyau.",
|
||||
"de": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Rohrtyp."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -208,7 +223,8 @@
|
|||
"id": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Jenis dinding.",
|
||||
"ru": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Тип стены.",
|
||||
"ja": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> 壁型。",
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Mural."
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Mural.",
|
||||
"de": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_unknown.svg\" /> Wandtyp."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -220,7 +236,8 @@
|
|||
"then": {
|
||||
"en": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_underground.svg\" /> Underground type.",
|
||||
"ja": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_underground.svg\" />地下式。",
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_underground.svg\" /> Enterré."
|
||||
"fr": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_underground.svg\" /> Enterré.",
|
||||
"de": "<img style=\"width:15px\" src=\"./assets/themes/hailhydrant/hydrant_underground.svg\" /> Untergrundtyp."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -230,12 +247,14 @@
|
|||
"question": {
|
||||
"en": "Update the lifecycle status of the hydrant.",
|
||||
"ja": "消火栓のライフサイクルステータスを更新します。",
|
||||
"fr": "Mettre à jour l’état de la borne."
|
||||
"fr": "Mettre à jour l’état de la borne.",
|
||||
"de": "Aktualisieren Sie den Lebenszyklusstatus des Hydranten."
|
||||
},
|
||||
"render": {
|
||||
"en": "Lifecycle status",
|
||||
"ja": "ライフサイクルステータス",
|
||||
"fr": "État"
|
||||
"fr": "État",
|
||||
"de": "Lebenszyklus-Status"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "disused:emergency"
|
||||
|
@ -251,7 +270,8 @@
|
|||
"en": "The hydrant is (fully or partially) working.",
|
||||
"ja": "消火栓は(完全にまたは部分的に)機能しています。",
|
||||
"ru": "Гидрант (полностью или частично) в рабочем состоянии.",
|
||||
"fr": "La borne est en état, ou partiellement en état, de fonctionner."
|
||||
"fr": "La borne est en état, ou partiellement en état, de fonctionner.",
|
||||
"de": "Der Hydrant ist (ganz oder teilweise) in Betrieb."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -264,7 +284,8 @@
|
|||
"then": {
|
||||
"en": "The hydrant is unavailable.",
|
||||
"ja": "消火栓は使用できません。",
|
||||
"fr": "La borne est hors-service."
|
||||
"fr": "La borne est hors-service.",
|
||||
"de": "Der Hydrant ist nicht verfügbar."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -278,7 +299,8 @@
|
|||
"en": "The hydrant has been removed.",
|
||||
"ja": "消火栓が撤去されました。",
|
||||
"ru": "Гидрант демонтирован.",
|
||||
"fr": "La borne a été retirée."
|
||||
"fr": "La borne a été retirée.",
|
||||
"de": "Der Hydrant wurde entfernt."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -307,12 +329,14 @@
|
|||
"ru": "Пожарный гидрант",
|
||||
"ja": "消火栓",
|
||||
"nb_NO": "Brannhydrant",
|
||||
"fr": "Borne incendie"
|
||||
"fr": "Borne incendie",
|
||||
"de": "Löschwasser-Hydrant"
|
||||
},
|
||||
"description": {
|
||||
"en": "A hydrant is a connection point where firefighters can tap water. It might be located underground.",
|
||||
"ja": "消火栓は消防士が水を汲み上げることができる接続点です。地下にあるかもしれません。",
|
||||
"fr": "Une borne incendie est un point où les pompiers peuvent s’alimenter en eau. Elle peut être enterrée."
|
||||
"fr": "Une borne incendie est un point où les pompiers peuvent s’alimenter en eau. Elle peut être enterrée.",
|
||||
"de": "Ein Hydrant ist ein Anschlusspunkt, an dem die Feuerwehr Wasser zapfen kann. Er kann sich unterirdisch befinden."
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -325,7 +349,8 @@
|
|||
"ja": "消火器の地図です。",
|
||||
"nb_NO": "Kart over brannhydranter",
|
||||
"ru": "Карта огнетушителей.",
|
||||
"fr": "Couche des extincteurs."
|
||||
"fr": "Couche des extincteurs.",
|
||||
"de": "Karte mit Feuerlöschern."
|
||||
},
|
||||
"minzoom": 14,
|
||||
"source": {
|
||||
|
@ -341,7 +366,8 @@
|
|||
"ru": "Огнетушители",
|
||||
"ja": "消火器",
|
||||
"nb_NO": "Brannslokkere",
|
||||
"fr": "Exctincteurs"
|
||||
"fr": "Exctincteurs",
|
||||
"de": "Feuerlöscher"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
|
@ -350,7 +376,8 @@
|
|||
"zh_Hant": "顯示消防栓的地圖圖層。",
|
||||
"nb_NO": "Kartlag for å vise brannslokkere.",
|
||||
"ru": "Слой карты, отображающий огнетушители.",
|
||||
"fr": "Couche des lances à incendie."
|
||||
"fr": "Couche des lances à incendie.",
|
||||
"de": "Kartenebene zur Anzeige von Hydranten."
|
||||
},
|
||||
"tagRenderings": [
|
||||
{
|
||||
|
@ -359,13 +386,15 @@
|
|||
"en": "Location: {location}",
|
||||
"ja": "場所:{location}",
|
||||
"ru": "Местоположение: {location}",
|
||||
"fr": "Emplacement : {location}"
|
||||
"fr": "Emplacement : {location}",
|
||||
"de": "Standort: {location}"
|
||||
},
|
||||
"question": {
|
||||
"en": "Where is it positioned?",
|
||||
"ja": "どこにあるんですか?",
|
||||
"ru": "Где это расположено?",
|
||||
"fr": "Où est-elle positionnée ?"
|
||||
"fr": "Où est-elle positionnée ?",
|
||||
"de": "Wo befindet er sich?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
|
@ -378,7 +407,8 @@
|
|||
"en": "Found indoors.",
|
||||
"ja": "屋内にある。",
|
||||
"ru": "Внутри.",
|
||||
"fr": "Intérieur."
|
||||
"fr": "Intérieur.",
|
||||
"de": "Im Innenraum vorhanden."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -391,7 +421,8 @@
|
|||
"en": "Found outdoors.",
|
||||
"ja": "屋外にある。",
|
||||
"ru": "Снаружи.",
|
||||
"fr": "Extérieur."
|
||||
"fr": "Extérieur.",
|
||||
"de": "Im Außenraum vorhanden."
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -423,13 +454,15 @@
|
|||
"ja": "消火器",
|
||||
"nb_NO": "Brannslukker",
|
||||
"ru": "Огнетушитель",
|
||||
"fr": "Extincteur"
|
||||
"fr": "Extincteur",
|
||||
"de": "Feuerlöscher"
|
||||
},
|
||||
"description": {
|
||||
"en": "A fire extinguisher is a small, portable device used to stop a fire",
|
||||
"ja": "消火器は、火災を止めるために使用される小型で携帯可能な装置である",
|
||||
"ru": "Огнетушитель - небольшое переносное устройство для тушения огня",
|
||||
"fr": "Un extincteur est un appareil portatif servant à éteindre un feu"
|
||||
"fr": "Un extincteur est un appareil portatif servant à éteindre un feu",
|
||||
"de": "Ein Feuerlöscher ist ein kleines, tragbares Gerät, das dazu dient, ein Feuer zu löschen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -443,7 +476,8 @@
|
|||
"nb_NO": "Kart over brannstasjoner",
|
||||
"it": "Mappa delle caserme dei vigili del fuoco",
|
||||
"ru": "Карта пожарных частей",
|
||||
"fr": "Couche des stations de pompiers"
|
||||
"fr": "Couche des stations de pompiers",
|
||||
"de": "Karte der Feuerwachen"
|
||||
},
|
||||
"minzoom": 12,
|
||||
"source": {
|
||||
|
@ -461,7 +495,8 @@
|
|||
"ru": "Пожарная часть",
|
||||
"nb_NO": "Brannstasjon",
|
||||
"it": "Caserma dei vigili del fuoco",
|
||||
"fr": "Station de pompiers"
|
||||
"fr": "Station de pompiers",
|
||||
"de": "Feuerwache"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
|
@ -469,7 +504,8 @@
|
|||
"ja": "消防署を表示するためのマップレイヤ。",
|
||||
"it": "Livello che mostra le caserme dei vigili del fuoco.",
|
||||
"ru": "Слой карты, отображающий пожарные части.",
|
||||
"fr": "Couche des stations de pompiers."
|
||||
"fr": "Couche des stations de pompiers.",
|
||||
"de": "Kartenebene zur Darstellung von Feuerwachen."
|
||||
},
|
||||
"tagRenderings": [
|
||||
{
|
||||
|
@ -482,7 +518,8 @@
|
|||
"ja": "この消防署の名前は何ですか?",
|
||||
"ru": "Как называется эта пожарная часть?",
|
||||
"it": "Come si chiama questa caserma dei vigili del fuoco?",
|
||||
"fr": "Quel est le nom de la station ?"
|
||||
"fr": "Quel est le nom de la station ?",
|
||||
"de": "Wie lautet der Name dieser Feuerwache?"
|
||||
},
|
||||
"render": {
|
||||
"en": "This station is called {name}.",
|
||||
|
@ -649,12 +686,14 @@
|
|||
"en": "Fire station",
|
||||
"ja": "消防署",
|
||||
"ru": "Пожарная часть",
|
||||
"fr": "Caserne de pompiers"
|
||||
"fr": "Caserne de pompiers",
|
||||
"de": "Feuerwache"
|
||||
},
|
||||
"description": {
|
||||
"en": "A fire station is a place where the fire trucks and firefighters are located when not in operation.",
|
||||
"ja": "消防署は、運転していないときに消防車や消防士がいる場所です。",
|
||||
"fr": "Une caserne de pompiers est un lieu où les pompiers et leur équipements sont situés en dehors des missions."
|
||||
"fr": "Une caserne de pompiers est un lieu où les pompiers et leur équipements sont situés en dehors des missions.",
|
||||
"de": "Eine Feuerwache ist ein Ort, an dem die Feuerwehrfahrzeuge und die Feuerwehrleute untergebracht sind, wenn sie nicht im Einsatz sind."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -854,7 +893,8 @@
|
|||
"en": "Add an ambulance station to the map",
|
||||
"ja": "救急ステーション(消防署)をマップに追加する",
|
||||
"ru": "Добавить станцию скорой помощи на карту",
|
||||
"fr": "Ajouter une station d’ambulances à la carte"
|
||||
"fr": "Ajouter une station d’ambulances à la carte",
|
||||
"de": "Eine Rettungsstation der Karte hinzufügen"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue